A logo showing the text blog.marcnuri.com
Español
Home»Java»Angular + Spring Boot integration using Gradle

Recent Posts

  • Fabric8 Kubernetes Client 7.2 is now available!
  • Connecting to an MCP Server from JavaScript using AI SDK
  • Connecting to an MCP Server from JavaScript using LangChain.js
  • The Future of Developer Tools: Adapting to Machine-Based Developers
  • Connecting to a Model Context Protocol (MCP) Server from Java using LangChain4j

Categories

  • Artificial Intelligence
  • Front-end
  • Go
  • Industry and business
  • Java
  • JavaScript
  • Legacy
  • Operations
  • Personal
  • Pet projects
  • Tools

Archives

  • May 2025
  • April 2025
  • March 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • August 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023
  • March 2023
  • February 2023
  • January 2023
  • December 2022
  • November 2022
  • October 2022
  • September 2022
  • August 2022
  • July 2022
  • June 2022
  • May 2022
  • March 2022
  • February 2022
  • January 2022
  • December 2021
  • November 2021
  • October 2021
  • September 2021
  • August 2021
  • July 2021
  • January 2021
  • December 2020
  • November 2020
  • October 2020
  • September 2020
  • August 2020
  • July 2020
  • June 2020
  • May 2020
  • February 2020
  • January 2020
  • December 2019
  • October 2019
  • September 2019
  • July 2019
  • March 2019
  • November 2018
  • July 2018
  • June 2018
  • May 2018
  • April 2018
  • March 2018
  • February 2018
  • December 2017
  • July 2017
  • January 2017
  • December 2015
  • November 2015
  • December 2014
  • March 2014
  • February 2011
  • November 2008
  • June 2008
  • May 2008
  • April 2008
  • January 2008
  • November 2007
  • September 2007
  • August 2007
  • July 2007
  • June 2007
  • May 2007
  • April 2007
  • March 2007

Angular + Spring Boot integration using Gradle

2017-07-24 in Java / Front-end tagged Angular / Backend / Build / CI / Frontend / Gradle / Initializr / Java / JavaScript / Spring Framework / Spring Boot by Marc Nuri | Last updated: 2021-03-17
Versión en Español

Introduction

In this post, I’ll show you how to serve an Angular (>2) frontend application using a Java Spring Boot application as the backend and static page web server, and a Gradle script to perform automated build and deploy tasks both for Spring and Angular.

Requirements

The technology stack required for this tutorial is:

  • Node.js
  • Angular CLI
  • Gradle

The main goal is to achieve a npm install + build that integrates with Java’s Gradle build and deploys the distribution files into Spring's static resources directory. You could replace Angular CLI for any other Frontend build tool/framework such as React.

Backend

The backend of the stack will be a Spring Boot application.

We can generate a bootstrapped application using Spring's Initializr utility as follows:

Spring Initializr
Spring Initializr

Select the basic options for a Gradle Java Project with support for Web and click “Generate Project” to download an initial application.

Next extract the project to a location of your choice.

In order to test frontend and backend integration, we are going to build a simple REST endpoint that generates a “Hello world!” String.

Create a new class (e.g. TestController) and modify it as follows:

1@RestController
2@RequestMapping(path = "/api")
3public class TestController {
4  @GetMapping(path = "/hello-world")
5  public String helloWorld(){
6    return "Hello world!";
7  }
8}

Frontend

Once the Spring bootstrapped application has been extracted and modified, we must initialize the Frontend application.

In this case, we are going to use angular-cli to prepare a bootstrapped empty Angular application.

The Angular application should be placed in the project’s directory ./src/main/webapp. The easiest way to achieve this is to open a terminal, navigate to ./src/main in the project’s root and execute the following Angular CLI command:

1ng new webapp
Angular CLI Bootsrap application
Angular CLI Bootsrap application

Angular build configuration

Some additional settings must be made to the default angular-cli.json configuration in order to ease the deployment of the application with Spring Boot.

