Getting the (J)Hipsters aboard

When I think of craft beers, I think of long beards and oiled mustaches. The biggest community of craft drinkers are definitely the hipsters and HelloBeerTM wants to add the contents of their shiny leather wallets to its bank account. So high time to get those hipsters on board and dive into JHipster.

JHipster is a generator tool able to generate web applications based on a Spring Boot back-end (exposed via REST) and an Angular front-end. In this first part of a series of blog posts – in which we’re gonna delve into JHipster to discover its nooks and crannies – we’ll generate our first (monolithic) JHipster application.

I’ll assume that you’ve got your JHipster development environment all set up (steps can be found here (choose Local installation with YARN)). I’m using the current latest version of JHipster, i.e. 4.14.1.

The GitHub code can be found here.

First contact

Let’s hit the ground running and generate the skeleton of our first JHipster application. We’ll put the project in the hb-jhipster directory and call it HelloBeer:

jhipster

The CLI (Command Line Interface) of JHipster will ask a lot of questions and demand answers to every one of them. Let’s choose the defaults for most of them, except for the package name (nl.whitehorses.hellobeer). We’ll also add support for an additional language (Dutch) besides English.

A couple of seconds after we answered the last question (10 seconds on my laptop), the application will be generated and can be started in two steps:

The back-end can be started with Maven by the following command:

./mvnw

The front-end can be fired up with the help of YARN:

yarn start

After both components have been started, the application greets us on localhost:9000:
Screenshot-2018-3-25 Welcome, Java Hipster
The application doesn’t have any business value yet, but it’s nice to see that with just a few steps we got a working application for free, with a homepage, login screen, user registration functionality, i18n and a most helpful Administration menu. That menu gives us insight into the inner workings of our JHipster app. It enables viewings of metrics, logs and it gives us a page displaying all the (Spring Boot) Swagger APIs available in the app (every REST service we’ll add to the application will be automatically added to this page):
Screenshot-2018-3-25 API

Domain model

Our beers aren’t exactly flowing yet. The  most important part is still missing: getting the domain model in place! There are two ways of doing this: JHipster UML and JDL Studio. I’ll use the latter, since it’s an online editor that’s very easy to use. Simply hop over to https://start.jhipster.tech/jdl-studio/ and you’re good to go!

We’ll use a slightly more complex domain model than the one we’ve used in my previous blog – which basically was just one domain object – albeit the most important one – Beer. In this blog I’ll use a few objects with relationships, just to get the most out of JHipster.

There will be a Beer object, a Brewery object, an InventoryItem object and an ItemStockLevel object. The domain model will allow us to keep track of our inventory of crafts – the types and stock – and will demonstrate how JHipster will generate its back- and front-end with multiple related tables involved.

Screenshot-2018-3-27 JDL-Studio

As you can see in the upper figure: you’ll get a nice diagram on the right for free when typing out the model on the left. This is the entire model in text form, which you get when you download it to your computer:

entity Beer {
  name String required
  type BeerType required
}

enum BeerType {
  LAGER, PILSNER, PALE_ALE, INDIA_PALE_ALE, PORTER, STOUT, OTHER
}

entity Brewery {
  name String required
  countryName String
}

entity InventoryItem {
  itemDescription String,
  serving ServingType required,
  amount Integer required,
  rating Integer
}

enum ServingType {
  CAN, BOTTLE
}

entity ItemStockLevel {
  stockDate ZonedDateTime required,
  quantity Long
}

relationship ManyToOne {
  Beer{brewery} to Brewery
}

relationship ManyToOne {
  InventoryItem{beer} to Beer
}

relationship ManyToOne {
  ItemStockLevel{inventoryItem} to InventoryItem
}

// Set pagination options
paginate Beer, InventoryItem with pagination
paginate Brewery with infinite-scroll

// dto * with mapstruct

// Set service options to all except few
// service all with serviceImpl

By default JHipster will generate Controller classes per Entity. These Controllers will delegate directly to the Repository classes exchanging the domain objects.
If you need more control you can uncomment the “dto * with mapstruct” and “service all with serviceImpl” lines. This will generate Service classes in between the Repository and Controller classes together with DTO classes. These Service classes will map the Entity objects (used by the Repository) to DTO objects (used by the Controller). So these DTO objects will be exposed to the front-end instead of the Entity objects, giving you a lesser coupled application.
For now lets stick to the architecture without the Service layer and leave those lines commented out.

