DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

Related

  • Spring Cloud Stream: A Brief Guide
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Component Tests for Spring Cloud Microservices
  • How Kafka Can Make Microservice Planet a Better Place

Trending

  • GitHub Copilot's New AI Coding Agent Saves Developers Time – And Requires Their Oversight
  • Start Coding With Google Cloud Workstations
  • Why Database Migrations Take Months and How to Speed Them Up
  • Beyond Code Coverage: A Risk-Driven Revolution in Software Testing With Machine Learning
  1. DZone
  2. Software Design and Architecture
  3. Microservices
  4. How to Use Spring Boot and JHipster With Reactive Java Microservices

How to Use Spring Boot and JHipster With Reactive Java Microservices

Learn how to create a reactive microservices architecture with Spring Boot, Spring Cloud Gateway, Spring Cloud Config, Spring WebFlux, Java, and JHipster.

By 
Matt Raible user avatar
Matt Raible
·
Feb. 26, 21 · Tutorial
Likes (6)
Comment
Save
Tweet
Share
4.9K Views

Join the DZone community and get the full member experience.

Join For Free

Even though it only came to prominence a few years ago, Java has been at the forefront of microservice architecture. Spring Cloud, Spring Data, and Spring Security, Java are well-known high-quality frameworks.

Spring WebFlux is a new web framework introduced by Spring Boot 2.0. While previous versions of Spring Boot only shipped with Spring MVC as an option, WebFlux gives the developers the chance to do reactive programming, meaning you can write your code with familiar syntax. As a result, your app will scale better and use up fewer resources.


Why Reactive Java?

Reactive programming isn’t for every app. The general rule of thumb is it won’t help you if you have < 500 requests/second. Chances are Spring MVC will perform as well as Spring WebFlux up to that point. When your traffic takes off, or if you need to process things faster than 500 requests/second, you should take a look at Spring WebFlux.

Spring WebFlux’s API has a similar syntax to Spring MVC. For example, here’s the Spring MVC code for creating a new Points entity.

Java
 




x
20


 
1
/**
2
 * {@code POST  /points} : Create a new points.
3
 *
4
 * @param points the points to create.
5
 * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new points, or with status {@code 400 (Bad Request)} if the points has already an ID.
6
 * @throws URISyntaxException if the Location URI syntax is incorrect.
7
 */
8
@PostMapping("/points")
9
public ResponseEntity<Points> createPoints(@Valid @RequestBody Points points) throws URISyntaxException {
10
    log.debug("REST request to save Points : {}", points);
11
    if (points.getId() != null) {
12
        throw new BadRequestAlertException("A new points cannot already have an ID", ENTITY_NAME, "idexists");
13
    }
14
    Points result = pointsRepository.save(points);
15
    pointsSearchRepository.save(result);
16
    return ResponseEntity
17
        .created(new URI("/api/points/" + result.getId()))
18
        .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
19
        .body(result);
20
}



The same functionality when implemented with Spring WebFlux returns a Mono and uses a more functional, streaming style to avoid blocking.

Java
 




xxxxxxxxxx
1
29


 
1
/**
2
 * {@code POST  /points} : Create a new points.
3
 *
4
 * @param points the points to create.
5
 * @return the {@link ResponseEntity} with status {@code 201 (Created)} and with body the new points, or with status {@code 400 (Bad Request)} if the points has already an ID.
6
 * @throws URISyntaxException if the Location URI syntax is incorrect.
7
 */
8
@PostMapping("/points")
9
public Mono<ResponseEntity<Points>> createPoints(@Valid @RequestBody Points points) throws URISyntaxException {
10
    log.debug("REST request to save Points : {}", points);
11
    if (points.getId() != null) {
12
        throw new BadRequestAlertException("A new points cannot already have an ID", ENTITY_NAME, "idexists");
13
    }
14
    return pointsRepository
15
        .save(points)
16
        .flatMap(pointsSearchRepository::save)
17
        .map(
18
            result -> {
19
                try {
20
                    return ResponseEntity
21
                        .created(new URI("/api/points/" + result.getId()))
22
                        .headers(HeaderUtil.createEntityCreationAlert(applicationName, true, ENTITY_NAME, result.getId().toString()))
23
                        .body(result);
24
                } catch (URISyntaxException e) {
25
                    throw new RuntimeException(e);
26
                }
27
            }
28
        );
29
}



