Gizzy Berry

Gizzy Berry


Angular Deployment with a Side of Spring Boot

One of the more popular combinations of frontend and backend frameworks is Angular + Spring Boot. I’ve written several tutorials about how to combine the two—from keeping them as separate apps to combining them into a single artifact. But, what about deployment?

Developers ask me from time-to-time, “What’s the best way to do Angular deployment?” In this tutorial, I’ll show you several options. I’ll start by showing you how to deploy a Spring Boot app to Heroku. Then, I’ll show how to deploy a separate Angular app to Heroku.

There are lots of tutorials and information in the Java community on how to deploy Spring Boot apps, so I’ll leave the Spring Boot API on Heroku and show other Angular deployment options, including Firebase, Netlify, and AWS S3.

Create an Angular + Spring Boot App

Since this tutorial is more about deployment than app creation, you can start with an existing Angular + Spring Boot app that I created previously. It’s a note-taking app that uses Kotlin and Spring Boot 2.2 on the backend and Angular 9 on the frontend. It’s secured with OpenID Connect (OIDC). If you’d like to see how I built it, you can read the following tutorials:

One of the slick features of this app is its full-featured data table that allows sorting, searching, and pagination. This feature is powered by NG Bootstrap and Spring Data JPA. Below is a screenshot:

Notes list with sorting

Clone the application into an okta-angular-deployment-example directory.

git clone \


Secure Your Angular + Spring Boot App with OIDC

To begin, you’ll need to create a Heroku account. If you already have a Heroku account, log in to it. Once you’re logged in, create a new app. I named mine bootiful-angular.

Create Heroku app

After creating your app, click on the Resources tab and add the Okta add-on.

Okta Add-On

If you haven’t entered a credit card for your Heroku account, you will receive an error. This is because Heroku requires you to have a credit card on file to use any of their add-ons, even for free ones. This is part of Heroku’s assurance to guard against misuse (real person, real credit card, etc.). I think this is a good security practice. Simply add a credit card to continue.

Click Provision and wait 20-30 seconds while your Okta account is created and OIDC apps are registered. Now go to your app’s Settings tab and click the Reveal Config Vars button. The Config Vars displayed are the environment variables you can use to configure both Angular and Spring Boot for OIDC authentication.

Okta Add-On

Create an okta.env file in the okta-angular-deployment-example/notes-api directory and copy the config vars into it, where $OKTA_* is the value from Heroku.


If you’re on Windows without Windows Subsystem for Linux installed, create an okta.bat file and use SET instead of export.

Start your Spring Boot app by navigating to the notes-api directory, sourcing this file, and running ./gradlew bootRun.

source okta.env
./gradlew bootRun

Environment Variables in IntelliJ IDEA

If you’re using IntelliJ IDEA, you can copy the contents of okta.env and paste its values as environment variables. Edit the DemoApplication configuration and click on the Browse icon on the right-side of Environment variables.

Edit DemoApplication Configuration

Next, click the paste icon. You’ll need to delete export in the Name column. Now you can run your Spring Boot app with Okta from IDEA!

IntelliJ Environment Variables

Next, configure Angular for OIDC authentication by modifying its auth-routing.module.ts to use the generated issuer, client ID, and update the callback URL.