jhipster import-jdl jhipster-jdl.jh

The CLI will ask you to override some files, choose yes for all of them (option a).

CRUD

When you fire up the application again, you’ll see that the Entities menu contains four additional entries (one for each domain object). Play round a bit. This is the Inventory Items page after entering some data:

Screenshot-2018-3-28 Inventory Items

And this is the Edit screen available when you click on the Edit button on the first row:

Screenshot-2018-3-28 Inventory Items(1)

As you can see, the required field are nicely validated (green when filled, red when empty), pagination is added and basically all the CRUD functionality is there. Pages are bookmarked as well. The above page eg. is available on the URL http://localhost:9000/#/inventory-item. Error and confirmation regions are displayed on the page when the data entered is invalid, resp. committed.

The biggest issue with the pages as-is after generation are those ugly ids you need to select to connect to a related domain object. Those same ids are displayed in the overview page. For example instead of the Beer Name (which is a Brand Pilsner) we’ll see a 1 displayed in the above screenshots.

Back-end

Don’t worry. There’s quite a few JHipster blog posts in the making and in those we will dissect quite a bit of all the objects that JHipster generates. And generate some more!
The thing I’d like to show you right now is how to test those Spring Boot REST services. We’ll need an endpoint and also a security header to test one of the services. Let’s check the Swagger page for the InventoryItem (login as an admin user). All the information to fire a GET request is available under the Try it Out button:

Screenshot from 2018-03-28 19-51-28

You need the Request URL and the Authorization header (the value unfortunately changes with every restart).  Here’s a test with Postman:

Screenshot from 2018-03-28 19-54-47

Front-end

The screens JHipster generates are functional albeit a bit crude. In the next blog post we’re gonna beautify ’em: getting rid of those ugly ids for one, use a calendar, add some auto-suggesting and who knows what else.

For now we’re gonna do some simple configuration, without changing any code: we’re gonna change the footer and beautify those list items a bit, so INDA_PALE_ALE will be displayed as Inda pale ale.

This is all part of the i18n functionality of JHipster. All the customized labels are available in JSON files in the src/main/webapp/i18n directories. Let’s change the beerType.json files (English and Dutch) :

Screenshot from 2018-03-28 20-08-34

The footer can be adjusted in the global.json file:

Screenshot from 2018-03-28 20-11-12

Now let’s fire up the application again, switch to the Dutch language and see the changes on the Beer page (check the footer and the Pilsner type):

Screenshot-2018-3-28 Beers(1)

Summary

That’s enough for now! In this first blogpost on JHipster we’ve seen how easy it is to get a basic CRUD application up and running. Most of the work goes into building the domain model and the rest of the heavy lifting is done by JHipster.

We’ve also done a little customization on the front-end. In our next blog post, we’re gonna look at how difficult or easy it is to spiff up the front-end a little more. So grab a beer and stay tuned!

References

Advertisements

HelloBeer goes Angular – Finale

Alright guys. This is the last and final episode of our – soon to be released on Netflix – blockbuster series of HelloBeerTM goes Angular starring lots of frustrated beer drinking developers. In this grande finale we’re gonna finish the app we developed in our previous blog posts here and here and add some much needed error handling, css styling and i18n.
The final code can be found here on Github.

Bootstrap CSS

I was using a bootstrap.css file that I snatched somewhere from the internet when I started developing the app, but I recently found out you can just add it as a dependency module. To install the bootstrap version I’ve been using you can add it to the project like this:

npm install bootstrap@3.3.2 --save

Now you can add the import to the styles.css file like this

@import '../node_modules/bootstrap/dist/css/bootstrap.css';

Error handling

The POST method of our REST service expects a beer name to be present in the JSON request. When you leave it blank the beer won’t be added to the inventory, the server will return an error and the JSON error message will be logged to the console. Let’s change that a bit and make it a more in-your-face-experience for the user.

First change the edit-beer.component.ts file to store a possible error in a model variable:

import {Component, EventEmitter, OnInit, Output} from '@angular/core';

