<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Phil Hardwick</title>
    <description>The latest articles on Forem by Phil Hardwick (@philhardwick).</description>
    <link>https://forem.com/philhardwick</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F154670%2Fb1368741-91eb-45a2-b227-1615af8915bc.JPG</url>
      <title>Forem: Phil Hardwick</title>
      <link>https://forem.com/philhardwick</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/philhardwick"/>
    <language>en</language>
    <item>
      <title>A Java Library Release Process Which Doesn't Suck</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 07 Aug 2020 05:15:39 +0000</pubDate>
      <link>https://forem.com/philhardwick/a-java-library-release-process-which-doesn-t-suck-4lb3</link>
      <guid>https://forem.com/philhardwick/a-java-library-release-process-which-doesn-t-suck-4lb3</guid>
      <description>&lt;p&gt;Everytime I read about &lt;a href="http://maven.apache.org/maven-release/maven-release-plugin/"&gt;Maven’s release process&lt;/a&gt; it makes me groan. There must be a better way than this. Something less manual, with less commits and less steps, right?&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;I had some strict requirements for this release process:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;no multiple commits&lt;/li&gt;
&lt;li&gt;no commits by CI&lt;/li&gt;
&lt;li&gt;should build snapshot versions when someone is building locally&lt;/li&gt;
&lt;li&gt;should build snapshot versions as a default when building in CI so not every push to master is a “release”&lt;/li&gt;
&lt;li&gt;versioning should be by &lt;a href="https://semver.org"&gt;semver&lt;/a&gt;, and shouldn’t include build numbers&lt;/li&gt;
&lt;li&gt;shoudn’t be tied to the CI choice (i.e. no CircleCI specific release)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  New solution
&lt;/h2&gt;

&lt;p&gt;The best, simplest way of releasing Java apps I’ve found is via git tags and &lt;a href="https://github.com/ilovemilk/semver-git-plugin"&gt;a lesser known Gradle plugin&lt;/a&gt; I’ve recently discovered, so I’ll show you how I’m now releasing Java libraries without the pain.&lt;/p&gt;

&lt;h2&gt;
  
  
  How it works
&lt;/h2&gt;

&lt;p&gt;The current version of the project is determined by the most recent git tag on the branch. So if the last tag was &lt;code&gt;0.0.5&lt;/code&gt;, 2 commits ago, and you’ve configured the plugin to increment the patch version, it’ll be &lt;code&gt;0.0.6-SNAPSHOT&lt;/code&gt;. If you merge that commit to master, CI will also build &lt;code&gt;0.0.6-SNAPSHOT&lt;/code&gt; and publish it to your Maven repo so others can try it out. If you want to release that commit as a new version, just tag the commit with the version you want e.g. &lt;code&gt;0.0.6&lt;/code&gt;. CI will pick up the new git tag and re-build. It will see that the current commit has a semantically versioned tag and it will use that as the version of the project. You can also tag it with any version number e.g. &lt;code&gt;0.1.0&lt;/code&gt; or &lt;code&gt;1.0.0&lt;/code&gt;. This keeps the developer in control of how the versions increment.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to add it to a project
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1. Add the semver git plugin
&lt;/h3&gt;



