<?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>DEV Community: Jonathan Duggan</title>
    <description>The latest articles on DEV Community by Jonathan Duggan (@jduggan83).</description>
    <link>https://dev.to/jduggan83</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%2F366405%2F28465b6a-151e-48b0-bd83-d9196321ad23.jpeg</url>
      <title>DEV Community: Jonathan Duggan</title>
      <link>https://dev.to/jduggan83</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jduggan83"/>
    <language>en</language>
    <item>
      <title>Hypermedia APIs in Web Applications</title>
      <dc:creator>Jonathan Duggan</dc:creator>
      <pubDate>Tue, 05 May 2020 09:51:38 +0000</pubDate>
      <link>https://dev.to/sonalake/hypermedia-apis-in-web-applications-5029</link>
      <guid>https://dev.to/sonalake/hypermedia-apis-in-web-applications-5029</guid>
      <description>&lt;p&gt;by &lt;strong&gt;Jonathan Duggan&lt;/strong&gt;, &lt;strong&gt;Daniel Bray&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Perhaps the hardest problem to solve when writing REST APIs is managing how those APIs evolve over time. Our goal is to minimise pain for API client developers while not being completely hamstrung by early design decisions.&lt;/p&gt;

&lt;p&gt;There are two popular approaches to this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  &lt;strong&gt;Versioning&lt;/strong&gt;
Avoid forcing client code to change at the expense of requiring the server-side to support multiple API versions&lt;/li&gt;
&lt;li&gt;  &lt;strong&gt;Deprecation&lt;/strong&gt;
Warn clients that they need to update by some future date&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Neither of these options are ideal. However there is a third approach that, in some circumstances, can represent a better solution – hypermedia.&lt;/p&gt;

&lt;p&gt;Hypermedia REST APIs allow developers to build services that effectively decouple client and server, allowing them to evolve independently. The representations returned for REST resources contain not only embedded data, but also links to related resources.&lt;/p&gt;

&lt;p&gt;We’ll focus on this approach and use of the &lt;a href="https://en.wikipedia.org/wiki/Hypertext_Application_Language"&gt;Hypertext Application Language&lt;/a&gt; (HAL) convention to document a REST API. By way of example, we’ll show how existing Angular libraries can be used to build a UI that is stable under what would normally be a breaking API change.&lt;/p&gt;

&lt;h2&gt;
  
  
  We need to talk about REST
&lt;/h2&gt;

&lt;p&gt;For most developers, REST means ‘JSON over HTTP’. This is mostly right, since it’s stateless, client/server, cacheable and layered, but it does omit of the more complicated elements of the &lt;a href="https://en.wikipedia.org/wiki/Representational_state_transfer#Uniform_interface"&gt;uniform interface&lt;/a&gt; constraints, specifically Hypermedia as the engine of application state (&lt;a href="https://en.wikipedia.org/wiki/HATEOAS"&gt;HATEOAS&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To be fair, if you’re writing your own UI against your own back-end, with a smallish internal team, this is something you can probably ignore. It’s likely to be more trouble than it’s worth. For this discussion though we’re talking about writing an API that will be shared with multiple 3rd party organisations where the impact of making non-backwards-compatible changes will be significant.&lt;/p&gt;

&lt;h2&gt;
  
  
  What’s the Problem?
&lt;/h2&gt;

&lt;p&gt;The root of the problem lies in hard-coding URIs in client code. For example, if your client does something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ConfigService&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;$resource&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="no"&gt;BASE_URLS&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;BASE_URLS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;devUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
   &lt;span class="n"&gt;resourceUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;configs&lt;/span&gt;&lt;span class="o"&gt;/:&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

 &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;$resource&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;resourceUrl&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="o"&gt;{},&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
   &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;getConfig&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;method:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;GET&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
     &lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;details&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;},&lt;/span&gt;
   &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;getStatus&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="nl"&gt;method:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="no"&gt;GET&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
    &lt;span class="nl"&gt;params:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
       &lt;span class="nl"&gt;action:&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;
     &lt;span class="o"&gt;}&lt;/span&gt;
   &lt;span class="o"&gt;}&lt;/span&gt;
 &lt;span class="o"&gt;});&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code is assuming that, for some element &lt;code&gt;id&lt;/code&gt; the URI to get the status is always going to be &lt;code&gt;configs/:id/status&lt;/code&gt;. As a result, as soon as we change that URI on the server, clients will be break.&lt;/p&gt;

&lt;h2&gt;
  
  
  How does Hypermedia Help?
&lt;/h2&gt;