import {ApiClientService} from "../services/beer";
import {Beer, Type} from '../services/beer/models';

@Component({
  selector: 'app-edit-beer',
  templateUrl: './edit-beer.component.html',
  styleUrls: ['./edit-beer.component.css']
})
export class EditBeerComponent implements OnInit {

  @Output() onBeerPosted = new EventEmitter<Beer>();

  public beer: Beer = {} as Beer;
  public beerTypes: string[];

  public error: string;

  constructor(private apiClientService: ApiClientService) {
    this.beerTypes = (Object.keys(Type));
  }

  /**
   * Call REST service to POST a beer
   */
  public postBeer(): void {
    this.apiClientService.addToBeerRepositoryUsingPOST(this.beer)
      .subscribe(resp => {
        this.pushBeer(resp.body)
      }, (error => {
        console.log(error);
        this.onError(error.error.message)
      }));
  }

  private pushBeer(beer: Beer): void {
    // add beer to app
    this.onBeerPosted.emit(beer);
    this.reset();
  }

  private onError(message: string): void {
    this.error = message;
  }

  private reset(): void {
    this.beer = {} as Beer;
    this.error = null;
  }

  ngOnInit() {
  }

}

And add the following html snippet at the top of our edit-beer.component.html page (just below the title).

<div [hidden]="!error" class="panel panel-danger panel-body">
  <span class="text-danger">{{error}}</span>
</div>

This will only show the div when there’s actually an error message there.
Now when we try to post a nameless beer to our inventory, we’ll see the error appearing on our screen, like this:
Screenshot-2018-3-5 HbAngularClient
It’s not the most helpful error message, but I’ll leave it up to the reader to pluck a better error message out of the quite verbose REST response.

i18n

Finally, let’s get rid of those ugly beer types. Again this took me a while to get it right, but in the end I found the module that got the job done. It’s called ngx-translate and I basically followed the steps explained on this how-to here.

First add the modules to the app:

npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save

Alter the app.module.ts file (consult the how-to page):

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from "@angular/forms";
import {HttpClient, HttpClientModule} from '@angular/common/http';
// import ngx-translate and the http loader
import {TranslateLoader, TranslateModule} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';

import {AppComponent} from './app.component';
import {EditBeerComponent} from './edit-beer/edit-beer.component';

import {ApiClientService} from './services/beer/index';

@NgModule({
  declarations: [
    AppComponent,
    EditBeerComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: HttpLoaderFactory,
        deps: [HttpClient]
      }
    })
  ],
  providers: [ApiClientService],
  bootstrap: [AppComponent]
})
export class AppModule {
}

// required for AOT compilation
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

Next, inject the TranslateService in the app component:

....
import {TranslateService} from "@ngx-translate/core";
....
  constructor(private apiClientService: ApiClientService, private translateService: TranslateService) {
    translateService.setDefaultLang('en');
  }
....

Add the en.json file with the beer type translations to the assets/i18n directory:

{
  "LAGER": "Lager",
  "PILSNER": "Pilsner",
  "PALE_ALE": "Pale Ale",
  "INDIA_PALE_ALE": "India Pale Ale",
  "STOUT": "Stout",
  "OTHER": "Other"
}

Now you can add the translate pipes to the fields displaying the beer types (there’s one on the app.component.html and one on the edit-beer.component.html), like this:

{{beer.type | translate}}

Now test the application. If you’ve made no mistake it should look like this now (check the beer types, they’re nicely translated):
Screenshot-2018-3-5 HbAngularClient(1)

Summary

In these last three blog posts we’ve seen how relatively easy it is to build a small Angular app consuming a Swagger API. The typescript code for consumption was generated by the angular-swagger-client-generator module.

The combination of a Spring Boot back end and an Angular front end is quite popular. As a matter of fact there’s an open source generator out there built around these two frameworks, one that’s gaining quite a lot of traction lately.

In my next blog post I’m gonna market my HelloBeerTM beers to one of the largest groups of craft beer drinkers out there: the hipsters! You guessed it, time to check out JHipster!

References

HelloBeer goes Angular – part II

Alright, let’s keep going. Our Angular clients are getting thirsty! In our previous blog post we’ve built the first part of our Angular app consuming a REST service based on a Swagger API. Let’s finish the app.