In this guide, I’ll show you how to create a reactive microservices architecture with Spring Boot, Spring Cloud Gateway, Spring Cloud Config, Spring WebFlux, Java, and JHipster.


Prerequisites

  • Java 11+
  • Docker

You can find the completed source code for this example on GitHub, in the oktadeveloper/java-microservices-examples repository.

Shell
 




xxxxxxxxxx
1


 
1
git clone https://github.com/oktadeveloper/java-microservices-examples.git
2
cd java-microservices-examples/reactive-jhipster



Build a Reactive Java Microservices Architecture

JHipster is an open-source project that started as an application generator, based on Yeoman. It’s also the most popular Yeoman generator. JHipster initially allowed you to generate AngularJS and Spring apps. In the last five years, it’s become a platform with extensibility, grown a thriving community, and has saved developers many hours of pain and frustration.

You see, JHipster integrates everything for you. Do you want to use Angular with Spring Boot? It’s got that. React? Yep. Microservices with Spring Cloud? Check!

JHipster 7 beta 1 was recently released, and it packs a punch! A couple of slick features that I like are Vue support and reactive microservices with Spring WebFlux. To be fair, WebFlux and Spring Cloud Gateway have been an option since JHipster 6.8.0 in March 2020, but now we have R2DBC support too!

In this tutorial, I’ll show you how to generate a microservice architecture that uses OAuth 2.0, an API gateway, and two microservices (a blog and a store). The gateway will use PostgreSQL with R2DBC, the blog will use Neo4j, and the store will use MongoDB. All persistence options are powered by Spring Data.

Start by installing JHipster using npm:

Shell
 




xxxxxxxxxx
1


 
1
npm i -g generator-jhipster@beta



After installing JHipster, you can run the following command to answer a whole slew of questions and create an app.

Shell
 




xxxxxxxxxx
1


 
1
jhipster



JHipster code


However, there’s an easier way. JHipster has its own domain language!

Define Your Reactive Java Architecture With JDL

JHipster Domain Language (JDL) offers a way to define apps, so you don’t have to worry about fat-fingering your answer to the jhipster command’s questions.

Create a new directory on your machine and navigate into it in your terminal.

Shell
 




xxxxxxxxxx
1


 
1
take reactive-stack # mkdir reactive-stack && cd reactive-stack
2
git init # initialize git, so apps aren't created with their own .git



Copy the JDL below and put it into a reactive-ms.jdl file.

Java
 




xxxxxxxxxx
1
93


 
1
application {
2
  config {
3
    baseName gateway 
4
    reactive true 
5
    packageName com.okta.developer.gateway
6
    applicationType gateway
7
    authenticationType oauth2 
8
    buildTool gradle 
9
    clientFramework vue 
10
    prodDatabaseType postgresql
11
    serviceDiscoveryType eureka
12
    testFrameworks [protractor]
13
  }
14
  entities Blog, Post, Tag, Product
15
}
16

          
17
application {
18
  config {
19
    baseName blog
20
    reactive true
21
    packageName com.okta.developer.blog
22
    applicationType microservice 
23
    authenticationType oauth2
24
    buildTool gradle
25
    databaseType neo4j
26
    devDatabaseType neo4j
27
    prodDatabaseType neo4j
28
    enableHibernateCache false
29
    serverPort 8081
30
    serviceDiscoveryType eureka
31
  }
32
  entities Blog, Post, Tag
33
}
34

          
35
application {
36
  config {
37
    baseName store
38
    reactive true
39
    packageName com.okta.developer.store
40
    applicationType microservice
41
    authenticationType oauth2
42
    buildTool gradle
43
    databaseType mongodb
44
    devDatabaseType mongodb
45
    prodDatabaseType mongodb
46
    enableHibernateCache false
47
    serverPort 8082
48
    serviceDiscoveryType eureka
49
  }
50
  entities Product
51
}
52

          
53
entity Blog {
54
  name String required minlength(3)
55
  handle String required minlength(2)
56
}
57

          
58
entity Post {
59
  title String required
60
  content TextBlob required
61
  date Instant required
62
}
63

          
64
entity Tag {
65
  name String required minlength(2)
66
}
67

          
68
entity Product {
69
  title String required
70
  price BigDecimal required min(0)
71
  image ImageBlob
72
}
73

          
74
relationship ManyToOne {
75
  Blog{user(login)} to User
76
  Post{blog(name)} to Blog
77
}
78

          
79
relationship ManyToMany {
80
  Post{tag(name)} to Tag{post}
81
}
82

          
83
paginate Post, Tag with infinite-scroll
84
paginate Product with pagination
85

          
86
microservice Product with store
87
microservice Blog, Post, Tag with blog
88

          
89
deployment { 
90
  deploymentType docker-compose
91
  appsFolders [gateway, blog, store]
92
  dockerRepositoryName "mraible"
93
}



  1. The first app is an API gateway.
  2. Because the gateway is reactive, it’ll use Spring Cloud Gateway.
  3. The gateway and microservice apps must use the same authentication type.
  4. Use Gradle, because a lot of y’all love it.
  5. Vue support is new in JHipster 7, let’s use it!
  6. Make sure and specify microservice as the application type for the blog and store apps.
  7. JDL allows you to create Docker Compose and Kubernetes deployments too!

