Integrate Angular with a Spring Boot project

featured_image

Developing a multi-module application where the backend runs on Spring Boot and the frontend is powered by Angular is far less complicated than one might expect. Check out how you can build such a project and manage it as a single jar file.

What we are going to build

The goal is to design and create a multi-module application, established with frameworks: Spring Boot for the backend and Angular for the frontend. After that we will build the project into a single jar file using Maven.

The finished project is available in the following GitHub repository: little-pinecone/spring-boot-angular-scaffolding.

Requirements

I try to keep the project up to date. Visit the releases list to keep track of the current versions of frameworks and libraries used.
  • We are working on a fresh Spring Boot project with the Web package dependency. You  can read about setting up this project with Spring Initializr in How to create a new Spring Boot Project. In this tutorial I named the Spring Boot project spring-boot-angular-scaffolding.
  • Angular CLI – a command line interface tool that generates a project as well as performs many development tasks.
    I’m working on:
  • This project was created on Kubuntu (Ubuntu 18.04 LTS) – remember to adjust commands if you don’t work on Linux OS.
  • For the IDE I recommend IntelliJ IDEA Community Edition.

Architecture overview

In our multi-module maven project we want all components to be built together and share some metadata, but to differ in configuration. Fortunately, we can specify a parent project in both modules and define submodules in the parent – we will utilize both Project Inheritance and Aggregation.

The final project directory tree:

The final project structure screenshot

Manage the Spring Boot module structure

We will start with preparing the backend module. Go to the main folder of the Spring Boot app:

Create the directory where the backend part of our app will be stored:

Now, move the src directory to the freshly created backend folder:

We also need a child pom.xml file to specify Spring Boot dependencies, so copy the already existing file from the parent project to our backend directory:

In pom.xml reserved for the Spring Boot module we will leave all required maven dependencies unchanged – the application will look for them here.

However, we will completely alter the content of the <parent> element:

  • to specify which artifact is the parent for this pom we will use the fully qualified artifact name of the parent pom – spring-boot-angular-scaffolding;
  • to keep the groupId and the version of the module the same as its parent, we will enclose those fields here.

Furthermore, there are some metadata that require to be updated, namely:

  • <artifactId> – we will put backend here,
  • <name> – we will put backend here,
  • <description> – we will put The backend module built with Spring Boot here,
  • <properties> – remove it,
  • <packaging> – remove it.

Thanks to those changes the backend can be later recognised by the parent application as its module.

Please, double check which pom.xml you are editing – now we are working on spring-boot-angular-scaffolding/backend/pom.xml.

Leave the rest of the properties unaltered and check out the updated values:

Initialize a git repository in the main project:

We will use the .gitignore file from the parent project, copy the file to the backend folder:

We’ve just prepared the backend module within our project – it won’t work as intended yet, we need to create the frontend module, and, later, bring all components together.

The work done in this section is contained in the commit ed4c7fe5127deaeffc81fe1012d9bca7a7038cee.

Manage the Angular module structure

In the parent project create the frontend/src/main/ folder for the web application sources – the src and main directories are here to follow the Maven standard directory layout. Use -p (–parents) option to create all non-existing parent directories:

Similar to the backend, this module also needs its own pom.xml so copy the one prepared in the backend:

Update the following elements:

  • <artifactId> – we will put frontend here,
  • <name> – we will putfrontend here,
  • <description> – we will put The frontend module built with Angular here,
  • <dependencies> – remove it,
  • <plugins> – remove the following plugin:
Please, double check which pom.xml you are editing – now we are working on spring-boot-angular-scaffolding/frontend/pom.xml.

Check out the updated file:

We will use the .gitignore file from the parent project, copy the file to the frontend folder:

You can adjust the .gitignore to your needs or use the standard one created automatically by Angular CLI – in both cases remember to include the /target/ folder.

The frontend module is prepared but still empty, we will come back to it after creating the Angular project. For now, let’s move to aggregating the created modules with the parent application.

The work done in this section is contained in the commit cfcf3aad897d9adca9aa81c50e77e8bf25073074.

Tie the modules together

The backend and frontend pom.xml files contains the <parent> field so the modules know from which project they inherit. Now the main application requires data to identify which submodules should be aggregated during the build. We will provide them by updating the main pom.xml file by adding a new field – <modules> – with directories of its modules specified: backend and fronted.

Update the following properties:

  • <packaging> – we will put pom here,
  • <dependencies> – remove it,
  • <build> – remove it.
Please, double check which pom.xml you are editing – now we are working on spring-boot-angular-scaffolding/pom.xml.

Check out the updated file:

If you are working in InteliJ IDE choose Enable Autoimport option when prompted or confirm this option in settings.