const oktaConfig = {
  issuer: '$OKTA_OAUTH2_ISSUER',
  redirectUri: window.location.origin + '/callback',
  pkce: true

const routes: Routes = [
    path: '/callback',
    component: OktaCallbackComponent

Install your Angular app’s dependencies and start it.

npm i
ng serve

Open http://localhost:4200 in your browser.

Angular Home

Click the Login button in the top right corner. You should be logged in straight-away, since you’re already logged in to Okta. If you want to see the full authentication flow, log out, or try it in a private window. You can use the $OKTA_ADMIN_EMAIL and $OKTA_ADMIN_PASSWORD from your Heroku config variables for credentials. Create a note to make sure everything works.

First note

Commit your progress to Git from the top-level okta-angular-deployment-example directory.

git commit -am "Add Okta OIDC Configuration"

Prepare Angular + Spring Boot for Production

There are a couple of things you should do to make your app ready for production.

  1. Make sure you’re using the latest releases
  2. Configure production URLs
  3. Use PostgreSQL for the production database

You’re going to want to continue to develop locally—so you’ll want a production mode as well as a development mode.

Update Spring Boot and Angular Dependencies

I’m the type of developer that likes to use the latest releases of open source libraries. I do this to take advantage of new features, performance optimizations, and security fixes.

There’s a Gradle Use Latest Versions Plugin that provides a task to update dependencies to the latest version. Configure it by adding the following to the plugins block at the top of notes-api/build.gradle.kts.

plugins {
    id("se.patrikerdes.use-latest-versions") version "0.2.13"
    id("com.github.ben-manes.versions") version "0.28.0"

For compatibility with Spring Boot 2.3, you’ll need to update the Gradle Wrapper to use Gradle 6.3+.

./gradlew wrapper --gradle-version=6.5 --distribution-type=bin

Then run the following command in the notes-api directory to update your dependencies to the latest released versions.

./gradlew useLatestVersions

You can verify everything still works by running ./gradlew bootRun and navigating to http://localhost:8080/api/notes. You should be redirected to Okta to log in, then back to your app.

If your app fails to start, you need to run source okta.env first.

For the Angular client, you can use npm-check-updates to upgrade npm dependencies.

npm i -g npm-check-updates
ncu -u

At the time of this writing, this will upgrade Angular to version 9.1.9 and TypeScript to version 3.9.3. Angular 9 supports TypeScript versions >=3.6.4 and <3.9.0, so you’ll need to change package.json to specify TypeScript 3.8.3.

"typescript": "~3.8.3"

Then run the following commands in the notes directory:

npm i
npm audit fix
ng serve

Confirm you can still log in at http://localhost:4200.

Commit all your changes to source control.

git commit -am "Update dependencies to latest versions"

Configure Production URLs

There are a few places where localhost is hard-coded:

  1. notes-api/src/main/kotlin/…​/DemoApplication.kt has http://localhost:4200
  2. notes/src/app/shared/okta/auth-interceptor.ts has http://localhost
  3. notes/src/app/note/note.service.ts has http://localhost:8080

You need to change Spring Boot’s code so other origins can make CORS requests too. Angular’s code needs updating so access tokens will be sent to production URLs while API requests are sent to the correct endpoint.

Open the root directory in your favorite IDE and configure it so it loads notes-api as a Gradle project. Open DemoApplication.kt and change the simpleCorsFilter bean so it configures the allowed origins from your Spring environment.


import org.springframework.beans.factory.annotation.Value

class DemoApplication {

    @Value("#{ @environment[''] ?: {} }")
    private lateinit var allowedOrigins: List<String>

    fun simpleCorsFilter(): FilterRegistrationBean<CorsFilter> {
        val source = UrlBasedCorsConfigurationSource()
        val config = CorsConfiguration()
        config.allowCredentials = true
        config.allowedOrigins = allowedOrigins
        config.allowedMethods = listOf("*");
        config.allowedHeaders = listOf("*")
        source.registerCorsConfiguration("/**", config)
        val bean = FilterRegistrationBean(CorsFilter(source))
        bean.order = Ordered.HIGHEST_PRECEDENCE
        return bean

Define the property in notes-api/src/main/resources/

Angular has an environment concept built-in. When you run ng build --prod to create a production build, it replaces environment.ts with

Open environment.ts and add an apiUrl variable for development.


export const environment = {
  production: false,
  apiUrl: 'http://localhost:8080'

Edit to point to your production Heroku URL. Be sure to replace bootiful-angular with your app’s name.


export const environment = {
  production: false,
  apiUrl: ''

Update auth-interceptor.ts to use environment.apiUrl.


import { environment } from '../../../environments/environment';

export class AuthInterceptor implements HttpInterceptor {


  private async handleAccess(request: HttpRequest<any>, next: HttpHandler): Promise<HttpEvent<any>> {
    const allowedOrigins = [environment.apiUrl];

Update notes.service.ts as well.


import { environment } from '../../environments/environment';

export class NoteService {
  api = `${environment.apiUrl}/api/notes`;

  find(filter: NoteFilter): Observable<Note[]> {

    const userNotes = `${environment.apiUrl}/user/notes`;

Use PostgreSQL for the Production Database

H2 is a SQL database that works nicely for development. In production, you’re going to want something a little more robust. Personally, I like PostgreSQL so I’ll use it in this example.

Similar to Angular’s environments, Spring and Maven have profiles that allow you to enable different behavior for different environments.

Open notes-api/build.gradle.kts and change the H2 dependency so PostgreSQL is used when -Pprod is passed in.

if (project.hasProperty("prod")) {
} else {

At the bottom of the file, add the following code to make the prod profile the default when -Pprod is included in Gradle commands.

val profile = if (project.hasProperty("prod")) "prod" else "dev"

tasks.bootRun {

tasks.processResources {
    rename("application-${profile}.properties", "")

Rename notes-api/src/main/resources/ to and add a URL for H2 so it will persist to disk, which retains data through restarts.

Create a notes-api/src/main/docker/postgresql.yml so you can test your prod profile settings.

version: '2'
    image: postgres:12.1
      - POSTGRES_USER=notes
      - 5432:5432

Create an file in the same directory as You’ll override these properties with environment variables when you deploy to Heroku.


The word user is a keyword in PostgreSQL, so you’ll need to change user to username in the Note entity.


data class Note(@Id @GeneratedValue var id: Long? = null,
                var title: String? = null,
                var text: String? = null,
                @JsonIgnore var username: String? = null)

This will cause compilation errors and you’ll need to rename method names and variables to fix them.

Click to see the diff

You won’t want to pre-populate your production database with a bunch of notes, so add a @Profile annotation to the top of DataInitializer so it only runs for the dev profile.

import org.springframework.context.annotation.Profile

class DataInitializer(val repository: NotesRepository) : ApplicationRunner {...}

To test your profiles, start PostgreSQL using Docker Compose.

docker-compose -f src/main/docker/postgresql.yml up

If you have PostreSQL installed and running locally, you’ll need to stop the process for Docker Compose to work.

In another terminal, run your Spring Boot app.

source okta.env
./gradlew bootRun -Pprod

If it starts OK, confirm your Angular app can talk to it and get ready to deploy to production!

git commit -am "Configure environments for production"

Deploy Spring Boot to Heroku

One of the easiest ways to interact with Heroku is with the Heroku CLI. Install it before proceeding with the instructions below.

brew tap heroku/brew && brew install heroku

Open a terminal and log in to your Heroku account.

heroku login

Heroku expects you to have one Git repo per application. However, in this particular example, there are multiple apps in the same repo. This is called a “monorepo”, where many projects are stored in the same repository.

Luckily, there’s a heroku-buildpack-monorepo that allows you to deploy multiple apps from the same repo.

You should already have a Heroku app that you added Okta to. Let’s use it for hosting Spring Boot. Run heroku apps and you’ll see the one you created.

$ heroku apps
=== Apps

You can run heroku config -a $APP_NAME to see your Okta variables. In my case, I’ll be using bootiful-angular for $APP_NAME.

Associate your existing Git repo with the app on Heroku.

heroku git:remote -a $APP_NAME

Set the APP_BASE config variable to point to the notes-api directory. While you’re there, add the monorepo and Gradle buildpacks.

heroku config:set APP_BASE=notes-api
heroku buildpacks:add
heroku buildpacks:add heroku/gradle

Attach a PostgreSQL database to your app.

heroku addons:create heroku-postgresql

As part of this process, Heroku will create a DATASOURCE_URL configuration variable. It will also automatically detect Spring Boot and set variables for SPRING_DATASOURCE_URL, SPRING_DATASOURCE_USERNAME, AND SPRING_DATASOURCE_PASSWORD. These values will override what you have in

By default, Heroku’s Gradle support runs ./gradlew build -x test. Since you want it to run ./gradlew bootJar -Pprod, you’ll need to override it by setting a GRADLE_TASK config var.

heroku config:set GRADLE_TASK="bootJar -Pprod"

The $OKTA_* environment variables don’t have the same names as the Okta Spring Boot starter expects. This is because the Okta Heroku Add-On creates two apps: SPA and web. The web app’s config variables end in _WEB. You’ll have to make some changes so those variables are used for the Okta Spring Boot starter. One way to do so is to create a Procfile in the notes-api directory.

web: java -Dserver.port=$PORT -Dokta.oauth2.client-id=${OKTA_OAUTH2_CLIENT_ID_WEB} -Dokta.oauth2.client-secret=${OKTA_OAUTH2_CLIENT_SECRET_WEB} -jar build/lib/*.jar

I think it’s easier to rename the variable, so that’s what I recommend. Run the following command and remove _WEB from the two variables that have it.

heroku config:edit

Now you’re ready to deploy! Take a deep breath and witness how Heroku can deploy your Spring Boot + Kotlin app with a simple git push.

git push heroku master

When I ran this command, I received this output:

remote: Compressing source files... done.
remote: Building source:
remote: -----> Monorepo app detected
remote:       Copied notes-api to root of app successfully
remote: -----> Gradle app detected
remote: -----> Spring Boot detected
remote: -----> Installing JDK 1.8... done
remote: -----> Building Gradle app...
remote: -----> executing ./gradlew bootJar -Pprod
remote:        Downloading
remote:        ..........................................................................................
remote:        > Task :compileKotlin
remote:        > Task :compileJava NO-SOURCE
remote:        > Task :processResources
remote:        > Task :classes
remote:        > Task :bootJar
remote:        BUILD SUCCESSFUL in 1m 28s
remote:        3 actionable tasks: 3 executed
remote: -----> Discovering process types
remote:        Procfile declares types     -> (none)
remote:        Default types for buildpack -> web
remote: -----> Compressing...
remote:        Done: 91.4M
remote: -----> Launching...
remote:        Released v1
remote: deployed to Heroku
remote: Verifying deploy... done.
   a1b10c4..6e298cf  master -> master
Execution time: 2 min. 7 s.

Run heroku open to open your app. You’ll be redirected to Okta to authenticate, then back to your app. It will display a 404 error message because you have nothing mapped to /. You can fix that by adding a HomeController with the following code.

package com.okta.developer.notes

import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RestController

class HomeController {

    fun hello(@AuthenticationPrincipal user: OidcUser): String {
        return "Hello, ${user.fullName}"

Commit this change and deploy it to Heroku.

git commit -am "Add HomeController"
git push heroku master

Now when you access the app, it should say hello.


Deploy Angular to Heroku

An Angular app is composed of JavaScript, CSS, and HTML when built for production. It’s extremely portable because it’s just a set of static files. If you run ng build --prod, the production-ready files will be created in dist/<app-name>. In this section, you’ll learn how you can use your package.json scripts to hook into Heroku’s lifecycle and how to deploy them with a simple git push.

You’ll need to create another app on Heroku for the Angular frontend.

heroku create

Set the APP_BASE config variable and add the necessary buildpacks to the app that was just created.

heroku config:set APP_BASE=notes -a $APP_NAME
heroku buildpacks:add -a $APP_NAME
heroku buildpacks:add heroku/nodejs -a $APP_NAME

Change notes/package.json to have a different start script.

"start": "http-server-spa dist/notes index.html $PORT",

Add a heroku-postbuild script to your package.json:

"heroku-postbuild": "ng build --prod && npm install -g http-server-spa"

Commit your changes, add a new Git remote for this app, and deploy!

git commit -am "Prepare for Heroku"
git remote add angular$APP_NAME.git
git push angular master

When it finishes deploying, you can open your Angular app with:

heroku open --remote angular

If you experience any issues, you can run heroku logs --remote angular to see your app’s log files.

You won’t be able to log in to your app until you modify its Login redirect URI on Okta. Log in to your Okta dashboard (tip: you can do this from the first Heroku app you created, under the Resources tab). Go to Applications > SPA > General > Edit. Add https://<angular-app-on-heroku> to the Login redirect URIs and https://<angular-app-on-heroku> to the Logout redirect URIs.

You should be able to log in now, but you won’t be able to add any notes. This is because you need to update the allowed origins in your Spring Boot app. Run the following command to add an ALLOWED_ORIGINS variable in your Spring Boot app.

heroku config:set ALLOWED_ORIGINS=https://$ --remote heroku

Now you should be able to add a note. Pat yourself on the back for a job well done!

One issue you’ll experience is that you’re going to lose your data between restarts. This is because Hibernate is configured to update your database schema each time. Change it to simply validate your schema by overriding the ddl-auto value in

heroku config:set SPRING_JPA_HIBERNATE_DDL_AUTO=validate --remote heroku

#angular #spring-boot #java #web-development

What is GEEK

Buddha Community

Angular Deployment with a Side of Spring Boot

Angular 12 + Spring Boot: JWT Authentication example | Spring Security

In this tutorial, I will show you how to build a full stack Angular 12 + Spring Boot JWT Authentication example. The back-end server uses Spring Boot with Spring Security for JWT Authentication & Role based Authorization, Spring Data JPA for interacting with database. The front-end will be built using Angular 12 with HttpInterceptor & Form validation.

Related Posts:

– Angular 12 + Spring Boot: CRUD example

– Angular 12 + Spring Boot: File upload example

– Spring Boot, MongoDB: JWT Authentication with Spring Security

Contents [hide]

#angular #full stack #spring #angular #angular 12 #authentication #authorization #jwt #login #registration #security #spring boot #spring security #token based authentication

Spring: A Static Web Site Generator Written By GitHub Issues


Spring is a blog engine written by GitHub Issues, or is a simple, static web site generator. No more server and database, you can setup it in free hosting with GitHub Pages as a repository, then post the blogs in the repository Issues.

You can add some labels in your repository Issues as the blog category, and create Issues for writing blog content through Markdown.

Spring has responsive templates, looking good on mobile, tablet, and desktop.Gracefully degrading in older browsers. Compatible with Internet Explorer 10+ and all modern browsers.

Get up and running in seconds.


Quick start guide

For the impatient, here's how to get a Spring blog site up and running.

First of all

  • Fork the Spring repository as yours.
  • Goto your repository settings page to rename Repository Name.
  • Hosted directly on GitHub Pages from your project repository, you can take it as User or organization site or Project site(create a gh-pages branch).
  • Also, you can set up a custom domain with Pages.


  • Open the index.html file to edit the config variables with yours below.
$.extend(spring.config, {
  // my blog title
  title: 'Spring',
  // my blog description
  desc: "A blog engine written by github issues [Fork me on GitHub](",
  // my github username
  owner: 'zhaoda',
  // creator's username
  creator: 'zhaoda',
  // the repository name on github for writting issues
  repo: 'spring',
  // custom page
  pages: [
  • Put your domain into the CNAME file if you have.
  • Commit your change and push it.

And then

  • Goto your repository settings page to turn on the Issues feature.
  • Browser this repository's issues page, like this
  • Click the New Issue button to just write some content as a new one blog.


  • Browser this repository's GitHub Pages url, like this, you will see your Spring blog, have a test.
  • And you're done!

Custom development


  • You will need a web server installed on your system, for example, Nginx, Apache etc.
  • Configure your spring project to your local web server directory.
  • Run and browser it, like http://localhost/spring/dev.html .
  • dev.html is used to develop, index.html is used to runtime.

Folder Structure

├── css/
|    ├── boot.less  #import other less files
|    ├── github.less  #github highlight style
|    ├── home.less  #home page style
|    ├── issuelist.less #issue list widget style
|    ├── issues.less #issues page style
|    ├── labels.less #labels page style
|    ├── main.less #commo style
|    ├── markdown.less #markdown format style
|    ├── menu.less #menu panel style
|    ├── normalize.less #normalize style
|    ├── pull2refresh.less #pull2refresh widget style
|    └── side.html  #side panel style
├── dist/
|    ├── main.min.css  #css for runtime
|    └── main.min.js  #js for runtime
├── img/  #some icon, startup images
├── js/
|    ├── lib/  #some js librarys need to use
|    ├── boot.js  #boot
|    ├── home.js  #home page
|    ├── issuelist.js #issue list widget
|    ├── issues.js #issues page
|    ├── labels.js #labels page
|    ├── menu.js #menu panel
|    ├── pull2refresh.less #pull2refresh widget
|    └── side.html  #side panel
├── css/
|    ├── boot.less  #import other less files
|    ├── github.less  #github highlight style
|    ├── home.less  #home page style
|    ├── issuelist.less #issue list widget style
|    ├── issues.less #issues page style
|    ├── labels.less #labels page style
|    ├── main.less #commo style
|    ├── markdown.less #markdown format style
|    ├── menu.less #menu panel style
|    ├── normalize.less #normalize style
|    ├── pull2refresh.less #pull2refresh widget style
|    └── side.html  #side panel style
├── dev.html #used to develop
├── favicon.ico #website icon
├── Gruntfile.js #Grunt task config
├── index.html #used to runtime
└── package.json  #nodejs install config


  • Browser http://localhost/spring/dev.html, enter the development mode.
  • Changes you want to modify the source code, like css, js etc.
  • Refresh dev.html view change.


  • You will need Node.js installed on your system.
  • Installation package.

$ npm install

*   Run grunt task.

$ grunt
  • Browser http://localhost/spring/index.html, enter the runtime mode.
  • If there is no problem, commit and push the code.
  • Don't forget to merge master branch into gh-pages branch if you have.
  • And you're done! Good luck!

Report a bug

Who used

If you are using, please tell me.

Download Details:
Author: zhaoda
Source Code:
License: MIT License

#spring #spring-framework #spring-boot #java 

Sigrid  Farrell

Sigrid Farrell


Angular 12 + Spring Boot: CRUD example

In this tutorial, we will learn how to build a full stack Spring Boot + Angular 12 example with a CRUD App. The back-end server uses Spring Boot with Spring Web MVC for REST Controller and Spring Data JPA for interacting with embedded database (H2 database). Front-end side is made with Angular 12, HttpClient, Router and Bootstrap 4.

Run both Project on same server/port:

How to Integrate Angular with Spring Boot Rest API

Contents [hide]

#angular #full stack #spring #angular #angular 12 #crud #h2 database #mysql #postgresql #rest api #spring boot #spring data jpa

Sigrid  Farrell

Sigrid Farrell


Angular 12 + Spring Boot + PostgreSQL example: Build CRUD App

In this tutorial, we will learn how to build a full stack Angular 12 + Spring Boot + PostgreSQL example with a CRUD App. The back-end server uses Spring Boot with Spring Web MVC for REST Controller and Spring Data JPA for interacting with PostgreSQL database. Front-end side is made with Angular 12, HTTPClient, Router and Bootstrap 4.

Older versions:

– Angular 10 + Spring Boot + PostgreSQL example: CRUD App

– Angular 11 + Spring Boot + PostgreSQL example: CRUD App

Contents [hide]

#angular #full stack #spring #angular #angular 12 #crud #postgresql #rest api #spring boot #spring data jpa

I Dev


Spring Boot + Angular 11: Pagination example (Server side)

In this tutorial, I will show you how to build a full-stack Pagination (Angular 11 + Spring Boot) example on Server side. The back-end server uses Spring Data and Spring Web for REST APIs, front-end side is an Angular 11 App with HTTPClient.

Full Article:

Pagination with Angular 11 & Spring Boot example

Assume that we have tutorials table in database like this: spring-boot-angular-11-pagination-example-database

We need to export APIs for pagination (with/without filter) as following samples:

  • /api/tutorials?page=1&size=3
  • /api/tutorials?size=5: using default value for page
  • /api/tutorials?title=data&page=1&size=5: pagination & filter by title containing 'data'
  • /api/tutorials/published?page=2: pagination & filter by 'published' status

This is structure of the result that we want to get from the APIs:

    "totalItems": 12,
    "tutorials": [...],
    "totalPages": 3,
    "currentPage": 1

Our Angular app will display the result with pagination:


You can change to a page with larger index:


Or change page size (quantity of items per page):


Or paging with filter:


Full-stack Architecture

We're gonna build the application with following architecture: spring-boot-angular-11-pagination-example-architecture
  • Spring Boot exports REST Apis using Spring Web MVC & interacts with Database using Spring Data.
  • Angular 11 Client sends HTTP Requests and retrieve HTTP Responses using axios, shows data on the components. We also use Angular Router for navigating to pages.

For more details, please visit:

Further Reading

Fullstack CRUD App:

Or Security: Angular 11 + Spring Boot: JWT Authentication example

Happy learning, see you again!

#spring #angular #pagination #web-development #spring-boot #spring-framework