See application configuration options to see the possible values for the above configuration options.

Import this architecture definition and generate gateway, blog, and store apps.

Shell
 




xxxxxxxxxx
1


 
1
jhipster jdl reactive-ms.jdl


As part of this process, several Docker Compose files are generated for you. These allow you to run databases, the JHipster Registry (for service discovery), Keycloak (for identity), all with Docker.

Run Your Reactive Java Microservices

After JHipster finishes generating your apps, you can run them with Gradle. Assuming you’re in the same top-level directories you ran jhipster jdl from, you can run the following commands to start all the backend services for each microservice.

JHipster has a Oh My ZSH! plugin that I highly recommend. It provides aliases for starting Docker containers and is a real time-saver. I’ve included these commands as comments below.

Shell
 




xxxxxxxxxx
1


 
1
cd gateway
2
docker-compose -f src/main/docker/keycloak.yml up -d #jhkeycloakup
3
docker-compose -f src/main/docker/postgresql.yml up -d #jhpostgresqlup
4
docker-compose -f src/main/docker/jhipster-registry.yml up -d #jhregistryup
5
./gradlew





The JHipster Registry is a Netflix Eureka server that handles service discovery. When the gateway and microservices start up, they register with Eureka. This allows communication between services using logical names, rather than IP address or host names. JHipster Registry also contains a Spring Cloud Config server that can distribute configuration between apps. You can learn more about Spring Cloud Config in Spring Cloud Config for Shared Microservice Configuration.

Open a new terminal window, start the blog app’s Neo4j database, and then the app itself.

Shell
 




xxxxxxxxxx
1


 
1
cd ../blog
2
docker-compose -f src/main/docker/neo4j.yml up -d #jhneo4jup
3
./gradlew



Then, open another terminal window, start the store app’s MongoDB database, and the microservice.

Shell
 




xxxxxxxxxx
1


 
1
cd ../store
2
docker-compose -f src/main/docker/mongodb.yml up -d #jhmongoup
3
./gradlew



To make Keycloak work, you need to add the following line to your hosts file (/etc/hosts on Mac/Linux, c:\Windows\System32\Drivers\etc\hosts on Windows).

Java
 




x


 
1
127.0.0.1    keycloak



This is because you will access your application with a browser on your machine (which is named localhost, or 127.0.0.1), but inside Docker, it will run in its own container, which is named keycloak.

Test Your Reactive Java Microservices

Open http://localhost:8080 in your favorite browser. You should be able to login with admin/admin as credentials.

Make sure you can add a new blog, edit existing posts, and add new products.

To prove everything works in an automated fashion, you can run npm run e2e in the gateway project’s directory. This will run a number of end-to-end tests with Protractor.JHipster has support for Cypress, but it doesn’t work with Okta yet.

Prepare Your Reactive Java Stack for Production

Keycloak is a superb open source identity provider. It has excellent support for OAuth 2.0 and OpenID Connect (OIDC) and easily runs in a Docker container. I greatly appreciate Keycloak’s ease-of-use. I also appreciate Spring Security’s OAuth and OIDC support.