Finally, we have a multi-module application. The backend module is the Spring Boot project created with Spring Initializr, what we need now is to set up an Angular project in the frontend module.

The work done in this section is contained in the commit 6963bee6b2aeb0dfa83b4fde28664cfdcd0ab3b0.

Generate an Angular project

Create an Angular project in the frontend/main/src/ folder. We will use the --skip-git option cause we are already tracking the whole project from the main directory, so we don’t need another repository within the project. I will simply name the project angular:

The angular directory contains the new project:

Angular project structure screenshot
Angular project structure

The work done in this section is contained in the commit ccc98ee03ef361bce2ccd29501d67cb58c2f4a3b.

Build project with Maven

Configure the frontend-maven-plugin

To build the frontend module with Maven we will use frontend-maven-plugin. It installs node and npm as well as builds our angular project. Be sure that you include the latest tagged version of the plugin (I used 1.6) and add the following code from the <plugins> field to the frontend/pom.xml:

Take a closer look to the following part of the plugin configuration:

npm run build calls the npm run command (don’t confuse it with npm build), which will run the angular ng build command to compile an application into an output directory. You can configure the build command in the frontend’s package.json file, so we will add the –prod option to uglify the javascript code:

Alter the angular output path

To keep up with the Maven standards we need to alternate the outputPath option for our Angular project, instead of "dist/angular" use "../../../target/frontend":

We have just changed the path for the built project, so we need to add the information about the new path to the frontend/pom.xml:

Add the frontend module dependency

Add the frontend dependency to the Spring Boot backend:

We used ${project.version} to access the project.version variable and avoid repetition. It’s possible thanks to the fact that “any field of the model that is a single value element can be referenced as a variable”see maven documentation.

Build the project

You can build your project with the Maven plugin directly from the InteliJ IDE – double click clean and then install:

Building Maven project form InteliJ screenshot
Building Maven project form InteliJ

The successful outcome:

Build output screenshot
Build output

Alternatively install maven on your machine and execute the build command:

Clean the git repository

The frontend-maven-plugin downloads Node and npm from https://nodejs.org/ dist and extracts them into a node folder created in frontend/src/main/angular/ directory. To avoid commiting this folder, add it alongside node_modules to the .gitignore created during generating the Angular project:

The work done in this section is contained in the commit f3f29ede3c5271e455ee3ccfa222563a7e28fc9f.

Prepare the app for development

Fix CORS issues on localhost

To speed up the development process you may want to run the frontend module separately. In that case, the host that serves the frontend (http://localhost:4200/) is different from the host that serves the data (http://localhost:8080/). You are going to encounter the following error:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:4200' is therefore not allowed access.

Read the Fix CORS issues between Spring Boot and Angular on localhost post to learn how to enable the cross-domain communication on a development environment.

Allow Angular to handle the routing

All paths implemented in Angular are accessible when the server is started with $ ng serve . However, when you run the whole project built with Maven, the app will give you a Whitelabel Error Page:

There was an unexpected error (type=Not Found, status=404)

The reason is that Spring Boot tries to handle all routes by itself. Check out the Make Spring Boot surrender routing control to Angular post to solve this issue.

Troubleshooting

Check the global settings of maven:

On Ubuntu with JDK older than 8 installed mvn commands will use that version despite the one that is specified in the project properties. You can:

force the usage of JDK 8:

and check the version now:

or you can fix dependencies issues. e.g. data-jpa requires jaxb-api in JDK9, so add it to the backend pom file:

The problem doesn’t occur when you build the project directly from InteliJ.

Photo by Vero Photoart on StockSnap

2 thoughts on “Integrate Angular with a Spring Boot project

  1. Hello. Nice tutorial. One question: If i run my fat jar on a pc in a local area network, if i access on another pc the ip of the first pc using port 8080 my app renders. But, if i add controllers to my backend, a simple get requests gets “connection refused” on the second pc(the pc that doesn’t run the fatjar).

    Do you have a solution to this?

    Kind regards,

    1. Hi,

      I haven’t run this project in a local network, but maybe I can still be of some use 🙂

      Maybe you can’t get a response from a different machine in the network because of the Cross Origin Resource Sharing issue?

      When I run the frontend separately with $ ng serve (so it was running on http://localhost:4200), the API (http://localhost:8080/api) refused to allow requests from the other host.

      I allowed other origins to access the API (Fix CORS issues between Spring Boot and Angular on localhost) on the development profile.

      Btw, I also had to make Spring Boot to surrender control over routing to Angular (Make Spring Boot surrender routing control to Angular).

      I’ll try to run my project in a local network to investigate the issue if I have the time.

      I hope you will fix your problem in no time 🙂

Leave a Reply

Your email address will not be published. Required fields are marked *