Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Browser testing is essential if you have a website or web applications that users interact with. Manual testing can be very helpful to an extent, but given the multiple browsers available, not to mention versions and operating system, testing everything manually becomes time-consuming and repetitive.

To help automate this process, Selenium is a popular choice for developers, as an open-source tool with a large and active community. What's more, we can further scale our automation testing by running on theLambdaTest cloud-based testing platform.

Read more through our step-by-step tutorial on how to set up Selenium tests with Java and run them on LambdaTest:

>> Automated Browser Testing With Selenium

Partner – Orkes – NPI EA (cat=Java)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LSS – NPI (cat=Spring Security)
announcement - icon

If you're working on a Spring Security (and especially an OAuth) implementation, definitely have a look at the Learn Spring Security course:

>> LEARN SPRING SECURITY

1. Introduction

Simply put, a microservice architecture allows us to break up our system and our API into a set of self-contained services, which can be deployed fully independently.

While this is great from a continuous deployment and management point of view, it can quickly become convoluted when it comes to API usability. With different endpoints to manage, dependent applications will need to manage CORS (Cross-Origin Resource Sharing) and a diverse set of endpoints.

Zuul is an edge service that allows us to route incoming HTTP requests into multiple backend microservices. For one thing, this is important for providing a unified API for consumers of our backend resources.

Basically, Zuul allows us to unify all of our services by sitting in front of them and acting as a proxy. It receives all requests and routes them to the correct service. To an external application, our API appears as a unified API surface area.

In this tutorial, we’ll talk about how we can use it for this exact purpose, in conjunction with an OAuth 2.0 and JWTs, to be the front line for securing our web services. Specifically, we’ll be using the Password Grant flow to obtain an Access Token to the protected resources.

A quick but important note is that we’re only using the Password Grant flow to explore a simple scenario; most clients will more likely be using the Authorization Grant flow in production scenarios.

2. Adding Zuul Maven Dependencies

Let’s begin by adding Zuul to our project. We do this by adding the spring-cloud-starter-netflix-zuul artifact:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
    <version>2.0.2.RELEASE</version>
</dependency>

3. Enabling Zuul

The application that we’d like to route through Zuul contains an OAuth 2.0 Authorization Server which grants access tokens and a Resource Server which accepts them. These services live on two separate endpoints.

We’d like to have a single endpoint for all external clients of these services, with different paths branching off to different physical endpoints. To do so, we’ll introduce Zuul as an edge service.

To do this, we’ll create a new Spring Boot application, called GatewayApplication. We’ll then simply decorate this application class with the @EnableZuulProxy annotation, which will cause a Zuul instance to be spawned:

@EnableZuulProxy
@SpringBootApplication
public class GatewayApplication {
    public static void main(String[] args) {
	SpringApplication.run(GatewayApplication.class, args);
    }
}

4. Configuring Zuul Routes

Before we can go any further, we need to configure a few Zuul properties. The first thing we’ll configure is the port on which Zuul is listening for incoming connections. That needs to go into the /src/main/resources/application.yml file:

server:
    port: 8080

Now for the fun stuff, configuring the actual routes that Zuul will forward to. To do that, we need to note the following services, their paths and the ports that they listen on.

The Authorization Server is deployed on: http://localhost:8081/spring-security-oauth-server/oauth

The Resource Server is deployed on: http://localhost:8082/spring-security-oauth-resource

The Authorization Server is an OAuth identity provider. It exists to provide authorization tokens to the Resource Server, which in turn provides some protected endpoints.

The Authorization Server provides an Access Token to the Client, which then uses the token to execute requests against the Resource Server, on behalf of the Resource Owner. A quick run through the OAuth terminology will help us keep these concepts in view.

Now let’s map some routes to each of these services:

zuul:
  routes:
    spring-security-oauth-resource:
      path: /spring-security-oauth-resource/**
      url: http://localhost:8082/spring-security-oauth-resource
    oauth:
      path: /oauth/**
      url: http://localhost:8081/spring-security-oauth-server/oauth	 

At this point, any request reaching Zuul on localhost:8080/oauth/** will be routed to the authorization service running on port 8081. Any request to localhost:8080/spring-security-oauth-resource/** will be routed to the resource server running on 8082.

5. Securing Zuul External Traffic Paths

Even though our Zuul edge service is now routing requests correctly, it’s doing so without any authorization checks. The Authorization Server sitting behind /oauth/*, creates a JWT for each successful authentication. Naturally, it’s accessible anonymously.

The Resource Server – located at /spring-security-oauth-resource/**, on the other hand, should always be accessed with a JWT to ensure that an authorized Client is accessing the protected resources.

First, we’ll configure Zuul to pass through the JWT to services that sit behind it. In our case here, those services themselves need to validate the token.

We do that by adding sensitiveHeaders: Cookie,Set-Cookie.

This completes our Zuul configuration:

server:
  port: 8080
zuul:
  sensitiveHeaders: Cookie,Set-Cookie
  routes:
    spring-security-oauth-resource:
      path: /spring-security-oauth-resource/**
      url: http://localhost:8082/spring-security-oauth-resource
    oauth:
      path: /oauth/**
      url: http://localhost:8081/spring-security-oauth-server/oauth

After we’ve got that out of the way, we need to deal with authorization at the edge. Right now, Zuul will not validate the JWT before passing it on to our downstream services. These services will validate the JWT themselves, but ideally, we’d like to have the edge service do that first and reject any unauthorized requests before they propagate deeper into our architecture.

Let’s set up Spring Security to ensure that authorization is checked in Zuul.

First, we’ll need to bring in the Spring Security dependencies into our project. We want spring-security-oauth2 and spring-security-jwt:

<dependency>
    <groupId>org.springframework.security.oauth</groupId>
    <artifactId>spring-security-oauth2</artifactId>
    <version>2.3.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.security</groupId>
    <artifactId>spring-security-jwt</artifactId>
    <version>1.0.9.RELEASE</version>
</dependency>

Now let’s write a configuration for the routes we want to protect by extending ResourceServerConfigurerAdapter:

@Configuration
@Configuration
@EnableResourceServer
public class GatewayConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(final HttpSecurity http) throws Exception {
	http.authorizeRequests()
          .antMatchers("/oauth/**")
          .permitAll()
          .antMatchers("/**")
	  .authenticated();
    }
}

The GatewayConfiguration class defines how Spring Security should handle incoming HTTP requests through Zuul. Inside the configure method, we’ve first matched the most restrictive path using antMatchers and then allowed anonymous access through permitAll.

That is all requests coming into /oauth/** should be allowed through without checking for any authorization tokens. This makes sense because that’s the path from which authorization tokens are generated.

Next, we’ve matched all other paths with /**, and through a call to authenticated insisted that all other calls should contain Access Tokens.

6. Configuring the Key Used for JWT Validation

Now that the configuration is in place, all requests routed to the /oauth/** path will be allowed through anonymously, while all other requests will require authentication.

There is one thing we’re missing here though, and that’s the actual secret required to verify that the JWT is valid. To do that, we need to provide the key (which is symmetric in this case) used to sign the JWT. Rather than writing the configuration code manually, we can use spring-security-oauth2-autoconfigure.

Let’s start by adding the artifact to our project:

<dependency>
    <groupId>org.springframework.security.oauth.boot</groupId>
    <artifactId>spring-security-oauth2-autoconfigure</artifactId>
    <version>2.1.2.RELEASE</version>
</dependency>

Next, we need to add a few lines of configuration to our application.yaml file to define the key used to sign the JWT:

security:
  oauth2:
    resource:
      jwt:
        key-value: 123

The line key-value: 123 sets the symmetric key used by the Authorization Server to sign the JWT. This key will be used by spring-security-oauth2-autoconfigure to configure token parsing.

It’s important to note that, in a production system, we shouldn’t use a symmetric key, specified in the source code of the application. That naturally needs to be configured externally.

7. Testing the Edge Service

7.1. Obtaining an Access Token

Now let’s test how our Zuul edge service behaves – with a few curl commands.

First, we’ll see how we can obtain a new JWT from the Authorization Server, using the password grant.

Here we exchange a username and password in for an Access Token. In this case, we use ‘john‘ as the username and ‘123‘ as the password:

curl -X POST \
  http://localhost:8080/oauth/token \
  -H 'Authorization: Basic Zm9vQ2xpZW50SWRQYXNzd29yZDpzZWNyZXQ=' \
  -H 'Cache-Control: no-cache' \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  -d 'grant_type=password&password=123&username=john'

This call yields a JWT token which we can then use for authenticated requests against our Resource Server.

Notice the “Authorization: Basic…” header field. This exists to tell the Authorization Server which client is connecting to it.

It’s to the Client (in this case the cURL request) what the username and password are to the user:

{    
    "access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX...",
    "token_type":"bearer",    
    "refresh_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpX...",
    "expires_in":3599,
    "scope":"foo read write",
    "organization":"johnwKfc",
    "jti":"8e2c56d3-3e2e-4140-b120-832783b7374b"
}

7.2. Testing a Resource Server Request

We can then use the JWT we retrieved from the Authorization Server to now execute a query against the Resource Server:

curl -X GET \
curl -X GET \
  http:/localhost:8080/spring-security-oauth-resource/users/extra \
  -H 'Accept: application/json, text/plain, */*' \
  -H 'Accept-Encoding: gzip, deflate' \
  -H 'Accept-Language: en-US,en;q=0.9' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXV...' \
  -H 'Cache-Control: no-cache' \

The Zuul edge service will now validate the JWT before routing to the Resource Server.

This then extracts key fields from the JWT and checks for more granular authorization before responding to the request:

{
    "user_name":"john",
    "scope":["foo","read","write"],
    "organization":"johnwKfc",
    "exp":1544584758,
    "authorities":["ROLE_USER"],
    "jti":"8e2c56d3-3e2e-4140-b120-832783b7374b",
    "client_id":"fooClientIdPassword"
}

8. Security Across Layers

It’s important to note that the JWT is being validated by the Zuul edge service before being passed into the Resource Server. If the JWT is invalid, then the request will be denied at the edge service boundary.

If the JWT is indeed valid on the other hand, the request is passed on downstream. The Resource Server then validates the JWT again and extracts key fields such as user scope, organization (in this case a custom field) and authorities. It uses these fields to decide what the user can and can’t do.

To be clear, in a lot of architectures, we won’t actually need to validate the JWT twice – that’s a decision you’ll have to make based on your traffic patterns.

For example, in some production projects, individual Resource Servers may be accessed directly, as well as through the proxy – and we may want to verify the token in both places. In other projects, traffic may be coming only through the proxy, in which case verifying the token there is enough.

9. Summary

As we’ve seen Zuul provides an easy, configurable way to abstract and define routes for services. Together with Spring Security, it allows us to authorize requests at service boundaries.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

Course – LSS – NPI (cat=Security/Spring Security)
announcement - icon

I just announced the new Learn Spring Security course, including the full material focused on the new OAuth2 stack in Spring Security:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)