Spring Security makes it so you only need to override three properties to switch from Keycloak to Okta!

In production, you might not want to manage your own identity provider instance. That’s where Okta comes in. We’re a developer-friendly SaaS company that provides OAuth and OIDC support as a service. You can create a developer account and use it for free. Our Okta CLI makes it super easy.

Install the Okta CLI using the aforementioned website and come back here when you’re done. If you don’t have an Okta developer account, run okta register.

You can also use your browser and Okta’s developer console to register an app. See JHipster’s security documentation for those instructions.

Then, from the gateway project’s directory, run okta apps create jhipster. Accept the default redirect URIs.


This process does several things:

  1. Registers an OIDC app in Okta with JHipster’s configured redirect URIs.
  2. Creates ROLE_ADMIN and ROLE_USER groups and adds your user to both.
  3. Creates a groups claim and adds it to ID tokens.
  4. Creates a .okta.env file with the values you’ll need to talk to Okta.

Update the JHipster Registry to Distribute OIDC Configuration

I mentioned earlier that Spring Cloud Config allows you to distribute Spring’s configuration between apps. In this section, you’ll configure JHipster’s Spring Security settings to use Okta across all your services.

Add the following YAML to gateway/src/main/docker/central-server-config/localhost-config/application.yml. You can find the values for each property in the .okta.env file.

YAML
 




xxxxxxxxxx
1
11


 
1
spring:
2
  security:
3
    oauth2:
4
      client:
5
        provider:
6
          oidc:
7
            issuer-uri: https://<your-okta-domain>/oauth2/default
8
        registration:
9
          oidc:
10
            client-id: <client-id>
11
            client-secret: <client-secret>



Save your changes. These values will be distributed to the JHipster Registry, gateway, blog, and store apps. Restart the JHipster Registry by running the following commands:

Shell
 




xxxxxxxxxx
1


 
1
docker-compose -f src/main/docker/jhipster-registry.yml down #jhregistrydown
2
docker-compose -f src/main/docker/jhipster-registry.yml up -d #jhregistryup



Use Ctrl+C to kill all your ./gradlew processes and start them again.

Now, open a new incognito browser window, go to http://localhost:8080, and sign in. Rejoice that using Okta for authentication works!

If you’re feeling lucky, you can set your Okta credentials as environment variables and run end-to-end tests (from the gateway directory).

Shell
 




xxxxxxxxxx
1


 
1
export E2E_USERNAME=<your-username>
2
export E2E_PASSWORD=<your-password>
3
npm run e2e



Your JHipster Registry is now configured to use Okta for authentication. You’ll need to add redirect URIs in your Okta app for http://localhost:8761. After making these changes, you should be able to sign in to it.

Create Docker Images for Your Microservice Apps

The JDL you used to create this reactive stack contains Docker configuration, so you can run everything with Docker Compose.

Stop all your apps with Ctrl+C. Stop all your Docker instances too.

Shell
 




xxxxxxxxxx
1


 
1
docker stop $(docker ps -a -q)


To run your reactive stack with Docker Compose, you need to create Docker images for each app. In your three different app directories, run the following Gradle command:

Shell
 




xxxxxxxxxx
1


 
1
./gradlew -Pprod bootJar jibDockerBuild



Run Your Microservices Stack with Docker Compose

Once your Docker containers are finished building, you’ll want to add your Okta settings to Spring Cloud Config in JHipster Registry.

Switch Identity Providers With Spring Cloud Config

Open docker-compose/docker-compose.yml in your favorite IDE (I like IntelliJ IDEA) and remove the Keycloak image at the bottom. You can leave it if you like, but it won’t be used in this example.

Update docker-compose/central-server-config/application.yml to contain your OIDC settings that you want to share with all your microservices.

YAML
 




xxxxxxxxxx
1
11


 
1
spring:
2
  security:
3
    oauth2:
4
      client:
5
        provider:
6
          oidc:
7
            issuer-uri: https://<your-okta-domain>/oauth2/default
8
        registration:
9
          oidc:
10
            client-id: <client-id>
11
            client-secret: <client-secret>



Prove Your Reactive Java Stack Works