1{
2  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3  "project": {
4    "name": "Demo Application"
5  },
6  "apps": [
7    {
8      "root": "src",
9      "outDir": "dist/static",
10      "assets": [
11        "assets",
12        "favicon.ico"
13      ],
14      "index": "index.html",
15      "main": "main.ts",
16      "polyfills": "polyfills.ts",
17      "test": "test.ts",
18      "tsconfig": "tsconfig.app.json",
19      "testTsconfig": "tsconfig.spec.json",
20      "prefix": "app",
21      "styles": [
22        "styles.css"
23      ],
24      "scripts": [],
25      "environmentSource": "environments/environment.ts",
26      "environments": {
27        "dev": "environments/environment.ts",
28        "prod": "environments/environment.prod.ts"
29      }
30    }
31  ],
32  "e2e": {
33    "protractor": {
34      "config": "./protractor.conf.js"
35    }
36  },
37  "lint": [
38    {
39      "project": "src/tsconfig.app.json"
40    },
41    {
42      "project": "src/tsconfig.spec.json"
43    },
44    {
45      "project": "e2e/tsconfig.e2e.json"
46    }
47  ],
48  "test": {
49    "karma": {
50      "config": "./karma.conf.js"
51    }
52  },
53  "defaults": {
54    "styleExt": "css",
55    "component": {}
56  }
57}

apps.outDir property should be changed from “dist” to “dist/static”. Also the project.name property should be changed from “webapp” to the real name of the application.

Backend integration

In order to test integration with the Backend, we are going to make some simple modifications to the newly created application to connect to the REST endpoint we just created:

1<h1>
2  {{title}}
3</h1>
4<button (click)="sayHello()">Say Hello</button>
5<span>{{result}}</span>

We’ve added to the component’s HTML a button to trigger the REST request, and a placeholder to show the result.

1import { Component } from '@angular/core';
2import { Http } from '@angular/http';
3import { Observable } from 'rxjs';
4
5@Component({
6  selector: 'app-root',
7  templateUrl: './app.component.html',
8  styleUrls: ['./app.component.css']
9})
10export class AppComponent {
11  title = 'app works!';
12  result = '';
13
14  constructor(private http: Http){
15  }
16
17  private sayHello(): void {
18    this.result = 'loading...';
19    this.http.get(`/api/hello-world`).subscribe(response => this.result = response.text());
20  }
21
22}

We’ve added a function that will be triggered by the button to call the REST endpoint and show the result in the placeholder.

Gradle Build Script

Finally, we are going to modify the build.gradle script to create frontend integration tasks.

The resulting script looks as follows:

1buildscript {
2  ext {
3    springBootVersion = '1.5.4.RELEASE'
4  }
5  repositories {
6    mavenCentral()
7  }
8  dependencies {
9    classpath("org.springframework.boot:spring-boot-gradle-plugin:${springBootVersion}")
10  }
11}
12
13apply plugin: 'java'
14apply plugin: 'eclipse'
15apply plugin: 'org.springframework.boot'
16
17version = '0.0.1-SNAPSHOT'
18sourceCompatibility = 1.8
19
20repositories {
21  mavenCentral()
22}
23
24
25dependencies {
26  compile('org.springframework.boot:spring-boot-starter-web')
27  testCompile('org.springframework.boot:spring-boot-starter-test')
28}
29
30def webappDir = "$projectDir/src/main/webapp"
31sourceSets {
32  main {
33    resources {
34      srcDirs = ["$webappDir/dist", "$projectDir/src/main/resources"]
35    }
36  }
37}
38
39processResources {
40  dependsOn "buildAngular"
41}
42
43task buildAngular(type:Exec) {
44  // installAngular should be run prior to this task
45  dependsOn "installAngular"
46  workingDir "$webappDir"
47  inputs.dir "$webappDir"
48  // Add task to the standard build group
49  group = BasePlugin.BUILD_GROUP
50  // ng doesn't exist as a file in windows -> ng.cmd
51  if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
52    commandLine "ng.cmd", "build"
53  } else {
54    commandLine "ng", "build"
55  }
56}
57
58task installAngular(type:Exec) {
59  workingDir "$webappDir"
60  inputs.dir "$webappDir"
61  group = BasePlugin.BUILD_GROUP
62  if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
63    commandLine "npm.cmd", "install"
64  } else {
65    commandLine "npm", "install"
66  }
67}