Consuming the POST method

To POST beers we’re gonna add a new Form component to our Angular app. We could have put the code in the main app component, but it’s always a good idea to keep your components small. So, to create the new component – we’ll call it edit-beer – just hit:

ng generate component edit-beer

First we’ll fill in the edit-beer.component.ts component code. We need a beer model variable, a list of beerTypes to serve as a drop-down list and a method for posting a beer. Here you go:

import {Component, OnInit} from '@angular/core';

import {ApiClientService} from "../services/beer";
import {Beer, Type} from '../services/beer/models';

@Component({
  selector: 'app-edit-beer',
  templateUrl: './edit-beer.component.html',
  styleUrls: ['./edit-beer.component.css']
})
export class EditBeerComponent implements OnInit {

  public beer: Beer = {} as Beer;
  public beerTypes: string[];

  constructor(private apiClientService: ApiClientService) {
    this.beerTypes = (Object.keys(Type));
  }

  /**
   * Call REST service to POST a new beer
   */
  public postBeer(): void {
    this.apiClientService.addToBeerRepositoryUsingPOST(this.beer)
      .subscribe(resp => {
        this.reset();
      }, (error => {
        console.log(error);
      }));
  }

  private reset(): void {
    this.beer = {} as Beer;
  }

  ngOnInit() {
  }

}

The first time I was testing with the generated code and used the Type interface in my typescript code, I got these messages from IntelliJ:

Screenshot from 2018-02-20 21-09-10

Apparently I was using an older version of typescript, that couldn’t handle string enums. Updating to the newest version of typescript fixed this issue.

Let’s put the form on the html component – edit-beer.component.html – that will enable us to post new beers to our inventory:

<div>
  <div class="well lead">Add a beer</div>
  <form method="POST" class="form-horizontal">
    <div class="row">
      <div class="form-group col-md-12">
        <label class="col-md-3 control-lable" for="input.name">Name</label>
        <div class="col-md-7">
          <input [(ngModel)]="beer.name" type="text" id="input.name" name="name" class="form-control input-sm"/>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="form-group col-md-12">
        <label class="col-md-3 control-lable" for="input.type">Beer type</label>
        <div class="col-md-7">
          <select [(ngModel)]="beer.type" id="input.type" name="type" class="form-control input-sm">
            <option *ngFor="let beerType of beerTypes" [value]="beerType">{{beerType}}</option>
          </select>
        </div>
      </div>
    </div>
    <div class="row">
      <div class="form-group col-md-12">
        <label class="col-md-3 control-lable" for="input.brewery">Brewery</label>
        <div class="col-md-7">
          <input [(ngModel)]="beer.brewery" type="text" id="input.brewery" name="brewery" class="form-control input-sm"/>
        </div>
      </div>
    </div>
    <div>
      <input (click)="postBeer()" title="OK" class="btn btn-primary custom-width float-right"/>
    </div>
  </form>
</div>

Note the postBeer() method coupled to the button click event binding.

Add the edit-beer component at the bottom of the app component and fire up the app to see my next rookie mistake appearing in the console:

Can't bind to 'ngModel' since it isn't a known property of 'input'.

This took me while to figure out. The error – though a bit vague – is all about forgetting to import the FormsModule in the app module, so let’s fix that:

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from "@angular/forms";
import {HttpClientModule} from '@angular/common/http';

import {AppComponent} from './app.component';
import {EditBeerComponent} from './edit-beer/edit-beer.component';

import {ApiClientService} from './services/beer/index';