&lt;p&gt;Further to simply having a REST API that adopts the principles of a hypermedia API, we need to specify a format that our API will follow. By standardising this format, or hypermedia type, multiple clients can easily integrate with the API.&lt;/p&gt;

&lt;p&gt;The most widely used hypermedia types are &lt;a href="https://en.wikipedia.org/wiki/Hypertext_Application_Language"&gt;HAL&lt;/a&gt;, &lt;a href="https://amundsen.com/media-types/collection/"&gt;Collection+JSON&lt;/a&gt;, &lt;a href="https://github.com/kevinswiber/siren"&gt;Siren&lt;/a&gt;, &lt;a href="https://jsonapi.org/"&gt;JSON API&lt;/a&gt;, and &lt;a href="https://www.markus-lanthaler.com/hydra/"&gt;Hydra&lt;/a&gt; and &lt;a href="https://json-ld.org/"&gt;JSON-LD&lt;/a&gt;. For this post, we’ll take a closer look at HAL.&lt;/p&gt;

&lt;p&gt;As a hypermedia format, HAL provides a consistent and straightforward mechanism to link resources in an API. Its goal is to make an APIs structure easily understandable and all related resources discoverable.&lt;/p&gt;

&lt;p&gt;HAL’s design focuses on two things: &lt;em&gt;resources&lt;/em&gt; and &lt;em&gt;links&lt;/em&gt;. A resources can contain an embedded resource or a link to another resource. It is designed with the goal of building APIs in which clients can navigate resources by following links.&lt;/p&gt;

&lt;p&gt;Considering the earlier example, this would mean returning something like the following within the response to &lt;code&gt;GET configs/:id&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;{&lt;/span&gt;
 &lt;span class="s"&gt;"id"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;"name"&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
 &lt;span class="s"&gt;"content"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{},&lt;/span&gt;

 &lt;span class="c1"&gt;// HAL content&lt;/span&gt;
 &lt;span class="s"&gt;"_links"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="s"&gt;"self"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="s"&gt;"href"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/config/123"&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;"details"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="s"&gt;"href"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/config/123/details"&lt;/span&gt;
    &lt;span class="o"&gt;},&lt;/span&gt;
    &lt;span class="s"&gt;"status"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
     &lt;span class="s"&gt;"href"&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"/config/123/status"&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
 &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using such a structure clients can avoid hard-coding the &lt;code&gt;details&lt;/code&gt; or &lt;code&gt;status&lt;/code&gt; URIs and can instead inspect &lt;code&gt;_links&lt;/code&gt;. For example, to get the status the client would inspect the response for the value of &lt;code&gt;_links.status.href&lt;/code&gt; and then request that resource. This can be called directly, without any further inspection, since it will always point to the correct URI – regardless of whether it has changed by the server team.&lt;/p&gt;

&lt;h2&gt;
  
  
  Sounds Like More Work
&lt;/h2&gt;

&lt;p&gt;Well it would be, if it were not for that fact that there are many popular libraries that can take care of the details. For example &lt;a href="https://projects.spring.io/spring-boot/"&gt;Spring Boot&lt;/a&gt; has &lt;a href="https://docs.spring.io/spring-hateoas/docs/current/reference/html/"&gt;HATEOAS&lt;/a&gt; baked into a starter.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;org&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;springframework&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;groupId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
   &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;spring&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;boot&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;starter&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="n"&gt;hateoas&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;artifactId&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="n"&gt;dependency&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Usage is straightforward:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Extend entities from &lt;code&gt;org.springframework.hateoas.ResourceSupport&lt;/code&gt;