We’ve included a new variable webappDir that points to the Frontend’s application directory.

sourceSets have been modified to include Angular’s dist directory where the application is packaged and deployed by Angular CLI.

We’ve added a dependency to the standard processResources task to one of our newly generated tasks: buildAngular.

Two new tasks have been created. buildAngular will run ng build command. This task will be added to the standard build tasks and be called after installAngular task,

It’s important to notice that both these tasks should execute slightly different commands when run on Windows. Neither npm nor ng exist as executables in windows, they are both cmd scripts that can be run in the console just passing their name (without extensions) but are really .cmd scripts. In order for them to be run as an Exec task, full name of the executable must be provided.

Finally, installAngular task will run npm install before any other task related to processing resources is executed.

build.gradle script
build.gradle script

Download sources

You can find a full working project with the sources for this tutorial here: https://github.com/marcnuri-demo/angularboot

To get up and running (it takes a while, npm must download Angular dependencies [not verbose]):

1git clone https://github.com/marcnuri-demo/angularboot.git
2gradle bootRun

Open http://localhost:8080 in your browser

Twitter iconFacebook iconLinkedIn iconPinterest iconEmail icon

Comments in "Angular + Spring Boot integration using Gradle"

  • Avatar for Amruta
    Amruta
    2017-11-28 21:44
    Very nice blog, exactly what I was looking for, thanks for such a simplified and understanding blog.
  • Avatar for ttzn
    ttzn
    2017-12-29 09:31
    It's impressive how fast and simple it is to get Gradle to manage a diverse set of tools. Thank you for this useful post.
  • Avatar for Patrick
    Patrick
    2018-02-12 10:04
    Thank you for the blog and useful information. Can some guidance be provided how this code is built and deployed for use? Thank you
    • Avatar for Patrick
      Patrick
      2018-02-12 10:59
      all sorted...was having a small problem with angular. Thank you!!
  • Avatar for trung
    trung
    2018-04-18 06:35
    Thanks
  • Avatar for Omar
    Omar
    2018-08-20 21:04
    Nice. Inspired me. Thx
  • Avatar for Al
    Al
    2018-11-01 15:58
    This is an excellent tutorial! Is there any chance you could update to use Angular6? I'm having difficulty transitioning form the angular-cli.json contained here to the new angular.json format of Angular6.
  • Avatar for Kevin Gregory
    Kevin Gregory
    2020-03-12 19:24
    Marc,
    Thanks so much for the great post. I've included a portion of a kotlin-version of the gradle build file for other readers.This is to allow your approach but using kotlin dsl. It should be self-explanatory when compared to your original file. Thanks again!
    Best,
    Kevin

    partial of build.gradle.kts:
    val processResources by tasks.getting(ProcessResources::class) {
      dependsOn(":buildAngular")
    }
    
    val webappDir = "$projectDir/src/main/webapp"
    
    tasks {
      register("installAngular") {
        workingDir = File(webappDir)
        inputs.dir(webappDir)
        group = BasePlugin.BUILD_GROUP
        if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")){
          commandLine = listOf("npm.cmd", "install")
        } else {
          commandLine = listOf("npm", "install")
        }
      }
      val register = register("buildAngular") {
        dependsOn(":installAngular")
        workingDir = File(webappDir)
        inputs.dir(webappDir)
        // Add task to the standard build group
        group = BasePlugin.BUILD_GROUP
        // ng doesn't exist as a file in windows -> ng.cmd
        commandLine = if (System.getProperty("os.name").toUpperCase().contains("WINDOWS")) {
          listOf("ng.cmd", "build")
        } else {
          listOf("ng", "build")
        }
      }
    }
    • Avatar for Marc Nuri
      Marc Nuri
      2020-03-14 06:44
      Nice! thank you very much.

Post navigation
Docker container as a Linux system serviceWindows: How to run PostgreSQL without installation (portable)
© 2007 - 2025 Marc Nuri