In the docker-compose directory, run the following command to start all your containers.

Shell
 




xxxxxxxxxx
1


 
1
docker-compose up


You should be able to open http://localhost:8080, sign in, and access all of your microservices. Pretty slick, eh?! 

What About Kotlin Microservices?

JHipster supports Kotlin-based microservices thanks to its Kotlin blueprint, supported by Sendil Kumar N.

You can install it using npm:

Shell
 




xxxxxxxxxx
1


 
1
npm install -g generator-jhipster-kotlin



Then, use khipster jdl reactive-ms to create the same stack you did above with Kotlin.

How Do I Deploy to the Cloud?

JHipster creates a cloud-native microservices architecture that can be deployed to many cloud providers. There’s specific support for AWS, Microsoft Azure, Heroku, and Google Cloud Platform.

However, if you’re doing microservices, you’ll probably want to leverage Docker as you did in this tutorial. When your apps are containerized, they can be orchestrated with Kubernetes.

JHipster has a Kubernetes sub-generator that you can use to deploy it to the cloud. I’ll cover this in a future tutorial.

In the meantime, you can watch a presentation that Ray Tsang and I did recently that shows how to deploy JHipster microservices with Kubernetes. If you start watching from 46:18, you’ll see Ray show how to deploy to Google Cloud using Kubernetes.


Should You Go Reactive?

As with most software architecture decisions, it depends. Are you building CRUD apps? Then no, Spring MVC is good enough.

Are you dealing with massive amounts of steaming data and millions of customers? Then yes, reactive frameworks like Spring WebFlux might just save you $$$ on your monthly cloud bill.

What about Project Loom? Will it allow you to write regular non-reactive code that performs as good as reactive frameworks? I’m not sure. I’m betting on reactive for now. I think it’s a good skill to have for Java developers.

If you want to learn more about Project Loom, I recommend listening to Episode 8 "Project Loom" with Ron Pressler from the Inside Java Podcast.

Learn More About Reactive Java and Microservices

This tutorial isn’t an in-depth guide to programming reactive Java microservices. That’s because it doesn’t have to be! With JHipster, you can generate high-quality reactive Java code (~70% test coverage) that’s based on fantastic frameworks like Spring Boot, Spring Cloud, Spring WebFlux, and Spring Security.

JHipster also implements most of the patterns in my Security Patterns for Microservice Architectures. You can add dependency scanning with Snyk (based on Brian Vermeer’s blog post), use HTTPS locally, adopt OAuth, add CI/CD, and generate secure Docker containers, just to name a few.

The Spring Cloud Gateway implementation in JHipster is largely based on what I learned when researching and writing Secure Reactive Microservices with Spring Cloud Gateway. Spring Cloud Gateway makes it trivial to relay an access token between a gateway and microservices. It’s just five lines of YAML:

YAML
 




xxxxxxxxxx
1


 
1
spring:
2
  cloud:
3
    gateway:
4
      default-filters:
5
        - TokenRelay



You can find the completed source code for this example on GitHub, in the oktadeveloper/java-microservices-examples repository.

Shell
 




xxxxxxxxxx
1


 
1
git clone https://github.com/oktadeveloper/java-microservices-examples.git
2
cd java-microservices-examples/reactive-jhipster



If you want to learn more about reactive programming’s nitty-gritty details, we have a few posts on this blog.

  • Get Started with Reactive Programming in Spring
  • Build Reactive APIs with Spring WebFlux
  • Full Stack Reactive with Spring WebFlux, WebSockets, and React

I’m proud to say that parts of this series were Josh Long’s initial drafts for his Reactive Spring book.

Keep in touch! If you have questions about this post, please ask them in the comments below. Follow @oktadev on Twitter, subscribe to our YouTube channel, and follow us on LinkedIn

Spring Framework microservice JHipster Java (programming language) Spring Cloud app Spring Boot Docker (software) Spring Security

Published at DZone with permission of Matt Raible, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Spring Cloud Stream: A Brief Guide
  • Distributed Tracing System (Spring Cloud Sleuth + OpenZipkin)
  • Component Tests for Spring Cloud Microservices
  • How Kafka Can Make Microservice Planet a Better Place

Partner Resources

×

Comments
Oops! Something Went Wrong

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!