This places no requirements on your class other than requiring that you they can’t have a &lt;code&gt;getId&lt;/code&gt; method&lt;/li&gt;
&lt;li&gt;  In controllers set the links before returning the resource
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@RequestMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/configs/{id}"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;method&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;RequestMethod&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;GET&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;HttpEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Config&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;survey&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@PathVariable&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"id"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

   &lt;span class="c1"&gt;// Config extends ResourceSupport&lt;/span&gt;
   &lt;span class="nc"&gt;Config&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConfig&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

   &lt;span class="c1"&gt;// Link to self&lt;/span&gt;
   &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linkTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methodOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConfigController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;config&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConfigId&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;withSelfRel&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt;

   &lt;span class="c1"&gt;// References methods on ‘this’, or on other @RestController services &lt;/span&gt;
   &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linkTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methodOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ConfigController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;details&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConfigId&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;withRel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"details"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;
   &lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;add&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;linkTo&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;methodOn&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;StatusController&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
          &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getConfigId&lt;/span&gt;&lt;span class="o"&gt;())).&lt;/span&gt;&lt;span class="na"&gt;withRel&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="o"&gt;));&lt;/span&gt;

   &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;(&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;HttpStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;OK&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Note that Spring derives the URIs from the &lt;code&gt;@RequestMapping&lt;/code&gt; on the referenced methods.&lt;/p&gt;

&lt;h2&gt;
  
  
  Consuming HAL on the Client Side
&lt;/h2&gt;

&lt;p&gt;There are many libraries to consume HAL responses on the client side – since we develop a lot of Angular UI where we’ll use &lt;a href="https://angular-hal.io/"&gt;angular-hal&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;A sample controller might look something like the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="nx"&gt;angular&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;app&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;angularHal&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;
  &lt;span class="p"&gt;])&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;$api&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ApiFactory&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;$http&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/configs&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;})&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;controller&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ConfigController&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nx"&gt;ConfigController&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;$api&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;$scope&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

   &lt;span class="c1"&gt;// Gets a config's status&lt;/span&gt;
   &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;getStatus&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;config&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;$del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

   &lt;span class="c1"&gt;// Delete a config using the 'self' link&lt;/span&gt;
    &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;deleteConfig&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;config&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;$request&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;$del&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;then&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;load&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
 &lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Supporting Major API Changes
&lt;/h2&gt;

&lt;p&gt;The changes shown in the example shown above are simple – they show protection against minor API changes, for example renaming URLs or inserting additional parameters into the API. What if an API requires more invasive changes?&lt;/p&gt;

&lt;p&gt;In the above example we have a config resource, and a second call to get the status. Imagine, after some user-testing, we noticed that clients always wanted the status whenever we loaded the config. In this case it would make sense to include the status in the response, but how can we do this without breaking existing clients?&lt;/p&gt;

&lt;p&gt;The easiest way is to use embedded resources:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt; Include &lt;code&gt;status&lt;/code&gt; as a simple JSON property so that new clients can use it as a normal value&lt;/li&gt;
&lt;li&gt; Include &lt;code&gt;status&lt;/code&gt; in an &lt;code&gt;_embedded&lt;/code&gt; section. This is a little more complicated than the simple JSON properly, but it has the benefit that the angular-hal snippet above will work as-is, with no amendments.
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;id&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;123&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
         &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
         &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;last_amended&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;1992-01-12T20:17:46.384Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// HAL content&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_links&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;self&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/config/123&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;details&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;href&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/config/123/details&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
       &lt;span class="p"&gt;},&lt;/span&gt;

  &lt;span class="c1"&gt;// Amended resource. Status moved from a link to an embedded value&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;_embedded&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;status&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;OK&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
     &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
 &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We have changed the JSON resource we’re returning as well as the changing the expected client behaviour (it no longer needs to do a second GET to retrieve a config’s status). However, angular-hal will know that when it’s asked to get the data for &lt;code&gt;status&lt;/code&gt; it will use the embedded value from the original response. As a result, any UI written with angular-hal will accommodate these changes without requiring a rewrite.&lt;/p&gt;

&lt;h2&gt;
  
  
  So, should I use this?
&lt;/h2&gt;

&lt;p&gt;In many cases hypermedia APIs can be overkill, but where multiple 3rd party client applications are involved, and if the API is something you need to maintain for years, HAL can be a benefit.&lt;/p&gt;

&lt;p&gt;As ever, there are pros and cons so good judgement is required.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pros&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Client apps can be built without any URL dependencies&lt;/li&gt;
&lt;li&gt;  Provides a clear and easy way to manage API versioning&lt;/li&gt;
&lt;li&gt;  Simpler forward and backward compatibility through component decoupling&lt;/li&gt;
&lt;li&gt;  Accommodate fundamental object model changes in APIs&lt;/li&gt;
&lt;li&gt;  Manage API call processing times better with embedded or linked resources&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cons&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;  Can be time consuming to setup and maintain a hypermedia driven API&lt;/li&gt;
&lt;li&gt;  As hypermedia popularity increases though, so to has the availability of 3rd party libraries to simplify development.&lt;/li&gt;
&lt;li&gt;  Hypermedia APIs tend to be less readable than traditional APIs&lt;/li&gt;
&lt;li&gt;  Developers may feel the urge to optimise their clients and take shortcuts – essentially defeating the purpose of implementing hypermedia in the first place.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>hypermedia</category>
      <category>api</category>
      <category>json</category>
      <category>angular</category>
    </item>
    <item>
      <title>Multi-Tenant Applications With JHipster</title>
      <dc:creator>Jonathan Duggan</dc:creator>
      <pubDate>Thu, 13 Feb 2020 11:09:38 +0000</pubDate>
      <link>https://dev.to/sonalake/multi-tenant-applications-with-jhipster-1fbn</link>
      <guid>https://dev.to/sonalake/multi-tenant-applications-with-jhipster-1fbn</guid>
      <description>&lt;p&gt;Modern web applications are complex; there are a multitude of ways of building them and a seemingly endless set of technology choices. Starting a project with an empty directory can be daunting and it can take a lot of effort to get beyond a canonical “Hello, World!” app. JHipster, a popular application generator, best-of-breed technology choices with industry best practice design to allow developers get on with developing their application logic and user interface without getting tied up in the plumbing unless they really want to.&lt;/p&gt;