&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;plugins {
    id "io.wusa.semver-git-plugin" version "2.2.1"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Configure the plugin
&lt;/h3&gt;

&lt;p&gt;This is the simple configuration I decided on: that all branches behave the same way (incrementing the patch version when a tag isn’t on the current commit) and that the version is just &lt;code&gt;major.minor.patch&lt;/code&gt; with a possible &lt;code&gt;-SNAPSHOT&lt;/code&gt; suffix. More options are available as shown in the plugin &lt;a href="https://github.com/ilovemilk/semver-git-plugin"&gt;README.md&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;semver {
    snapshotSuffix = "SNAPSHOT"
    initialVersion = "0.0.1"
    branches {
        branch {
            regex = ".+"
            incrementer = "PATCH_INCREMENTER"
            formatter = { "${semver.info.version.major}.${semver.info.version.minor}.${semver.info.version.patch}" }
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Use the version
&lt;/h3&gt;

&lt;p&gt;Assign the version calculated by the plugin to the version of the project. I explicitly call &lt;code&gt;.toString()&lt;/code&gt; here so it’s only evaluated once. If you have a multimodule build, the version will be evaluated for each subproject and the &lt;code&gt;.toString()&lt;/code&gt; method will be called each time (which is where all the git commands and tag searching happens).&lt;/p&gt;

&lt;p&gt;I also find it very useful to output the version being built for visibility.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = semver.info.toString()
println "Building version $version of $rootProject.name"
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Set up your CI to build when a new tag appears
&lt;/h3&gt;

&lt;p&gt;This will be different based on what CI you use, but in Concourse I added a new git resource with a &lt;code&gt;tag_filter: *.*.*&lt;/code&gt; and then added a new input to the build job which will also trigger the job:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;resources:
- name: commons-utils.git-release-tags
  type: git
  check_every: 2m
  source:
    uri: git@github.com:PhilHardwick/commons-utils.git
    branch: master
    private_key: #private key config
    fetch_tags: true
    # only detect a new version when tag matches the semver pattern
    tag_filter: "*.*.*"

jobs:
  - name: build-commons-utils
    plan:
      - get: commons-utils.git
        trigger: true
        params:
          fetch_tags: true
      # use new resource as input and trigger job on new releases
      - get: commons-utils.git-release-tags
        trigger: true
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h3&gt;
  
  
  Github Bonus
&lt;/h3&gt;

&lt;p&gt;As a bonus, if you’re using Github, it will also pick up the tags and show them as releases on your Github repository so developers can easily check the current version.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’m a big fan of this release process since it is simpler than the usual Maven releases process with multiple commits. It’s also not tied to any CI implementation, and it works the same in CI as it does locally.&lt;/p&gt;

&lt;p&gt;What’s next? Still need to find a good way to do release notes! Maybe using conventional commit…&lt;/p&gt;

</description>
      <category>java</category>
      <category>maven</category>
      <category>gradle</category>
      <category>ci</category>
    </item>
    <item>
      <title>Refactoring Branches out of Spring Controllers with Params</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 17 Jul 2020 05:05:31 +0000</pubDate>
      <link>https://forem.com/philhardwick/refactoring-branches-out-of-spring-controllers-with-params-1b55</link>
      <guid>https://forem.com/philhardwick/refactoring-branches-out-of-spring-controllers-with-params-1b55</guid>
      <description>&lt;p&gt;There’s a lesser known way of specifying which method in a &lt;a href="https://spring.io"&gt;Spring&lt;/a&gt; controller should be executed based on the query parameters sent to it.&lt;/p&gt;

&lt;p&gt;Before knowing about this I would have used optional parameters and if statements inside the same handler - which increases complexity and decreases readability. For example, here I’m returning a bank account and there are two ways of searching for one, by &lt;code&gt;nameOnAccount&lt;/code&gt; and by &lt;code&gt;accountNumber&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
@RequestMapping(value = "/accounts")
public class AccountController {
    private AccountService accountService;

    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }

    @RequestMapping(method = GET)
    public ResponseEntity&amp;lt;AccountResource&amp;gt; searchForAccount(
            @RequestParam(value = "accountNumber", required = false) String accountNumber,
            @RequestParam(value = "nameOnAccount", required = false) String nameOnAccount) {
        // both params are optional so I need to manually check if neither or both exist
        if ((isBlank(accountNumber) &amp;amp;&amp;amp; isBlank(nameOnAccount))
                || isNotBlank(accountNumber) &amp;amp;&amp;amp; isNotBlank(nameOnAccount)) {
            // Returns a bad request
            throw new AccountSearchException(
                "Must provide either account number or name on account only.");
        }

        if (isNotBlank(accountNumber)) {
            return accountService.getAccountByAccountNumber(accountNumber);
        } else {
            return accountService.getAccountByNameOnAccount(nameOnAccount);
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The above method has more if statements than necessary for a simple handler which makes it difficult to read. We can make it simpler by using the params field in the &lt;code&gt;@RequestMapping&lt;/code&gt; annotation.&lt;/p&gt;

&lt;p&gt;You can provide an array of strings in the params field of the &lt;code&gt;@RequestMapping&lt;/code&gt;. This field can specify whether the request query parameters should have a specific value e.g. &lt;code&gt;params = "accountNumber=12345678"&lt;/code&gt; or not have a specific value e.g. &lt;code&gt;params = "accountNumber!=12345678"&lt;/code&gt; or whether it should have the query parameter present with any value e.g. &lt;code&gt;params = "accountNumber"&lt;/code&gt; or not present e.g. &lt;code&gt;params = "!accountNumber"&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The example below shows how you can simplify the above code and still provide the same functionality. The other possible parameter needs to be negated so that if someone provides both query parameters they get a 400 status code back, just as they did before from the &lt;code&gt;AccountSearchException&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@RestController
@RequestMapping(value = "/accounts")
public class AccountController {
    private AccountService accountService;

    public AccountController(AccountService accountService) {
        this.accountService = accountService;
    }

    @RequestMapping(method = GET, params = {"accountNumber", "!nameOnAccount" })
    public ResponseEntity&amp;lt;AccountResource&amp;gt; getAccountByAccountNumber(
            @RequestParam(value = "accountNumber") String accountNumber) {
        return accountService.getAccountByAccountNumber(accountNumber);
    }

    @RequestMapping(method = GET, params = {"nameOnAccount", "!accountNumber"})
    public ResponseEntity&amp;lt;AccountResource&amp;gt; getAccountByNameOnAccount(
            @RequestParam(value = "nameOnAccount") String nameOnAccount) {
        return accountService.getAccountByNameOnAccount(nameOnAccount);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;By using the params field we’ve been able to get rid of a number of branches in our code whilst still having handlers attached to the same url mapping.&lt;/p&gt;

</description>
      <category>spring</category>
      <category>java</category>
    </item>
    <item>
      <title>Paging a http endpoint by recursion</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 10 Jul 2020 22:45:12 +0000</pubDate>
      <link>https://forem.com/philhardwick/paging-a-http-endpoint-by-recursion-3ddk</link>
      <guid>https://forem.com/philhardwick/paging-a-http-endpoint-by-recursion-3ddk</guid>
      <description>&lt;p&gt;Paging the results of REST API calls is a good opportunity to show recursion and how it differs from just using loops.&lt;/p&gt;

&lt;p&gt;Recursion requires 3 things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a stop condition (also called a base case)&lt;/li&gt;
&lt;li&gt;an accumulator (some number or value which changes) which is used as input into the stop condition&lt;/li&gt;
&lt;li&gt;a method which can be called with the accumulator&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Here’s an example where the goal is to get REST resources from a HTTP API. We have a &lt;code&gt;client&lt;/code&gt; which has a method &lt;code&gt;get(int offset, int limit)&lt;/code&gt; which gets the resource from the API and returns a Java object representation of the response. Here’s how to use that client recursively:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;Object&amp;gt; getResources() {
    List&amp;lt;Object&amp;gt; resources = new ArrayList();
    return retrievePagedResource(resources, 0);
}

private List&amp;lt;Object&amp;gt; retrievePagedResource(List&amp;lt;Object&amp;gt; resources, int offset) {
    ResourceResponse response = client.get(offset, limit);
    resources.addAll(response.getItems());
    if (response.getTotal &amp;gt; limit + offset) {
        retrievePagedResource(resources, limit + offset);
    }    
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Let’s see how the above implementation of paging satisfies the requirements for recursion. The stop condition is in the implicit else of the if statement - recursion will stop when total results are less than or equal to the limit plus offset. We use the combination of the limit and offset as the accumulator and we use it as an input in the stop condition. Because the original method takes no method arguments we need a second method which takes the accumulator as an argument. This second method can then be called from the original function with a default value, 0, indicating we want to start paging from the 0th item in the available resources.&lt;/p&gt;

&lt;p&gt;Using loops, this same example would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public List&amp;lt;Object&amp;gt; getResources() {
    int limit = 50;
    int offset = 0;
    int totalResults;
    List&amp;lt;Object&amp;gt; resources = new ArrayList();
    ResourceResponse response = client.get(offset, limit);
    resources.addAll(response.getItems());
    totalResults = response.getTotal;
    while (totalResults &amp;gt; limit + offset) {
        offset = offset + limit;
        ResourceResponse response = client.get(offset, limit);
        resources.addAll(response.getItems());
    }
    return resources;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;There are some clear differences - the loop implementation relies heavily on modifying variables and so since the variables are always changing it’s harder to reason about. The recursive example can be made purer by not adding items to an existing list but creating a new list every time which is concatenated with another list.&lt;/p&gt;

&lt;p&gt;When paging, be wary of storing every object in-memory, in case there’s a lot of objects. If you are filtering the returned list, it is best to filter as each page comes in rather than gather a huge list and filter after everything has been returned.&lt;/p&gt;

</description>
      <category>java</category>
      <category>http</category>
      <category>recursion</category>
    </item>
    <item>
      <title>Changing Bootstrap Theme at Runtime with CSS Variables</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 03 Jul 2020 06:40:59 +0000</pubDate>
      <link>https://forem.com/philhardwick/changing-bootstrap-theme-at-runtime-with-css-variables-3jm1</link>
      <guid>https://forem.com/philhardwick/changing-bootstrap-theme-at-runtime-with-css-variables-3jm1</guid>
      <description>&lt;p&gt;&lt;a href="https://getbootstrap.com"&gt;Bootstrap&lt;/a&gt; is a well-known framework for quickly building websites and apps. The way to customise it is well documented - override the &lt;a href="https://sass-lang.com/"&gt;SASS&lt;/a&gt; variables which are provided. This allows customisation at compile-time - if you know your colours and branding when you develop the app. However, what if you want to change the theme of your Bootstrap components at runtime? For example, maybe you want to allow choice between a light or dark theme, or, as in my case, you have multiple tenants visiting your site, each with their own branding.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Requirements
&lt;/h2&gt;

&lt;p&gt;The first requirement is that the tenant branding should be stored in the app database, so it can be changed easily. Secondly I don’t want to have to redeploy the app when a new tenant is added. So that excludes adding a new a CSS file for every tenant. Dynamic theming is possible with &lt;a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Using_CSS_custom_properties"&gt;CSS custom properties&lt;/a&gt; (CSS variables). You can change the values of the CSS variables in Javascript, and they will apply to the browser immediately. So, is this possible in Bootstrap?&lt;/p&gt;

&lt;h2&gt;
  
  
  CSS Variables Solution
&lt;/h2&gt;

&lt;p&gt;I stumbled across the possibility of dynamic theming in an &lt;a href="https://github.com/twbs/bootstrap/issues/26596"&gt;issue thread&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Top tip, don’t just search google for blog posts when you need ideas. Search issues in Github for the library you’re using and see if it’s been solved, answered or has a workaround.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The problem with using CSS variables in Bootstrap is that all the SASS colour functions require a colour type input - they can’t handle a string like &lt;code&gt;var(--primary)&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;On this issue, the idea of using CSS variables to change the Bootstrap theme had been dismissed as too much work in the past but had just been reopened. A contributor to the project, &lt;code&gt;johanlef&lt;/code&gt;, &lt;a href="https://github.com/twbs/bootstrap/issues/26596#issuecomment-601380068"&gt;posted an idea&lt;/a&gt; for how to override the SASS functions to enable using hsl values assigned to CSS variables which could then be assigned to SASS variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  Drawbacks
&lt;/h2&gt;

&lt;p&gt;This way of dynamic theming uses the CSS function &lt;code&gt;calc()&lt;/code&gt; which &lt;a href="https://caniuse.com/#feat=calc"&gt;isn’t compatible on IE11&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How I implemented it
&lt;/h2&gt;

&lt;p&gt;Firstly, take &lt;a href="https://gist.github.com/johanlef/518a511b2b2f6b96c4f429b3af2f169a#file-_functions-override-scss"&gt;Johan’s SASS functions&lt;/a&gt; and put them in a file called &lt;code&gt;_functions-override.scss&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Secondly, in &lt;code&gt;_bootstrap-variables.scss&lt;/code&gt;, set your Bootstrap SASS variables to reference CSS variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$primary: var(--primary);

$theme-colors: (
  'primary': var(--primary)
);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;$primary&lt;/code&gt; now references the string &lt;code&gt;var(--primary)&lt;/code&gt;, which can be set at runtime.&lt;/p&gt;

&lt;p&gt;Thirdly, change the order of imports in your main SASS file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// functions and mixins first
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/mixins';

// override bootstrap functions to comply with --vars
@import 'functions-override';

// Override Boostrap variables
@import 'bootstrap-variables';
// add other themes if you want
@import '~bootswatch/dist/sandstone/variables';
// Import Bootstrap source files from node_modules
@import "~bootstrap/scss/variables";
@import "~bootstrap/scss/root";
@import "~bootstrap/scss/reboot";
@import "~bootstrap/scss/type";
@import "~bootstrap/scss/images";
@import "~bootstrap/scss/code";
@import "~bootstrap/scss/grid";
@import "~bootstrap/scss/tables";
@import "~bootstrap/scss/forms";
@import "~bootstrap/scss/buttons";
@import "~bootstrap/scss/transitions";
@import "~bootstrap/scss/dropdown";
@import "~bootstrap/scss/button-group";
@import "~bootstrap/scss/input-group";
@import "~bootstrap/scss/custom-forms";
@import "~bootstrap/scss/nav";
@import "~bootstrap/scss/navbar";
@import "~bootstrap/scss/card";
@import "~bootstrap/scss/breadcrumb";
@import "~bootstrap/scss/pagination";
@import "~bootstrap/scss/badge";
@import "~bootstrap/scss/jumbotron";
@import "~bootstrap/scss/alert";
@import "~bootstrap/scss/progress";
@import "~bootstrap/scss/media";
@import "~bootstrap/scss/list-group";
@import "~bootstrap/scss/close";
@import "~bootstrap/scss/toasts";
@import "~bootstrap/scss/modal";
@import "~bootstrap/scss/tooltip";
@import "~bootstrap/scss/popover";
@import "~bootstrap/scss/carousel";
@import "~bootstrap/scss/spinners";
@import "~bootstrap/scss/utilities";
@import "~bootstrap/scss/print";
//other app specific css below
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;I’ve included all the Bootstrap SASS files above, but you can remove those you don’t need.&lt;/p&gt;

&lt;p&gt;Lastly set the CSS variables based on some app state. I’m using &lt;a href="https://github.com/nfl/react-helmet"&gt;React Helmet&lt;/a&gt; to change the page &lt;code&gt;head&lt;/code&gt; and set the CSS variables in an in-line &lt;code&gt;style&lt;/code&gt;. The below code mostly uses Johan’s code from his gist, with a few tweaks for Typescript and using it with React Helmet. I get my app state from a Redux store but this could just as easily be retrieved from React Context or other state management.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react'
import { connect } from 'react-redux';
import { IRootState } from 'app/shared/reducers';
import { Helmet } from 'react-helmet';
import identity from 'lodash/identity'
import map from 'lodash/map'
import trim from 'lodash/trim'

const printCss = (suffix = '', convert: (string) =&amp;gt; string = identity) =&amp;gt; {
  return (value, property) =&amp;gt; `--${property}${suffix ? '-' + suffix : ''}: ${convert(value)};`
}

const rgbToHsl = (red, green, blue) =&amp;gt; {
  const r = Number(trim(red)) / 255
  const g = Number(trim(green)) / 255
  const b = Number(trim(blue)) / 255

  const max = Math.max(r, g, b)
  const min = Math.min(r, g, b)
  let h,
    s,
    l = (max + min) / 2

  if (max === min) {
    h = s = 0 // achromatic
  } else {
    const d = max - min
    s = l &amp;gt; 0.5 ? d / (2 - max - min) : d / (max + min)
    switch (max) {
      case r:
        h = (g - b) / d + (g &amp;lt; b ? 6 : 0)
        break
      case g:
        h = (b - r) / d + 2
        break
      case b:
        h = (r - g) / d + 4
        break
      default:
        break
    }
    h /= 6
  }

  h = Math.round(360 * h)
  s = Math.round(100 * s)
  l = Math.round(100 * l)

  return [h, s, l]
}

// from @josh3736 | https://stackoverflow.com/a/3732187
const colorToHsl = (color: string): any[] =&amp;gt; {
  if (color.startsWith('#')) {
    if (color.length === 4) {
      const r = parseInt(color.substr(1, 1) + color.substr(1, 1), 16)
      const g = parseInt(color.substr(2, 1) + color.substr(2, 1), 16)
      const b = parseInt(color.substr(3, 1) + color.substr(3, 1), 16)
      return rgbToHsl(r, g, b)
    } else {
      const r = parseInt(color.substr(1, 2), 16)
      const g = parseInt(color.substr(3, 2), 16)
      const b = parseInt(color.substr(5, 2), 16)
      return rgbToHsl(r, g, b)
    }
  } else if (color.startsWith('rgba')) {
    const [r, g, b] = color.slice(5, -1).split(',')
    return rgbToHsl(r, g, b).slice(0, 3)
  } else if (color.startsWith('rgb')) {
    const [r, g, b] = color.slice(4, -1).split(',')
    return rgbToHsl(r, g, b)
  } else if (color.startsWith('hsla')) {
    return color.slice(5, -1).split(',').slice(0, 3)
  } else if (color.startsWith('hsl')) {
    return color.slice(4, -1).split(',')
  } else {
    // named color values are not yet supported
    console.error('Named color values are not supported in the config. Convert it manually using this chart: https://htmlcolorcodes.com/color-names/')
    return [0, 0, 16] // defaults to dark gray
  }
}

export const ApplyBranding = ({colors}) =&amp;gt; {
  if (colors) {
    return (
      &amp;lt;Helmet&amp;gt;
        &amp;lt;style&amp;gt;
          {`:root {
          ${colors &amp;amp;&amp;amp;
          map(
            colors,
            printCss('', color =&amp;gt; {
              const hsl = colorToHsl(color)
              return `hsl(${hsl[0]}, ${hsl[1]}%, ${hsl[2]}%)`
            })
          )}
          ${colors &amp;amp;&amp;amp;
          map(
            colors,
            printCss('h', color =&amp;gt; {
              const hsl = colorToHsl(color)
              return hsl[0]
            })
          )}
          ${colors &amp;amp;&amp;amp;
          map(
            colors,
            printCss('s', color =&amp;gt; {
              const hsl = colorToHsl(color)
              return `${hsl[1]}%`
            })
          )}
          ${colors &amp;amp;&amp;amp;
          map(
            colors,
            printCss('l', color =&amp;gt; {
              const hsl = colorToHsl(color)
              return `${hsl[2]}%`
            })
          )}
          }`}
        &amp;lt;/style&amp;gt;
      &amp;lt;/Helmet&amp;gt;
    )
  } else return null
}

export const TenantAwareTheming = (props: StateProps) =&amp;gt; {
  return &amp;lt;ApplyBranding colors={{
    primary: props.tenant.branding.primary,
    secondary: props.tenant.branding.secondary,
  }}/&amp;gt;
}

const mapStateToProps = ({tenant}: IRootState) =&amp;gt; ({
  tenant: tenant.currentTenant
});

type StateProps = ReturnType&amp;lt;typeof mapStateToProps&amp;gt;;

export default connect(mapStateToProps)(TenantAwareTheming);
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;So really, most of this isn’t my work - but I wanted to draw attention to it since it took me so long to find it! Hopefully this can save time for someone else. Thank you, Johan, for producing this solution.&lt;/p&gt;

</description>
      <category>css</category>
      <category>bootstrap</category>
      <category>react</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Using Micronaut Annotation Mapping to Automatically Add Security Info to Swagger Docs</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 26 Jun 2020 16:41:34 +0000</pubDate>
      <link>https://forem.com/philhardwick/using-micronaut-annotation-mapping-to-automatically-add-security-info-to-swagger-docs-3be8</link>
      <guid>https://forem.com/philhardwick/using-micronaut-annotation-mapping-to-automatically-add-security-info-to-swagger-docs-3be8</guid>
      <description>&lt;p&gt;In my &lt;a href="https://dev.to/philhardwick/custom-micronaut-security-rules-616"&gt;last post&lt;/a&gt; I introduced how to create a custom security rule in &lt;a href="https://micronaut.io"&gt;Mirconaut&lt;/a&gt; which allows you to secure an endpoint by requiring a particular permission for a resource ID. In &lt;a href="https://mettle.co.uk"&gt;Mettle&lt;/a&gt;, we wanted to automatically add some documentation to &lt;a href="https://swagger.io"&gt;Swagger&lt;/a&gt; based on the custom security annotation so any person consuming the API documentation would know what permissions are necessary. This is a good example of documentation generated from code, so that it is always correct and up to date.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://swagger.io/specification/"&gt;OpenAPI Specification&lt;/a&gt; allows you to add extra information via “Specification Extensions”. In Java annotations these are specified like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;

@Operation(
            extensions = {
                    @Extension(name = "extensionName",
                    properties = {
                            @ExtensionProperty(name = "name", value = "value")
                    })
            }
    )
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;To add these annotations automatically however, my colleague Nejc and I, used an annotation mapper to hook into the Micronaut compilation process. This is how we did it:&lt;/p&gt;

&lt;h2&gt;
  
  
  Dependencies
&lt;/h2&gt;

&lt;p&gt;Start a new gradle project and add to your build.gradle:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation platform("io.micronaut:micronaut-bom:$micronautVersion")
implementation "io.micronaut:micronaut-inject"
implementation "io.micronaut:micronaut-runtime"
implementation("io.swagger.core.v3:swagger-annotations") 
implementation project(":custom-security-rule-lib")
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This will add the necessary Micronaut and Swagger annotations to your classpath.&lt;/p&gt;

&lt;h2&gt;
  
  
  Annotation Mapper
&lt;/h2&gt;

&lt;p&gt;Extend the &lt;code&gt;TypedAnnotationMapper&amp;lt;RequiredPermission&amp;gt;&lt;/code&gt; interface and implement like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import custom.security.rule.RequiredPermission;
import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.inject.annotation.TypedAnnotationMapper;
import io.micronaut.inject.visitor.VisitorContext;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.extensions.Extension;
import io.swagger.v3.oas.annotations.extensions.ExtensionProperty;

import java.util.Collections;
import java.util.List;

public class OpenApiAnnotationMapper implements TypedAnnotationMapper&amp;lt;RequiredPermission&amp;gt; {
    @Override
    public Class&amp;lt;RequiredPermission&amp;gt; annotationType() {
        return RequiredPermission.class;
    }

    @Override
    public List&amp;lt;AnnotationValue&amp;lt;?&amp;gt;&amp;gt; map(AnnotationValue&amp;lt;RequiredPermission&amp;gt; annotation, 
            VisitorContext visitorContext) {
        String resourceIdName = annotation.stringValue("resourceIdName").orElse(null);
        String permission = annotation.stringValue("permission").orElse(null);

        AnnotationValue&amp;lt;ExtensionProperty&amp;gt; extensionProp = AnnotationValue.builder(ExtensionProperty.class)
                .member("name", "AuthorisationDescription")
                .member("value", "Your JWT needs to have " + permission + " permissions for " + resourceIdName)
                .build();

        AnnotationValue&amp;lt;Extension&amp;gt; extension = AnnotationValue.builder(Extension.class)
                .member("name", "Security")
                .member("properties", new AnnotationValue[]{extensionProp})
                .build();

        AnnotationValue&amp;lt;Operation&amp;gt; operation = AnnotationValue.builder(Operation.class)
                .member("extensions", new AnnotationValue[]{extension})
                .build();
        return List.of(operation);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Here I’ve decided to use &lt;code&gt;TypedAnnotationMapper&lt;/code&gt; and have the jar which provides the custom security rule annotation on the annotation processor classpath, but it’s also possible to use &lt;code&gt;NamedAnnotationMapper&lt;/code&gt;. &lt;code&gt;NamedAnnotationMapper&lt;/code&gt; allows you to map the annotation without having it on the classpath - this is useful if you want to keep you annotation processor classpath small, as suggested in the &lt;a href="https://docs.micronaut.io/latest/guide/index.html#annotationMetadata"&gt;Micronaut docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Implementing the mapping is a case of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;getting the information from the custom security rule&lt;/li&gt;
&lt;li&gt;creating an extension property &lt;/li&gt;
&lt;li&gt;creating an extension which holds a list of that extension property&lt;/li&gt;
&lt;li&gt;creating an operation which holds a list of that extension&lt;/li&gt;
&lt;li&gt;return that operation&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Micronaut won’t remove the annotation you’re mapping, so your endpoint will still be secured by the security rule. It also won’t remove any existing &lt;code&gt;Operation&lt;/code&gt; annotations, it will merge the new &lt;code&gt;Operation&lt;/code&gt; annotation with the existing one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making the mapper discoverable
&lt;/h2&gt;

&lt;p&gt;To make the mapper discoverable via the java service loader create a file in the resources folder called &lt;code&gt;META-INF/services/io.micronaut.inject.annotation.AnnotationMapper&lt;/code&gt; and put the fully qualified name of the mapper inside:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;custom.security.rule.openapi.OpenApiAnnotationMapper
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Using your mapper in another project
&lt;/h2&gt;

&lt;p&gt;Add the jar as an annotation processor, for example, in gradle add the following to your dependencies:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//to generate the openapi docsc
annotationProcessor("io.micronaut.configuration:micronaut-openapi:1.5.1")
//This shows using the jar from a multi-module project 
//if you're uploading this to a maven repo use the artefact coordinates
annotationProcessor project(":custom-security-rule-openapi") 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  What gets generated
&lt;/h2&gt;

&lt;p&gt;When the above class and service descriptor is added to the annotation processor classpath, the annotation mapper will run before the Micronaut openapi annotation processor. This means the OpenAPI processor will parse the mapped &lt;code&gt;@Extension&lt;/code&gt; annotation and generate the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;openapi: 3.0.1
info:
  title: Example API
  version: v1
paths:
  /tenant/{tenantId}:
    get:
      operationId: index
      parameters:
      - name: tenantId
        in: path
        required: true
        schema:
          type: string
      responses:
        default:
          description: index default response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/HttpStatus'
      x-Security:
        AuthorisationDescription: Your JWT needs to have READ_ONLY permissions for tenantId
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Notice the &lt;code&gt;x-Security&lt;/code&gt; key which holds the info specified in our AnnotationMapper.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Micronaut’s compilation process is really powerful and allows a lot of custom functionality to be created - this is just scratching the surface. Another way to do the above is to use a &lt;code&gt;TypeElementVisitor&lt;/code&gt; to modify the &lt;code&gt;@Operation&lt;/code&gt; annotation when a &lt;code&gt;@RequiredPermission&lt;/code&gt; is present. I’ll aim put a blog post up about that to follow this one.&lt;/p&gt;

&lt;p&gt;The code from above, including unit tests, is all in a public github repo: &lt;a href="https://github.com/PhilHardwick/micronaut-custom-security-rule"&gt;https://github.com/PhilHardwick/micronaut-custom-security-rule&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>micronaut</category>
      <category>swagger</category>
      <category>java</category>
    </item>
    <item>
      <title>Custom Micronaut Security Rules</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Sat, 20 Jun 2020 10:03:23 +0000</pubDate>
      <link>https://forem.com/philhardwick/custom-micronaut-security-rules-616</link>
      <guid>https://forem.com/philhardwick/custom-micronaut-security-rules-616</guid>
      <description>&lt;p&gt;&lt;a href="https://micronaut.io"&gt;Micronaut&lt;/a&gt; comes with a few useful security rules such as ip filtering, url pattern matching and an annotation inspecting rule. However, extending these by creating custom rules is also possible and is useful to lock down your application and reduce the amount of code needed for checking authorisation.&lt;/p&gt;

&lt;p&gt;First, let’s look at customising the default rules in Micronaut security:&lt;/p&gt;

&lt;h2&gt;
  
  
  Customising @Secured
&lt;/h2&gt;

&lt;p&gt;The usual way to secure endpoints is by using &lt;code&gt;@Secured&lt;/code&gt; with the name of a role or roles e.g. &lt;code&gt;@Secured("ADMIN")&lt;/code&gt;. This will look for a string of “ADMIN” in the roles key in the claims. Either&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "sub":"1",
    "roles":["ADMIN"]
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;or&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "sub":"1",
    "roles": "ADMIN"
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;would be allowed.&lt;/p&gt;

&lt;p&gt;To customise this, you can either change the key the default roles finder looks in by setting the property &lt;code&gt;micronaut.security.token.rolesName&lt;/code&gt; or implement &lt;code&gt;io.micronaut.security.token.RolesFinder&lt;/code&gt; in a new Bean.&lt;/p&gt;

&lt;h2&gt;
  
  
  Custom Security Rules
&lt;/h2&gt;

&lt;p&gt;To implement a new custom security rule you need to implement &lt;code&gt;io.micronaut.security.rules.SecurityRule&lt;/code&gt; which only has one method:&lt;br&gt;&lt;br&gt;
SecurityRuleResult check(HttpRequest request, @Nullable RouteMatch routeMatch, @Nullable Map claims);&lt;br&gt;&lt;br&gt;
&lt;code&gt;SecurityRule&lt;/code&gt; also implements &lt;code&gt;Ordered&lt;/code&gt; so you can override the default &lt;code&gt;getOrder&lt;/code&gt; method to define when your rule gets run.&lt;/p&gt;

&lt;p&gt;When implementing the check method you need to return &lt;code&gt;SecurityRuleResult&lt;/code&gt;. This is an enum with 3 values: &lt;code&gt;ALLOWED&lt;/code&gt;, &lt;code&gt;DENIED&lt;/code&gt; and &lt;code&gt;UNKNOWN&lt;/code&gt;. You should return &lt;code&gt;ALLOWED&lt;/code&gt; if your rule explicitly allows the action, &lt;code&gt;DENIED&lt;/code&gt; if your rule specifically does not allow the action and &lt;code&gt;UNKNOWN&lt;/code&gt; if you don’t have enough information to make a decision. Returning &lt;code&gt;UNKNOWN&lt;/code&gt; allows the other security rules to also try make a decision, rather than immediately denying the request if there’s not enough information.&lt;/p&gt;

&lt;p&gt;When you implement the rule you have 3 parameters passed to you: the request, the route match and claims. The request is simply the request made by the client which is being authorised. The route match is what gives you access to the method in your controller so you can get annotations or arguments. Claims is a map of the JSON from the JWT sent in the request. This can be null if there wasn’t a JWT, or it couldn’t be parsed or validated.&lt;/p&gt;

&lt;p&gt;So when would you need a custom security rule?&lt;/p&gt;
&lt;h2&gt;
  
  
  Permissions on Specific Resources
&lt;/h2&gt;

&lt;p&gt;If you want to implement permissions on specific resources then you need to implement a custom rule. This is useful if, for example, your system is multi-tenant and users are only allowed to manage their tenant. This is different from a list of roles because the user is only allowed to do something on a specific resource. Usually, JWTs with resource specific permissions would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    {
      "sub": "",
      "https://your-domain.com/claims": {
        "123": "ADMIN",
        "234": "READ_ONLY"
      }
    } 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The permissions are in a namespaced map (namespacing by domain is the conventional way to do it - &lt;a href="https://auth0.com/docs/tokens/guides/create-namespaced-custom-claims"&gt;Auth0 explains a bit more about this&lt;/a&gt;) where the keys are resource IDs. Following my example, 123 and 234 would be the IDs of two tenants. The user who asked for this JWT would be able to perform ADMIN actions on tenant with ID 123 and only view tenant with ID 234.&lt;/p&gt;

&lt;h2&gt;
  
  
  So how can we authorise this user in Mirconaut?
&lt;/h2&gt;

&lt;p&gt;You’ll need two classes, one annotation and one &lt;code&gt;SecurityRule&lt;/code&gt; implementation. The annotation will need to define the &lt;code&gt;resourceIdName&lt;/code&gt; and the &lt;code&gt;permission&lt;/code&gt; it’s looking for:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;public @interface RequiredPermission {

    /**
     * The name of the parameter in the controller method which contains the 
     * resource ID this permisssion is required for
     * @return resourceIdName
     */
    String resourceIdName();

    /**
     * The permission required, e.g. READ_ONLY, ADMIN, WRITE
     * @return permission
     */
    String permission();

}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then we define a security rule that looks for this permission and uses the values in the annotation to pull out the resource ID in the url and compare it with the claims in the token:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import io.micronaut.core.annotation.AnnotationValue;
import io.micronaut.http.HttpRequest;
import io.micronaut.security.rules.SecurityRule;
import io.micronaut.security.rules.SecurityRuleResult;
import io.micronaut.web.router.MethodBasedRouteMatch;
import io.micronaut.web.router.RouteMatch;

import javax.annotation.Nullable;
import javax.inject.Singleton;
import java.util.Map;
import java.util.Optional;

@Singleton
public class PermissionSecurityRule implements SecurityRule {
    @Override
    public SecurityRuleResult check(HttpRequest request, @Nullable RouteMatch routeMatch, @Nullable Map&amp;lt;String, Object&amp;gt; claims) {
        if (routeMatch instanceof MethodBasedRouteMatch) {
            MethodBasedRouteMatch methodBasedRouteMatch = (MethodBasedRouteMatch) routeMatch;
            if (methodBasedRouteMatch.hasAnnotation(RequiredPermission.class)) {
                AnnotationValue&amp;lt;RequiredPermission&amp;gt; requiredPermissionAnnotation = methodBasedRouteMatch.getAnnotation(RequiredPermission.class);
                // Get parameters from annotation on method
                Optional&amp;lt;String&amp;gt; resourceIdName = requiredPermissionAnnotation.stringValue("resourceIdName");
                Optional&amp;lt;String&amp;gt; permission = requiredPermissionAnnotation.stringValue("permission");
                if (permission.isPresent() &amp;amp;&amp;amp; resourceIdName.isPresent() &amp;amp;&amp;amp; claims != null) {
                    // Use name of parameter to get the value passed in as an argument to the method
                    String resourceId = methodBasedRouteMatch.getVariableValues().get(resourceIdName.get()).toString();
                    // Get claim from jwt using the resource ID
                    Object permissionForResource = ((Map) claims.get("https://your-domain.com/claims")).get(resourceId);
                    if (permissionForResource != null &amp;amp;&amp;amp; permissionForResource.equals(permission.get())) {
                        // if the permission exists and it's equal, allow access
                        return SecurityRuleResult.ALLOWED;
                    }
                }
            }
        }
        return SecurityRuleResult.UNKNOWN;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Annotating this rule with &lt;code&gt;@Singleton&lt;/code&gt; means it will be picked up by Micronaut and executed as part of a list of rules. Notice how one only path in the code leads to the method returning &lt;code&gt;ALLOWED&lt;/code&gt; and all others return &lt;code&gt;UNKNOWN&lt;/code&gt;, meaning other rules can also be checked - if everything returns &lt;code&gt;UNKNOWN&lt;/code&gt; the request will be rejected with a 403.&lt;/p&gt;

&lt;p&gt;To put this rule before other rules, implement the &lt;code&gt;getOrder&lt;/code&gt; method and return a number lower than the numbers returned from the other rules. Currently, this is the order of the rules, and the numbers returned from getOrder():&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;IpPatternsRule - Order number: -300&lt;/li&gt;
&lt;li&gt;SecuredAnnotationRule - Order number: -200&lt;/li&gt;
&lt;li&gt;ConfigurationInterceptUrlMapRule - Order number: -100&lt;/li&gt;
&lt;li&gt;SensitiveEndpointRule - Order number: 0&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;You can have much more complicated JWT claims and still validate they are correct. For example, I would probably have a list of permissions in the JWT per resource ID like &lt;code&gt;{"123":["READ_ONLY","WRITE","ADMIN"]}&lt;/code&gt; and so I would verify that the required permission is in the list. Also, unless your IDs are globally unique, I would put these in a nested object to show what resource they relate to, e.g. &lt;code&gt;{"https://your-domain.com/claims": {"tenants": {"123": ["READ_ONLY"]}}}&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Micronaut makes it really easy to hook into the security and provides all you need to validate claims and authorise requests. All code for this, plus tests, is on Github at &lt;a href="https://github.com/PhilHardwick/micronaut-custom-security-rule"&gt;https://github.com/PhilHardwick/micronaut-custom-security-rule&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>micronaut</category>
      <category>java</category>
      <category>security</category>
      <category>jwt</category>
    </item>
    <item>
      <title>8 reasons you should use GitOps</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 12 Jun 2020 06:12:37 +0000</pubDate>
      <link>https://forem.com/philhardwick/8-reasons-you-should-use-gitops-3ci1</link>
      <guid>https://forem.com/philhardwick/8-reasons-you-should-use-gitops-3ci1</guid>
      <description>&lt;h2&gt;
  
  
  What is GitOps
&lt;/h2&gt;

&lt;p&gt;Before saying why GitOps is so useful, I should explain what it is. At its most basic, GitOps is defining all the configuration for your system in Git. This includes deployments, versions of services, config and secrets. For example, if using &lt;a href="https://kubernetes.io/"&gt;Kubernetes&lt;/a&gt;, a GitOps repository will have some Kubernetes deployment files which define the images and versions to deploy. Each deployment file may also reference config maps or contain environment variables which specify the config required to run that service in each environment.&lt;/p&gt;

&lt;p&gt;All this means you have a declarative way of defining the state of your system. It’s like saying, “I want the whole system to always reflect the settings in these files”. This is the opposite to the imperative way of defining your system where you tell you the system how to change e.g. &lt;code&gt;helm deploy&lt;/code&gt; or &lt;code&gt;helm rollback&lt;/code&gt;. In the imperative way, the system is a sum of all the things it has been told.&lt;/p&gt;

&lt;p&gt;In GitOps, changes to the system are pulled in (via agents) rather than pushed in by developers, or a CI issuing commands. Agents run in the cluster, comparing the actual state of the cluster and to the state defined in Git. If there’s been changes to Git, it will apply them to the cluster.&lt;/p&gt;

&lt;p&gt;Agents are also used in the deployment of services. New versions of services are deployed by tagging an image in the docker repository. An agent will be scanning for new tags in that repository. If the tag matches a predefined pattern then the tag gets applied to the deployment files in the Git repo and that change will be picked up and applied.&lt;/p&gt;

&lt;p&gt;So why use GitOps?&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Show me the config
&lt;/h2&gt;

&lt;p&gt;It’s really easy to find and share the configuration of a service. I’ve had many instances when someone has asked me, “what configuration does Kafka have set?” Using GitOps doesn’t require me to look at the deployment descriptor in Kubernetes. I search in Git. When I’ve found it, I can easily share that file as a url with anyone who needs it - they don’t need special access to be able to inspect what’s running. GitOps is a great leveller, and it gives everyone the ability to see how things are running.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. History of changes
&lt;/h2&gt;

&lt;p&gt;When all changes are made through Git you have a ready-made history of all the changes to the system, including some description of what or why the changes happened in the commit messages. When something breaks, it’s then easy to look back at the last change and figure out what may have caused the problem.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Git revert
&lt;/h2&gt;

&lt;p&gt;Git revert then becomes an instant rollback mechanism. So you can feel confident making changes knowing it can easily be undone too.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Using familiar tools
&lt;/h2&gt;

&lt;p&gt;Git is a familiar tool to most developers and using GitOps saves having to learn a new CLI with all its syntax and options. It does still need developers to know how to define the deployment/configuration files though e.g. you need to know how to structure a Kubernetes deployment yaml file if deploying in Kubernetes - but at least you don’t have to learn how to use &lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; too!&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Declarative means rebuildable
&lt;/h2&gt;

&lt;p&gt;Having all your configuration and state in a single place is the first step to making your environments rebuildable. When an environment rebuilds it doesn’t require a CI to kick in at some point and deploy all the latest apps - the agents that are already running simply apply the config that’s already in Git and the system will be exactly as it was before.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Git is the source of truth
&lt;/h2&gt;

&lt;p&gt;I know it’s so tempting to make a sneaky change, in place, to try something out: &lt;code&gt;kubectl set env ...&lt;/code&gt;. If it works, “wonderful!”, but it’s possible you forget to apply the config to all services or add it to CI and then when there’s a cluster rebuild, or even a new deployment that change may be lost. It also works the other way. If an app breaks, you don’t need to check if any config has been manually set which is causing the problem. Git is the single source of truth for how your apps are running and that gives a warm sense of security and certainty about being able to reproduce, recreate and replicate entire systems in other environments, without any manual intervention.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Collaboration and sharing
&lt;/h2&gt;

&lt;p&gt;Changes happen via pull requests so all changes are visible and can be discussed. GitOps is a great way to share knowledge because everyone can see how the system is being configured - no one can make changes secretly.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Self service
&lt;/h2&gt;

&lt;p&gt;Anyone can change the state of the cluster, it just needs a pull request and some approvals. This is great because it means the organisation doesn’t rely on a few individuals to make changes, anyone can make the change. This is truly self-service. It also means people don’t need special permissions to be able to make changes. So you can lock down permissions whilst still allowing all developers to make changes via PRs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further reading
&lt;/h2&gt;

&lt;p&gt;If you want to find out more about GitOps, I’d recommend checking out &lt;a href="https://www.weave.works/technologies/gitops/"&gt;Weave Works&lt;/a&gt;, and to know how to implement GitOps, some blog posts from &lt;a href="https://medium.com/@swade1987"&gt;Steve Wade&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>git</category>
      <category>gitops</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>React Map GL - How do I test this?</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Sat, 06 Jun 2020 08:01:41 +0000</pubDate>
      <link>https://forem.com/philhardwick/react-map-gl-how-do-i-test-this-1agm</link>
      <guid>https://forem.com/philhardwick/react-map-gl-how-do-i-test-this-1agm</guid>
      <description>&lt;p&gt;How do I test this? This is a common question I ask myself when writing a new feature. Sometimes it’s not so easy and you need to truly think about what you’re testing and the level at which you’re testing (in the test pyramid).&lt;/p&gt;

&lt;p&gt;I’m creating an app which draws layers on a map. Testing these layers are visible to the user is a difficult problem, so I’ll share how I solved it and why.&lt;/p&gt;

&lt;h2&gt;
  
  
  Libraries and Components
&lt;/h2&gt;

&lt;p&gt;I’m using &lt;a href="https://www.typescriptlang.org/"&gt;Typescript&lt;/a&gt; and &lt;a href="https://reactjs.org/"&gt;React&lt;/a&gt; with &lt;a href="http://visgl.github.io/react-map-gl/"&gt;react-map-gl&lt;/a&gt; to provide the map component. As a test framework I’m using &lt;a href="https://devexpress.github.io/testcafe/"&gt;Testcafe&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make the map queryable
&lt;/h2&gt;

&lt;p&gt;The first thing is to make the map available to the tests. This is done by using React’s &lt;code&gt;ref&lt;/code&gt; prop. I have passed a function which takes the element and assigns it to the &lt;code&gt;window&lt;/code&gt;. Casting the &lt;code&gt;window&lt;/code&gt; to &lt;code&gt;any&lt;/code&gt; is required to ensure the Typescript compiler allows us to assign a new variable on the &lt;code&gt;window&lt;/code&gt; object.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;MapGL
    {...viewport}
    width="100%"
    height="100%"
    style={{ position: 'relative' }}
    mapStyle="mapbox://styles/streets-v11"
    onViewportChange={this._onViewportChange}
    mapboxApiAccessToken={process.env.REACT_APP_MAPBOX_ACCESS_TOKEN}
    ref={el =&amp;gt; ((window as any).map = el)}
  &amp;gt;
    &amp;lt;div className="navigation-control-container"&amp;gt;
      &amp;lt;NavigationControl showCompass={false} /&amp;gt;
    &amp;lt;/div&amp;gt;
    &amp;lt;MapLegend /&amp;gt;
  &amp;lt;/MapGL&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Querying the map for layers
&lt;/h2&gt;

&lt;p&gt;Testcafe (and most ui test frameworks like Cypress or Selenium) allow you to define code which can be executed on the browser. We’ll leverage this to access the map and its layers. In Testcafe this is done using a &lt;code&gt;ClientFunction&lt;/code&gt;. &lt;code&gt;getMapLayer&lt;/code&gt; uses a &lt;code&gt;ClientFunction&lt;/code&gt; by passing a function which returns a &lt;code&gt;Promise&lt;/code&gt;. The most difficult thing about this setup was getting the transpiled code to be correct. Testcafe runs the code in the &lt;code&gt;ClientFunction&lt;/code&gt; through Babel to allow you to use modern language features but it also means you have to structure your code quite specifically. I found it was easiest to define all called functions in the same file, pass those functions as dependencies and don’t call any other functions inside those functions (unless they’re defined in the scope of the function - like &lt;code&gt;filterLayerFields&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//map-commponent.page-object.ts
import {ClientFunction, Selector, t} from 'testcafe';
import {IMapLayer} from "./map-types";

// declared so typescript allows you to access window.map from the client function
declare let map: any;

const getMapLayerAndData = (localMap, layerId): IMapLayer =&amp;gt; {
  const filterLayerFields = layer =&amp;gt; {
    return {
      id: layer.id,
      type: layer.type,
      paint: layer.paint,
      layout: layer.layout
    };
  };

  const layer = localMap.getMap().getLayer(layerId);
  const source = localMap.getMap().getSource(layerId);
  return {
    layer: layer &amp;amp;&amp;amp; filterLayerFields(layer),
    geoJson: source &amp;amp;&amp;amp; source._data
  };
}

const doOnMapOnceLoadedOrImmediately = (localMap, callback) =&amp;gt; {
  if (localMap.getMap().loaded()) {
    callback()
  } else {
    localMap.getMap().on('idle', () =&amp;gt; {
      callback();
    });
  }
}

const getMapLayer = layerId =&amp;gt;
  ClientFunction(() =&amp;gt;
    new Promise&amp;lt;IMapLayer&amp;gt;(resolve =&amp;gt; {
      doOnMapOnceLoadedOrImmediately(map, () =&amp;gt; resolve(getMapLayerAndData(map, layerId)))
    }), { dependencies: { layerId, doOnMapOnceLoadedOrImmediately, getMapLayerAndData }
  });
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And the types used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//map-types.js
import { FeatureCollection, Point, MultiPoint, LineString, 
    MultiLineString, Polygon, MultiPolygon, GeoJsonProperties } from 'geojson';

export interface IPropertyValue {
  kind: string;
  value: any;
}

export interface IPaintProperty {
  property: any;
  value: IPropertyValue;
  parameters: any;
}

export interface IPaintValues {
  'line-opacity': IPaintProperty;
  'line-color': IPaintProperty;
  'line-width': IPaintProperty;
  'line-floorwidth': IPaintProperty;
}

export interface IPaint {
  _values: IPaintValues;
  _properties: any;
}

export interface ILayer {
  id: string;
  type: string;
  paint: IPaint;
  layout: any;
}

export interface IMapLayer {
  geoJson: FeatureCollection&amp;lt;Point | MultiPoint | LineString | 
    MultiLineString | Polygon | MultiPolygon, GeoJsonProperties&amp;gt;;
  layer: ILayer;
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Using this in your test
&lt;/h2&gt;

&lt;p&gt;Now you can call this client function. As with a lot of UI testing it helps to build in wait mechanisms because it will take some time for the map to render all the layers. This will make your test less brittle. I’ve put this code in a page component, so it can be easily reused. This is the same file that has the functions above declared globally (but scoped to the file).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;//map-commponent.page-object.ts
import {ClientFunction, Selector, t} from 'testcafe';
import {IMapLayer} from "./map-types";

export default class MapComponent {
  mapCanvas: Selector = Selector('.mapboxgl-canvas', { timeout: 1000 });

  private async waitForMapLayer(layerId: string, condition: (IMapLayer) =&amp;gt; boolean) {
    let mapLayer = await getMapLayer(layerId)();
    let retries = 0;
    while (!condition(mapLayer) &amp;amp;&amp;amp; retries &amp;lt; 20) {
      t.wait(100);
      retries++
      mapLayer = await getMapLayer(layerId)();
    }
    return mapLayer
  }

  mapLayerHasFeatures = (numberOfFeatures: number) =&amp;gt; (mapLayer: IMapLayer): boolean =&amp;gt; {
    return mapLayer.geoJson !== undefined &amp;amp;&amp;amp; mapLayer.geoJson.features.length === numberOfFeatures;
  }

  async getLayer(layerId: string, waitUntilNumberOfFeatures: number): Promise&amp;lt;IMapLayer&amp;gt; {
    return await this.waitForMapLayer(layerId, this.mapLayerHasFeatures(waitUntilNumberOfFeatures));
  }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Finally, you can call this in a test:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import MapComponent from "../map-component.page-object";

test('map layer exists with correct coordinates', async t =&amp;gt; {
  const mapComponent = new MapComponent()
  const mapLayer = await mapComponent.getLayer("my-road", 1);
  t.expect(mapLayer.geoJson.features[0].geometry.coordinates)
    .eql([[0.1872612, 51.9872986], [0.1876876, 51.9725736]])
});
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Things to watch out for
&lt;/h2&gt;

&lt;p&gt;You can’t currently pass a typescript class to the client function as a dependency otherwise it will hang. See this &lt;a href="https://github.com/DevExpress/testcafe/issues/3955"&gt;issue&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What you’re actually testing
&lt;/h2&gt;

&lt;p&gt;There are other ways to test this too. I’ve seen a lot of screenshot comparing tests. Comparing screenshots is the ultimate way to definitely make sure your layers are drawn on the map. I’ve also thought about comparing the image data from a canvas and counting the number of colour pixels. However, I decided not to go either of those ways because I felt the tests would be too brittle and require too much maintenance. When using my approach I’m just testing my code and some of React Map GL’s code, then trusting mapbox to render the layers correctly on a canvas. I can imagine they already have a lot of sophisticated testing around this, so I don’t need to duplicate that by comparing pixels.&lt;/p&gt;

</description>
      <category>typescript</category>
      <category>react</category>
      <category>mapbox</category>
      <category>testcafe</category>
    </item>
    <item>
      <title>Adding Observability - Tracking Exceptions</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 29 May 2020 05:26:21 +0000</pubDate>
      <link>https://forem.com/philhardwick/adding-observability-tracking-exceptions-39ei</link>
      <guid>https://forem.com/philhardwick/adding-observability-tracking-exceptions-39ei</guid>
      <description>&lt;p&gt;This post will show how to easily observe exceptions in a &lt;a href="https://spring.io/projects/spring-boot"&gt;Spring Boot&lt;/a&gt; application, using &lt;a href="https://honeycomb.io"&gt;Honeycomb&lt;/a&gt; and &lt;a href="https://docs.spring.io/spring-framework/docs/5.1.x/spring-framework-reference/core.html#aop"&gt;Aspect Oriented Programming&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Observability
&lt;/h2&gt;

&lt;p&gt;Observability is understanding how your system is running in production without deploying changes. It’s about being able to answer questions you didn’t know you wanted the answer to, without changing code. Two things that enable observability are: exporting non-aggregated data (i.e. events not metrics) and high cardinality labels for those events. Events contain lots of data about what happened in a system which can then be queried or aggregated later. A high cardinality label, for example, would be user ID. That’s useful because if your system is showing slow responses, you can group the response times by user ID and see what proportion of users are being affected. If it’s only a small subset of users you can then investigate only those users - you’ve delved into the heart of the problem much quicker than you could have with low cardinality metrics.&lt;/p&gt;

&lt;p&gt;To improve observability in a personal side project app, I decided to use Honeycomb. Honeycomb is super easy to export data into and has an intuitive UI for querying and graphing (I’m not affiliated with Honeycomb, it’s simply something I’ve wanted to try for a while).&lt;/p&gt;

&lt;h2&gt;
  
  
  Observing Exceptions
&lt;/h2&gt;

&lt;p&gt;Another high cardinality label would be exception data. Adding exception data to events is also very useful for understanding why things are happening in your system and particular exceptions might be the cause or differentiator for you to be able to find issues and the causes of them.&lt;/p&gt;

&lt;p&gt;I’m going to show how to easily add exception data to your events with Aspect Oriented Programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Aspect oriented programming (AOP)
&lt;/h2&gt;

&lt;p&gt;Aspect oriented programming allows you to write code for cross-cutting concerns (non-functional requirements (NFRs) that are needed for all business functionality e.g. logging, transactions, observability) without adding extra code into the business logic - which would distract from others being able to read the intent of the logic. Instead, you can define actions to be taken before, after or around method calls in your system and keep business logic and NFRs separate.&lt;/p&gt;

&lt;h3&gt;
  
  
  Terminology: Pointcuts and Advices
&lt;/h3&gt;

&lt;p&gt;Pointcuts are simply a filter, without which an advice would run on every method call (or join point as it’s called in AOP). An advice is the action that runs before, after, or around a method call.&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding fields to spans after an exception
&lt;/h2&gt;

&lt;p&gt;This is using Spring AOP. So firstly add the Spring Boot starter for AOP into &lt;code&gt;build.gradle&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;implementation 'org.springframework.boot:spring-boot-starter-aop'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Then add a new Aspect class (make sure to annotate with &lt;code&gt;@Aspect&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Aspect
public class BeelineAspect {

    private final Beeline beeline;

    public BeelineAspect(Beeline beeline) { // 0
        this.beeline = beeline;
    }

    @Pointcut("within(@org.springframework.stereotype.Repository *)" +
            " || within(@org.springframework.stereotype.Service *)" +
            " || within(@org.springframework.web.bind.annotation.RestController *)") // 1
    public void springBeanPointcut() {
    }

    @Pointcut("within(technology.wick.repository..*)" +
            " || within(technology.wick.service..*)" +
            " || within(technology.wick.web.rest..*)") // 2
    public void applicationPackagePointcut() {
    }

    @AfterThrowing(pointcut = "applicationPackagePointcut() &amp;amp;&amp;amp; springBeanPointcut()", throwing = "e") // 3
    public void traceAfterThrowing(JoinPoint joinPoint, Throwable e) {
        beeline.getActiveSpan().addField("exception.message", e.getMessage()) // 4
            .addField("exception.cause", e.getCause())
            .addField("exception.name", e.getClass().getSimpleName())
            .addField("exception.happenedIn", joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName())
        ;
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Beeline gets autowired in since it is exposed as a bean by the &lt;code&gt;beeline-spring-boot-starter&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Add pointcut to match any method call in beans annotated with &lt;code&gt;@Repository&lt;/code&gt;, &lt;code&gt;@Service&lt;/code&gt; or &lt;code&gt;@RestController&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Then add a pointcut to match any method call in beans in the repository, service and web packages.&lt;/li&gt;
&lt;li&gt;Use those pointcuts in an advice to run only after throwing an exception.&lt;/li&gt;
&lt;li&gt;Add exception data to the current span using &lt;code&gt;Beeline&lt;/code&gt; (Honeycomb’s interface to modify spans and traces).&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The pointcut methods are purposefully empty because the actual action we want to take is in the advice.&lt;/p&gt;

&lt;p&gt;This aspect can then be enabled with an &lt;code&gt;@Configuration&lt;/code&gt; class, which exposes the aspect as a bean.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;@Configuration
@EnableAspectJAutoProxy
public class AspectConfiguration {

    @Bean
    public BeelineAspect beelineAspect(Beeline beeline) {
        return new BeelineAspect(beeline);
    }
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;If you have the rest of the &lt;a href="https://docs.honeycomb.io/getting-data-in/java/beeline/#quick-installation-with-java-spring-boot-v2"&gt;Honeycomb configuration set up&lt;/a&gt;, you can now query for exception events in the dashboard.&lt;/p&gt;

&lt;p&gt;AOP is a nice way to add observability for exceptions since you don’t have to touch any of your current code. This can also be applied to other tracing providers like &lt;a href="https://opentelemetry.io/"&gt;OpenTelemetry&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>springboot</category>
      <category>aop</category>
      <category>observability</category>
      <category>tracing</category>
    </item>
    <item>
      <title>Facts about Pacts</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Fri, 22 May 2020 07:16:00 +0000</pubDate>
      <link>https://forem.com/philhardwick/facts-about-pacts-ofd</link>
      <guid>https://forem.com/philhardwick/facts-about-pacts-ofd</guid>
      <description>&lt;p&gt;In &lt;a href="https://mettle.co.uk"&gt;Mettle&lt;/a&gt;, &lt;a href="https://docs.pact.io"&gt;Pact&lt;/a&gt; was used to break up deployments and releases so that big bang releases were avoided. Previously testing had been done against a fixed set of versions of each of the services and if any version changed, testing would have to be re-done. I joined after this work had been done, so I had to catch up about how Pact worked.&lt;/p&gt;

&lt;p&gt;Using consumer driven contracts is a key step towards getting to continuous delivery, where deployment to production is automatic. Continuous delivery is particularly excellent because changes going into production are small and incremental - if something is broken it’s easy to roll back to the previous version. Also, since the change was small, you know where to look for the bug - it makes the process of releasing much less risky.&lt;/p&gt;

&lt;p&gt;These are some things I learnt about Pact, when first starting, which may help you get up to speed quicker!&lt;/p&gt;

&lt;h2&gt;
  
  
  It tests contracts
&lt;/h2&gt;

&lt;p&gt;What’s particularly key about Pact is that it separates testing the &lt;em&gt;functionality&lt;/em&gt; of a service (by feature tests) from the &lt;em&gt;interfaces&lt;/em&gt; it provides or consumes. Pact is very specific about what it tests: it’s not testing authorization, authentication, standards, interactions with third party systems - it is testing the format of messages sent between services you own.&lt;/p&gt;

&lt;h2&gt;
  
  
  It provides fast feedback
&lt;/h2&gt;

&lt;p&gt;Pacts sit in between the unit test and integration test levels of the test pyramid. It can therefore be used for really quick feedback: contract tests can be run as part of the build process, so you know immediately whether your service is compatible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consumers only publish contracts
&lt;/h2&gt;

&lt;p&gt;It’s “consumer driven”, so it follows that consumers publish the pacts (contracts) first. Consumers don’t “verify” contracts, they only publish them. For the consumer, it’s actually quite a self-contained process.&lt;/p&gt;

&lt;p&gt;Consumers create contracts by running an in memory server, setting up expected requests on the server and then invoking the production code to make that request.&lt;/p&gt;

&lt;p&gt;This means that when the consumer build runs, it’s not really running against a provider, it’s doing its own thing by sending requests to a mock Pact server and checking the request is as expected. The only reason this can fail is if the code is sending a different request to what the mock server is expecting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Providers only verify contracts
&lt;/h2&gt;

&lt;p&gt;Providers only verify the contracts which have been published, they don’t publish contracts.&lt;/p&gt;

&lt;p&gt;Providers verify pacts by running the exact request from the contract and then comparing the response they return with the expected response in the contract.&lt;/p&gt;

&lt;p&gt;Providers pull contracts down from the broker and use them to create requests to send to the running service (in our case they run against a &lt;a href="https://spring.io/projects/spring-boot"&gt;Spring Boot&lt;/a&gt; test which spins up the application in memory). This is where the contract test can fail because of a mismatch between the expected response in the contract compared to the response returned from the service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Providers need to know when new contracts are published
&lt;/h2&gt;

&lt;p&gt;To be able to get instant feedback, providers need to know when new contracts are published. Then they can run their own build to verify that they provide everything the new contract requires.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Pact broker can show a lot of version matches in the compatibility matrix
&lt;/h2&gt;

&lt;p&gt;Don’t be afraid of all the version matches shown - that’s normal, and the Pact broker is made to handle that. The reason for the number of versions is that when a provider runs a verification, it verifies against all the tags you specify and publishes each of these to the broker. So if you verify against tags &lt;code&gt;master, dev, staging, prod&lt;/code&gt; then you may be creating 4 version matches every time you build the provider. Add that to the fact that we use a git sha as the version of the Pacticipant, and you get even more version matches. This is because each git commit will be a new version in the broker.&lt;/p&gt;

&lt;h2&gt;
  
  
  Including generated JWTs in your contracts will create a new contract on every consumer build
&lt;/h2&gt;

&lt;p&gt;Because JWTs include time information such as expiry (&lt;code&gt;exp&lt;/code&gt;) and issued at (&lt;code&gt;iat&lt;/code&gt;), every time the test runs it will likely have a different JWT with a different &lt;code&gt;exp&lt;/code&gt; and &lt;code&gt;iat&lt;/code&gt;. Try to avoid generating JWTs and using them in your pact. Either don’t send it or use a static long-lived token. This enables Pact to do some optimisation - if the pact doesn’t change it automatically knows all the current providers fulfill it, so the provider tests don’t need to run again verify it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using tags it is easy to see the version of each service in each environment.
&lt;/h2&gt;

&lt;p&gt;After a service is deployed to a new environment we tag its version in the Pact broker with the environment name (for consumers we tag the contract, for providers we tag the provider). This is to enable providers to verify against all the versions of the consumers we have deployed. This enables our pipeline to check in the Pact broker that a new version of a service can run against everything that is already running in dev, staging or prod.&lt;/p&gt;

&lt;p&gt;There’s a side benefit in that you can see exactly what version of each service is deployed to which environment - pretty cool.&lt;/p&gt;

&lt;h2&gt;
  
  
  What to test in Pact
&lt;/h2&gt;

&lt;p&gt;What to test in Pact is up to you - but try to keep it to the format of interactions rather than the functionality. For instance we decided to mock the spring service layer in pacts rather than seed the repositories with data to meet the provider states. This bypasses any logic in the services and just keep the test to exercising what the controller does which the HTTP interface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;These were, hopefully useful, facts about Pact!&lt;/p&gt;

</description>
      <category>pact</category>
      <category>consumerdrivencontracts</category>
      <category>microservices</category>
      <category>continuousdelivery</category>
    </item>
    <item>
      <title>Prompt to install a PWA on iOS and Android with React Hooks</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Wed, 13 May 2020 06:10:30 +0000</pubDate>
      <link>https://forem.com/philhardwick/prompt-to-install-a-pwa-on-ios-and-android-with-react-hooks-dkf</link>
      <guid>https://forem.com/philhardwick/prompt-to-install-a-pwa-on-ios-and-android-with-react-hooks-dkf</guid>
      <description>&lt;p&gt;So you’ve got your service worker, your manifest.json and your app works offline, but how do you get your users to install the app?&lt;/p&gt;

&lt;p&gt;This post will show you how to prompt your users to install your &lt;a href="https://web.dev/progressive-web-apps/"&gt;progressive web app (PWA)&lt;/a&gt; using &lt;a href="https://reactjs.org/docs/hooks-intro.html"&gt;React Hooks&lt;/a&gt;. I’m going to assume you already have all the necessary stuff for a PWA in place (manifest.json, a service worker, all served from https - when you’re not on localhost).&lt;/p&gt;

&lt;p&gt;I’ve been creating an app and, instead of messing around with the App Store, React Native and two build pipelines, I decided to build a PWA so I could run one, web-based codebase on all devices. Users should be able to “install” the app if they wanted. So doing some research, I was surprised to find PWA support is still not universal or consistent across Android and iOS. So I created a cross-platform solution to prompt users based on their device. This solution uses React Hooks to be able to reuse and easily integrate this functionality into components.&lt;/p&gt;

&lt;h2&gt;
  
  
  Has the user been prompted recently?
&lt;/h2&gt;

&lt;p&gt;The first bit of functionality is to store when a user has been asked to install, so we can check if they’ve been asked recently and therefore not show the prompt too often. This is common to both iOS and Android prompts, so I extracted it into a Hook of its own.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState } from 'react';
import moment from 'moment';

const getInstallPromptLastSeenAt = (promptName: string): string =&amp;gt; localStorage.getItem(promptName);

const setInstallPromptSeenToday = (promptName: string): void =&amp;gt; {
  const today = moment().toISOString();
  localStorage.setItem(promptName, today);
};

function getUserShouldBePromptedToInstall(promptName: string, daysToWaitBeforePromptingAgain: number): boolean {
  const lastPrompt = moment(getInstallPromptLastSeenAt(promptName));
  const daysSinceLastPrompt = moment().diff(lastPrompt, 'days');
  return isNaN(daysSinceLastPrompt) || daysSinceLastPrompt &amp;gt; daysToWaitBeforePromptingAgain;
}

const useShouldShowPrompt = (promptName: string, daysToWaitBeforePromptingAgain = 30): [boolean, () =&amp;gt; void] =&amp;gt; {
  const [userShouldBePromptedToInstall, setUserShouldBePromptedToInstall] = useState(
    getUserShouldBePromptedToInstall(promptName, daysToWaitBeforePromptingAgain)
  );

  const handleUserSeeingInstallPrompt = () =&amp;gt; {
    setUserShouldBePromptedToInstall(false);
    setInstallPromptSeenToday(promptName);
  };

  return [userShouldBePromptedToInstall, handleUserSeeingInstallPrompt];
};
export default useShouldShowPrompt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This uses local storage to persist a user’s response across sessions. The &lt;code&gt;useState&lt;/code&gt; hook is used to make sure the application has a way to check the state of a user’s response. Combining these means you have a persistent way to watch for updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  iOS
&lt;/h2&gt;

&lt;p&gt;The iOS version of detecting whether a user should be prompted is simply detecting whether they’re on an iOS device, and that they haven’t already “installed” the PWA.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import useShouldShowPrompt from 'app/shared/hooks/useShouldShowPrompt';

const iosInstallPromptedAt = 'iosInstallPromptedAt';

const isIOS = (): boolean =&amp;gt; {
  // @ts-ignore
  if (navigator.standalone) {
    //user has already installed the app
    return false;
  }
  const ua = window.navigator.userAgent;
  const isIPad = !!ua.match(/iPad/i);
  const isIPhone = !!ua.match(/iPhone/i);
  return isIPad || isIPhone;
};

const useIosInstallPrompt = (): [boolean, () =&amp;gt; void] =&amp;gt; {
  const [userShouldBePromptedToInstall, handleUserSeeingInstallPrompt] = useShouldShowPrompt(iosInstallPromptedAt);

  return [isIOS() &amp;amp;&amp;amp; userShouldBePromptedToInstall, handleUserSeeingInstallPrompt];
};
export default useIosInstallPrompt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We return a hook which combines checking if the device is using iOS and whether the user has already been prompted, with a function to handle the user dismissing the prompt.&lt;/p&gt;

&lt;h2&gt;
  
  
  All other platforms
&lt;/h2&gt;

&lt;p&gt;On all other platforms, PWA support is more consistent and uses web events. The key is to attach an event handler in a &lt;code&gt;useEffect&lt;/code&gt; hook (using the &lt;a href="https://reactjs.org/docs/hooks-effect.html#effects-with-cleanup"&gt;clean up variation&lt;/a&gt; to remove the event handler) to catch and store the install prompt event. We also use the &lt;code&gt;useState&lt;/code&gt; hook to store the event, and the hook we previously created &lt;code&gt;useShouldShowPrompt&lt;/code&gt;. This hook returns the event, a method to handle a user wanting to install and a method to handle a user declining an install. You’ll notice the &lt;code&gt;useEffect&lt;/code&gt; has a dependency on &lt;code&gt;userShouldBePromptedToInstall&lt;/code&gt; so that it will run again when that changes, this is so that the user isn’t re-prompted right after they decline to install on the native prompt.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import { useState, useEffect } from 'react';
import useShouldShowPrompt from 'app/shared/hooks/useShouldShowPrompt';

const webInstallPromptedAt = 'webInstallPromptedAt';

const useWebInstallPrompt = (): [any, () =&amp;gt; void, () =&amp;gt; void] =&amp;gt; {
  const [installPromptEvent, setInstallPromptEvent] = useState();
  const [userShouldBePromptedToInstall, handleUserSeeingInstallPrompt] = useShouldShowPrompt(webInstallPromptedAt);

  useEffect(() =&amp;gt; {
    const beforeInstallPromptHandler = event =&amp;gt; {
      event.preventDefault();

      // check if user has already been asked
      if (userShouldBePromptedToInstall) {
        // store the event for later use
        setInstallPromptEvent(event);
      }
    };
    window.addEventListener('beforeinstallprompt', beforeInstallPromptHandler);
    return () =&amp;gt; window.removeEventListener('beforeinstallprompt', beforeInstallPromptHandler);
  }, [userShouldBePromptedToInstall]);

  const handleInstallDeclined = () =&amp;gt; {
    handleUserSeeingInstallPrompt();
    setInstallPromptEvent(null);
  };

  const handleInstallAccepted = () =&amp;gt; {
    // show native prompt
    installPromptEvent.prompt();

    // decide what to do after the user chooses
    installPromptEvent.userChoice.then(choice =&amp;gt; {
      // if the user declined, we don't want to show the prompt again
      if (choice.outcome !== 'accepted') {
        handleUserSeeingInstallPrompt();
      }
      setInstallPromptEvent(null);
    });
  };
  return [installPromptEvent, handleInstallDeclined, handleInstallAccepted];
};
export default useWebInstallPrompt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use the hooks
&lt;/h2&gt;

&lt;p&gt;This is an example of how I use these two hooks in a modal asking the user if they want to install the app. This is using &lt;a href="https://reactstrap.github.io/"&gt;Reactstrap&lt;/a&gt;. The modal is always open because, if neither of the hooks return true, this component will return &lt;code&gt;null&lt;/code&gt;. If the &lt;code&gt;iosInstallPrompt&lt;/code&gt; is true then we show an instruction to add the web page to the Home Screen. The &lt;code&gt;handleIOSInstallDeclined&lt;/code&gt; is wired up to the &lt;code&gt;onClick&lt;/code&gt; of the “close” button to make sure the user won’t be shown it again once they dismiss the modal.&lt;/p&gt;

&lt;p&gt;&lt;a href="///static/22b894a73261d4692cb44cdc80d287a0/c1d11/ios-install-modal.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--FF0CuyfO--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.wick.technology/static/22b894a73261d4692cb44cdc80d287a0/c1d11/ios-install-modal.png" alt="iOS Install modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Otherwise, if &lt;code&gt;webInstallPrompt&lt;/code&gt; exists the modal shows a modal with an “install” or “close” button. The &lt;code&gt;handleWebInstallDeclined&lt;/code&gt; and &lt;code&gt;handleWebInstallAccepted&lt;/code&gt; are wired up to the “close” and “install” buttons to either show the native install popup or register that the user has dismissed the modal and shouldn’t be shown it again.&lt;/p&gt;

&lt;p&gt;&lt;a href="///static/cd1ed6d27fc74af724cedeedf9539baf/d584a/install-modal.png"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--M09ouGVF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://blog.wick.technology/static/cd1ed6d27fc74af724cedeedf9539baf/d584a/install-modal.png" alt="Install modal"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is how the component’s code looks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import React from 'react';
import { Button, Modal, Card, CardText, CardBody, CardTitle } from 'reactstrap';
import useIosInstallPrompt from 'app/shared/hooks/useIosInstallPrompt';
import useWebInstallPrompt from 'app/shared/hooks/useWebInstallPrompt';

export const InstallPWA = () =&amp;gt; {
  const [iosInstallPrompt, handleIOSInstallDeclined] = useIosInstallPrompt();
  const [webInstallPrompt, handleWebInstallDeclined, handleWebInstallAccepted] = useWebInstallPrompt();

  if (!iosInstallPrompt &amp;amp;&amp;amp; !webInstallPrompt) {
    return null;
  }
  return (
    &amp;lt;Modal isOpen centered&amp;gt;
      &amp;lt;Card&amp;gt;
        &amp;lt;img
          className="mx-auto"
          style={{
            borderTopRightRadius: '50%',
            borderTopLeftRadius: '50%',
            backgroundColor: '#fff',
            marginTop: '-50px'
          }}
          width="100px"
          src="content/images/appIcon-transparent.png"
          alt="Icon"
        /&amp;gt;
        &amp;lt;CardBody&amp;gt;
          &amp;lt;CardTitle className="text-center"&amp;gt;
            &amp;lt;h3&amp;gt;Install App&amp;lt;/h3&amp;gt;
          &amp;lt;/CardTitle&amp;gt;
          {iosInstallPrompt &amp;amp;&amp;amp; (
            &amp;lt;&amp;gt;
              &amp;lt;CardText className="text-center"&amp;gt;
                Tap
                &amp;lt;img
                  src="content/images/Navigation_Action_2x.png"
                  style={{ margin: 'auto 8px 8px' }}
                  className=""
                  alt="Add to homescreen"
                  width="20"
                /&amp;gt;
                then &amp;amp;quot;Add to Home Screen&amp;amp;quot;
              &amp;lt;/CardText&amp;gt;
              &amp;lt;div className="d-flex justify-content-center"&amp;gt;
                &amp;lt;Button onClick={handleIOSInstallDeclined}&amp;gt;Close&amp;lt;/Button&amp;gt;
              &amp;lt;/div&amp;gt;
            &amp;lt;/&amp;gt;
          )}
          {webInstallPrompt &amp;amp;&amp;amp; (
            &amp;lt;div className="d-flex justify-content-around"&amp;gt;
              &amp;lt;Button color="primary" onClick={handleWebInstallAccepted}&amp;gt;
                Install
              &amp;lt;/Button&amp;gt;
              &amp;lt;Button onClick={handleWebInstallDeclined}&amp;gt;Close&amp;lt;/Button&amp;gt;
            &amp;lt;/div&amp;gt;
          )}
        &amp;lt;/CardBody&amp;gt;
      &amp;lt;/Card&amp;gt;
    &amp;lt;/Modal&amp;gt;
  );
};
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;You can find the iOS share icon in the &lt;a href="https://developer.apple.com/design/human-interface-guidelines/ios/icons-and-images/system-icons/"&gt;Apple documentation&lt;/a&gt; or &lt;a href="https://github.com/chrisdancee/react-ios-pwa-prompt"&gt;https://github.com/chrisdancee/react-ios-pwa-prompt&lt;/a&gt; has an &lt;a href="https://github.com/chrisdancee/react-ios-pwa-prompt/blob/master/src/components/ShareIcon.js"&gt;svg version&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I’m happy with how this has turned out: cross platform and easy to include in my app. The use of hooks here allowed me to extract some common functionality really easily, e.g. the &lt;code&gt;useShouldShowPrompt&lt;/code&gt; hook, which was used in both iOS and web prompts hooks.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attribution and Further Reading
&lt;/h3&gt;

&lt;p&gt;My code was inspired by &lt;a href="https://jason.codes/2019/03/pwa-install-prompt/"&gt;https://jason.codes/2019/03/pwa-install-prompt/&lt;/a&gt; and &lt;a href="https://medium.com/swlh/a-simple-react-hook-to-prompt-ios-users-to-install-your-wonderful-pwa-4cc06e7f31fa"&gt;https://medium.com/swlh/a-simple-react-hook-to-prompt-ios-users-to-install-your-wonderful-pwa-4cc06e7f31fa&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>react</category>
      <category>webdev</category>
      <category>pwa</category>
      <category>javascript</category>
    </item>
    <item>
      <title>Don't use Event Sourcing if you want auditability</title>
      <dc:creator>Phil Hardwick</dc:creator>
      <pubDate>Tue, 05 May 2020 07:54:00 +0000</pubDate>
      <link>https://forem.com/philhardwick/don-t-use-event-sourcing-if-you-want-auditability-4hd4</link>
      <guid>https://forem.com/philhardwick/don-t-use-event-sourcing-if-you-want-auditability-4hd4</guid>
      <description>&lt;p&gt;The reasons for choosing an architecture can be so varied. We take into account customer needs, stakeholder requirements, legislation and non-functional requirements like availability and security.&lt;/p&gt;

&lt;p&gt;At its core though, choosing an architecture is about choosing what you optimise for and the best choice, in the long run, is to optimise for &lt;em&gt;change&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/barryosull/event-sourcing-what-it-is-and-why-its-awesome"&gt;Event Sourcing&lt;/a&gt; is pretty popular right now and one reason I hear for choosing it is auditability, “if we have a log of all the events of changes in the system, we get auditability for free!”&lt;/p&gt;

&lt;p&gt;I think this is a bad reason to choose Event Sourcing - you’re choosing a particularly difficult pattern, simply so you can check what the system has done in the past.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why it might not provide auditability
&lt;/h2&gt;

&lt;p&gt;It’s possible, and probable, you won’t get Event Sourcing right the first time, and who’s to say you actually have recorded all the events of the system? If you’re not testing your golden source of truth regularly then you may not have all your data in events and therefore your audit trail may not be complete.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why you should really choose Event Sourcing
&lt;/h2&gt;

&lt;p&gt;A good reason to choose Event Sourcing is that you don’t know your future requirements. No one can fully predict how a system will evolve or what will be needed a year from now. Having a stream of events of all the previous changes which can be read from any service allows you to be flexible and implement any future requirement - it’s truly extensible. This is because any requirement can be implemented as a new service and it can load in data, transforming it and enriching it to meet what’s needed. For example, a requirement to send email reminders to fill in some questions: a new service can now consume user events to get email addresses and names, along with the events about when they last filled in the questions. The new service builds up an understanding of the current state of the system and then uses that to make decisions. This is all possible without changing the existing services, which helps to reduce the chance of introducing regressions, and makes it simpler to deploy since the change is only adding services, not modifying any.&lt;/p&gt;

&lt;p&gt;In this way, Event Sourcing optimises for dealing with &lt;em&gt;change&lt;/em&gt; in requirements.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>eventsourcing</category>
      <category>events</category>
    </item>
  </channel>
</rss>