@NgModule({
  declarations: [
    AppComponent,
    EditBeerComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule
  ],
  providers: [ApiClientService],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Now after running the app again, we’ll see a familiar screen appearing:
Screenshot-2018-3-4 HbAngularClient

You can enter a new beer and after hitting the OK button, the beer is posted. When you refresh the screen (don’t worry we’re gonna fix that), you can see that the list is updated with the beers you just added.

Updating the beer inventory instantly

Hitting refresh to update the beer inventory after adding a new beer every time, is bound to piss some clients off, especially when one of ’em is an angry drunk. So let’s fix that asap!

Now how do we do that? We obviously need a way to communicate between the edit-beer component and the app component: events to the rescue!

The application will require a few changes. Let start with the edit-component that will fire the event. This is the new code:

import {Component, EventEmitter, OnInit, Output} from '@angular/core';

import {ApiClientService} from "../services/beer";
import {Beer, Type} from '../services/beer/models';

@Component({
  selector: 'app-edit-beer',
  templateUrl: './edit-beer.component.html',
  styleUrls: ['./edit-beer.component.css']
})
export class EditBeerComponent implements OnInit {

  @Output() onBeerPosted = new EventEmitter<Beer>();

  public beer: Beer = {} as Beer;
  public beerTypes: string[];

  constructor(private apiClientService: ApiClientService) {
    this.beerTypes = (Object.keys(Type));
  }

  /**
   * Call REST service to POST a new beer
   */
  public postBeer(): void {
    this.apiClientService.addToBeerRepositoryUsingPOST(this.beer)
      .subscribe(resp => {
        this.pushBeer(resp.body)
      }, (error => {
        console.log(error);
      }));
  }

  private pushBeer(beer: Beer): void {
    // add beer to app
    this.onBeerPosted.emit(beer);
    this.reset();
  }

  private reset(): void {
    this.beer = {} as Beer;
  }

  ngOnInit() {
  }

}

The REST service will return a beer after it’s been posted. So we’ll gonna send that new beer on the event to the app component. That guy will use it to update its beers list.

The event will be emitted from the edit-beer.component, so reflect that in the app.component.html, here you’ll glue the methods from the app and edit-beer components together:

<app-edit-beer (onBeerPosted)="onBeerPosted($event)"></app-edit-beer>

Last piece of the puzzle is catching the event in the app component. Just add this code snippet to the app.component.ts and you’re done.

public onNewBeer(beer: Beer): void {
  this.beers.push(beer);
}

Test the app again and see the magic happening when you add a new beer. Flashy is it not?

Summary

We’re almost there. I was planning to finish this blog in 2 parts, but like with every great blockbuster movie of the 80s, we need a third installment.

In the last part of our HelloBeer goes Angular trilogy we’ll wrap it all up with some user-friendly error handling. We’ll also add i18n to our app to improve upon those ugly beer types. And then we’re really done!

HelloBeer goes Angular – Part I

You can never have enough clients for your beers, right? In our last post we served our Spring server-side clients mostly interested in Java flavored beers. Lets see how difficult it is to generate stub code for our Swagger API geared towards a more client-side oriented beer drinker. In this post we’ll generate some Typescript stubs on which we’ll try to build an Angular front-end application. Now, I’m not an expert in Angular so I obviously ran into a couple of rookie mistakes. In this blogpost I’m gonna show you the way I build the application and I’ll also point out some of the pitfalls I ran into.

Needless to say but the code will be available on GitHub. Since this blogpost is gonna be pretty big, I’ve decided to split it up into two parts. In this first part we’re gonna generate the stub and consume the GET part of the REST service. The link to the final Github code will be posted in part II.

New project

So let’s start brewing. First things first. For starters create our new project and call it hb-angular-client

ng new hb-angular-client

You can fire up your first incarnation by hitting “ng serve”, check http://localhost:4200 and at this time you should see a working application. Next, we’re gonna recreate the front-end we build with Spring MVC in our previous blogpost and make our Angular app look similar. The final version will look like this:

Screenshot-2018-3-3 HelloRoger

Generating the Typescript stub

This is probably the most important part. The rest is just building Angular. To generate the stub code for our Swagger API, I’m gonna use the angular4-swagger-client-generator. Since I’ve got a feeling I’m gonna use this generator more than just for this project, I’ll install it globally (hence the -g):

npm install -g angular4-swagger-client-generator

Now let’s generate our stub code. Make sure the output directory already exists. For our source we’re pointing at our Swagger api available on SwaggerHub. Note that opposed to the Maven generation in our previous blogpost where we took the yaml file as the source, we’re now pointing at the json file:

a4apigen -u https://app.swaggerhub.com/apiproxy/schema/file/rphgoossens/hello-beer/1.0/swagger.json -o ./src/app/services/beer

The generator will create a model file containing the Beer and Type interfaces and the index.ts file that will contain the methods with which we can communicate with our REST service:

  /**
  * Method addToBeerRepositoryUsingPOST
  * @param beer beer
  * @return Full HTTP response as Observable
  */
  public addToBeerRepositoryUsingPOST(beer: Beer): Observable {
    let uri = '/hello-beer/1.0/beer';
    let headers = new HttpHeaders();
    let params = new HttpParams();
    return this.sendRequest('post', uri, headers, params, JSON.stringify(beer));
  }

  /**
  * Method getAllBeersUsingGET
  * @param type type
  * @return Full HTTP response as Observable
  */
  public getAllBeersUsingGET(type: string): Observable {
    let uri = '/hello-beer/1.0/beers';
    let headers = new HttpHeaders();
    let params = new HttpParams();
    if (type !== undefined && type !== null) {
      params = params.set('type', type + '');
    }
    return this.sendRequest('get', uri, headers, params, null);
  }

Consuming the GET method

Let us first build the top part of the app, i.e. the table that will show us the beers currently served by the REST service. After putting the style sheets in place, we need to build the app.component.html and the app.component.ts code.
The typescript file will contain a call to the generated REST service stub. To inject the generated service in an Angular component, we first need to declare it as a Provider. Since we’ll be needing this service throughout the entire application, let’s declare it at the module level. Alter the app.module.ts like this:

import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {HttpClientModule} from '@angular/common/http';

import {AppComponent} from './app.component';

import {ApiClientService} from './services/beer/index';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule
  ],
  providers: [ApiClientService],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Note that the REST service is dependent on the HttpClientModule. I’ve added that one as an import as well.

Next, let’s build the component code. We need to import the model and service classes, inject the service and call it from the ngOnInit method to populate the beers array that will be exposed via our html page on startup.
This is the app.component.ts code so far. The important parts are highlighted.

import { Component, OnInit } from '@angular/core';

import {ApiClientService} from './services/beer/index';
import {Beer} from './services/beer/models';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public beers: Beer[];

  constructor(private apiClientService: ApiClientService) {
  }

  ngOnInit() {
    this.apiClientService.getAllBeersUsingGET(null)
      .subscribe(resp => {
        this.beers = resp.body;
      }, error => {
        console.log(error);
      });
  }
}