&lt;p&gt;We’ve certainly found JHipster to be very useful for certain types of projects but found that we needed to add multi-tenancy support to the JHipster applications on more than one occasion. Unfortunately, JHipster doesn’t provide multi-tenancy support as an option but it has an extension mechanism allowing developers to create Blueprints that extend JHipster functionality.&lt;/p&gt;

&lt;p&gt;With that in mind, and given that multi-tenancy is quite a common requirement for us, we took the opportunity to learn more about JHipster Blueprints and developed our own for creating multi-tenant applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing the JHipster Multi-tenancy Blueprint
&lt;/h2&gt;

&lt;p&gt;Our Blueprint structures your JHipster application to support multi-tenancy. Once you run it, your generated JHipster application will have the ability to provision and manage tenants and users, with all tenant aware data automatically separated. The Blueprint is very easy to implement and extend, providing the core values of multi-tenancy, to a known coding standard.&lt;/p&gt;

&lt;p&gt;Out of the box, you will get the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A suite of tenant management screens available to admins&lt;/li&gt;
&lt;li&gt;User management screens that allow the administrator to assign users to a tenant&lt;/li&gt;
&lt;li&gt;The ability to make any entity tenant aware. A tenant aware entity is then automatically filtered by the logged-in user’s tenant&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tbkGYaQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://sonalake.com/wp-content/uploads/2020/02/Multi-Tenant-Applications-With-JHipster.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tbkGYaQ6--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://sonalake.com/wp-content/uploads/2020/02/Multi-Tenant-Applications-With-JHipster.png" alt="" width="880" height="704"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Under The Hood
&lt;/h2&gt;

&lt;p&gt;There are three common approaches to multi-tenancy:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Separate databases&lt;/li&gt;
&lt;li&gt;Separate schemas&lt;/li&gt;
&lt;li&gt;Partition the data on a single database schema&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After some investigation, we found the most suitable option was to implement a custom discriminator using Spring, Hibernate, and AspectJ. Here is a breakdown of the key operations that the Blueprint performs to provide multi-tenant functionality to your JHipster application.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatically creates a tenant entity. The name of that entity is provided by the user when running the Blueprint. The examples below use “Company” as the tenant entity.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"company"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@Cache&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;usage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;CacheConcurrencyStrategy&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;NONSTRICT&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_READ&lt;/span&gt;&lt;span class="err"&gt;\&lt;/span&gt;&lt;span class="n"&gt;_WRITE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="nd"&gt;@Id&lt;/span&gt;
&lt;span class="nd"&gt;@GeneratedValue&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;strategy&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;GenerationType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;IDENTITY&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Long&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;..}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Extends the user object with a many-to-one relationship to the tenant along with the filter definition
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Entity&lt;/span&gt;
&lt;span class="nd"&gt;@Table&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"jhi\_user"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="nd"&gt;@FilterDef&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"COMPANY\_FILTER"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parameters&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;&lt;span class="nd"&gt;@ParamDef&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"companyId"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"long"&lt;/span&gt;&lt;span class="o"&gt;)})&lt;/span&gt;
&lt;span class="nd"&gt;@Filter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"COMPANY\_FILTER"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;condition&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"company\_id = :companyId"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;AbstractAuditingEntity&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;Serializable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 

&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt; 
&lt;span class="nd"&gt;@ManyToOne&lt;/span&gt;
 &lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="nc"&gt;Company&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
 &lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Provides Angular or React views, routes, and services for tenant and user management&lt;/li&gt;
&lt;li&gt;Extends user management views to allow a user to be assigned to a tenant&lt;/li&gt;
&lt;li&gt;Implements data partitioning using AOP to enable Hibernate filters for any tenant aware entity, for example “User”
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@Before&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"execution(\* com.mycompany.myapp.service.UserService.\*(..))"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;beforeExecution&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="kd"&gt;throws&lt;/span&gt; &lt;span class="nc"&gt;Throwable&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
&lt;span class="err"&gt;…&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt; 
&lt;span class="nc"&gt;User&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userRepository&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;findOneByLogin&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;login&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;()).&lt;/span&gt;&lt;span class="na"&gt;get&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCompany&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; 
&lt;span class="nc"&gt;Filter&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;entityManager&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;unwrap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Session&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;class&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;enableFilter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"COMPANY\_FILTER"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;setParameter&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fieldName&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getCompany&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getId&lt;/span&gt;&lt;span class="o"&gt;());&lt;/span&gt; 
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;To use the Blueprint, follow these steps.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install the Blueprint&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$ npm install -g generator-jhipster-multitenancy&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Generate your JHipster Multi-tenant application, running the below command in an empty directory&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$ jhipster --blueprints multitenancy&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Along with all the existing JHipster questions, you will be asked to provide an alias for tenants.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;What is the alias given to tenants in your application?&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Once the Blueprint has generated your application it will contain a tenant entity. All entities you create from here on out can be made tenant aware. Create a new entity using the standard JHipster command.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;$ jhipster entity Survey&lt;/code&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Upon generation, you will then be asked if you want to make your entity tenant aware.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;code&gt;Do you want to make Survey tenant aware? (Y/n)&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  The Challenges
&lt;/h2&gt;

&lt;p&gt;Development of this JHipster Blueprint presented some challenges. Broadly, these can be categorised as:&lt;/p&gt;

&lt;h3&gt;
  
  
  App Configurations
&lt;/h3&gt;

&lt;p&gt;One of the great benefits of JHipster is that it provides a wide range of options when generating your application. Providing support for every combination of the configuration options can make things tricky when developing a Blueprint. For example, entities can have no pagination, pagination, or pagination with infinite scrolling which complicates how a Blueprint can safely modify the default JHipster frontend templates.&lt;/p&gt;

&lt;h3&gt;
  
  
  Version Compatibility
&lt;/h3&gt;

&lt;p&gt;JHipster development is moving at a rapid pace. With new versions released every couple of weeks maintaining Blueprint compatibility continues to be a challenge. To address this our strategy is to minimise the number of JHipster files that are modified by the Blueprint. This lessens the chances that new or changed JHipster code will be overwritten by the Blueprint.&lt;/p&gt;

&lt;h3&gt;
  
  
  Partial Updates
&lt;/h3&gt;

&lt;p&gt;Partial updates of generated JHipster files, both frontend and backend, can be done during the writing phase of JHipster Blueprints. This process is achieved by detecting a specific piece of code in a file using regular expressions, and inserting custom code either instead of, or alongside regex matches. Establishing the correct regex pattern to use to detect the targeted code can be a time consuming process and frustrating. This is mainly due to the different stages of formatting that JHipster carries out during the code generation process.&lt;/p&gt;

&lt;h3&gt;
  
  
  Best Practices
&lt;/h3&gt;

&lt;p&gt;The JHipster development team follows certain coding policies to ensure best practices on all the code they deliver. We value this and make every effort to ensure that the multi-tenant Blueprint adheres to the high standards of the JHipster team. A big challenge throughout Blueprint development is ensuring that the generated code remained true to this objective.&lt;/p&gt;

&lt;h2&gt;
  
  
  Contributors Needed
&lt;/h2&gt;

&lt;p&gt;All this takes work and often we struggle to make the time to keep up to date with the pace of JHipster development. If you’re a Java, Angular, React, or Vue.js developer and you’d like to help, please get in touch!&lt;/p&gt;

&lt;p&gt;Check out the code for the Blueprint on &lt;a href="https://github.com/sonalake/generator-jhipster-multitenancy"&gt;&lt;strong&gt;GitHub&lt;/strong&gt;&lt;/a&gt;, or if you just want to see what the Blueprint gives you, check out our sample &lt;a href="https://github.com/sonalake/jhipster-mt-sample-angular"&gt;&lt;strong&gt;Angular&lt;/strong&gt;&lt;/a&gt; and &lt;a href="https://github.com/sonalake/jhipster-mt-sample-react"&gt;&lt;strong&gt;React&lt;/strong&gt;&lt;/a&gt; apps.&lt;/p&gt;

&lt;p&gt;The post &lt;a href="https://sonalake.com/latest/multi-tenant-applications-with-jhipster/"&gt;Multi-Tenant Applications With JHipster&lt;/a&gt; appeared first on &lt;a href="https://sonalake.com"&gt;Sonalake&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>java</category>
      <category>jhipster</category>
    </item>
  </channel>
</rss>