Last piece of the puzzle is the app.component.html page. It’s pretty straightforward. The most important part is the part for exposing the beers

<tr *ngFor="let beer of beers">
  <td><span>{{beer.name}}</span></td>
  <td><span>{{beer.type}}</span></td>
  <td><span>{{beer.brewery}}</span></td>
  <td>
    <a href="" class="btn btn-success custom-width">edit</a>
  </td>
  <td>
    <a href="" class="btn btn-danger custom-width">delete</a>
  </td>
</tr>

Taking a look at the app, we can see that our beers are being displayed quite nicely (of course after our hello-beer-server Spring Boot REST service has been spun up):

Screenshot-2018-3-3 HbAngularClient

CORS

One of the pitfalls – one that every REST developer will run into at least once in his lifetime – is the infamous Cross-Origin Request Block error. In my first attempt the GET request data wasn’t showing in my application.

Checking the Firefox Developer Tools (Network Tab) I could see that the REST service was being called, responding with a couple of Beers.

The console was showing me this error though:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at http://localhost:8080/hello-beer/1.0/beers. (Reason: CORS header ‘Access-Control-Allow-Origin’ missing).

Basically what this boils down to, is that you can’t make a service request from a localhost app when that service is also running on localhost albeit on a different port. The browser simply will not accept the response.

The easiest solution is to change the REST service to let it generate responses that the browser will accept. So that’s what I did. I added the following configuration to my Spring Boot Rest Service:

@Configuration
public class HelloBeerConfiguration {

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurerAdapter() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**");
            }
        };
    }
}

Summary

In this first part of a blog post series of 2 we’ve generated a Typescript client for our Swagger API and build a small Angular app that consumes the REST service implementing the Swagger API, on top of it. So far we’ve only consumed the GET method of the REST service.

In our 2nd part we’re gonna consume the POST part, add some error handling and as a bonus some i18n and finally we’re gonna wrap it all up. So stay tuned!!

References