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

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.

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

Regression testing is an important step in the release process, to ensure that new code doesn't break the existing functionality. As the codebase evolves, we want to run these tests frequently to help catch any issues early on.

The best way to ensure these tests run frequently on an automated basis is, of course, to include them in the CI/CD pipeline. This way, the regression tests will execute automatically whenever we commit code to the repository.

In this tutorial, we'll see how to create regression tests using Selenium, and then include them in our pipeline using GitHub Actions:, to be run on the LambdaTest cloud grid:

>> How to Run Selenium Regression Tests With GitHub Actions

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

1. Overview

We saw in the previous installments of the series how we can leverage Spring Remoting and the related technologies to enable synchronous Remote Procedure Calls on top of an HTTP channel between a server and a client.

In this article, we’ll explore Spring Remoting on top of AMQP, which makes it possible to execute synchronous RPC while leveraging a medium that is inherently asynchronous.

2. Installing RabbitMQ

There are various messaging systems that are compatible with AMQP that we could use, and we choose RabbitMQ because it’s a proven platform and it’s fully supported in Spring – both products are managed by the same company (Pivotal).

If you’re not acquainted with AMQP or RabbitMQ you can read our quick introduction.

So, the first step is to install and start RabbitMQ. There are various ways to install it – just choose your preferred method following the steps mentioned in the official guide.

3. Maven Dependencies

We are going to set up server and client Spring Boot applications to show how AMQP Remoting works. As is often the case with Spring Boot, we just have to choose and import the correct starter dependencies, as explained here:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-amqp</artifactId>
    <exclusions>
        <exclusion>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-tomcat</artifactId>
        </exclusion>
    </exclusions>
</dependency>

We explicitly excluded the spring-boot-starter-tomcat because we don’t need any embedded HTTP server – that would be automatically started instead if we allowed Maven to import all the transitive dependencies in the classpath.

4. Server Application

4.1. Expose the Service

As we showed in the previous articles, we’ll expose a CabBookingService that simulates a likely remote service.

Let’s start by declaring a bean that implements the interface of the service we want to make remotely callable. This is the bean that will actually execute the service call at server-side:

@Bean 
CabBookingService bookingService() {
    return new CabBookingServiceImpl();
}

Let’s then define the queue from which the server will retrieve invocations. It’s enough, in this case, to specify a name for it, providing it in the constructor:

@Bean 
Queue queue() {
    return new Queue("remotingQueue");
}

As we already know from the previous articles, one of the main concepts of Spring Remoting is the Service Exporter, the component that actually collects the invocation requests from some source ─ in this case, a RabbitMQ queue ─ and invokes the desired method on the service implementation.

In this case, we define an AmqpInvokerServiceExporter that ─ as you can see ─ needs a reference to an AmqpTemplate. The AmqpTemplate class is provided by the Spring Framework and eases the handling of AMQP-compatible messaging systems the same way the JdbcTemplate makes easier to deal with databases.

We won’t explicitly define such AmqpTemplate bean because it will be automatically provided by Spring Boot‘s auto-configuration module:

@Bean AmqpInvokerServiceExporter exporter(
  CabBookingService implementation, AmqpTemplate template) {
 
    AmqpInvokerServiceExporter exporter = new AmqpInvokerServiceExporter();
    exporter.setServiceInterface(CabBookingService.class);
    exporter.setService(implementation);
    exporter.setAmqpTemplate(template);
    return exporter;
}

Finally, we need to define a container that has the responsibility to consume messages from the queue and forward them to some specified listener.

We’ll then connect this container to the service exporter, we created in the previous step, to allow it to receive the queued messages. Here the ConnectionFactory is automatically provided by Spring Boot the same way the AmqpTemplate is:

@Bean 
SimpleMessageListenerContainer listener(
  ConnectionFactory facotry, 
  AmqpInvokerServiceExporter exporter, 
  Queue queue) {
 
    SimpleMessageListenerContainer container
     = new SimpleMessageListenerContainer(facotry);
    container.setMessageListener(exporter);
    container.setQueueNames(queue.getName());
    return container;
}

4.2. Configuration

Let’s remember to set up the application.properties file to allow Spring Boot to configure the basic objects. Obviously, the values of the parameters will also depend on the way RabbitMQ has been installed.

For instance, the following one could be a reasonable configuration when RabbitMQ runs it the same machine where this example runs:

spring.rabbitmq.dynamic=true
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.host=localhost

5. Client Application

5.1. Invoke the Remote Service

Let’s tackle the client now. Again, we need to define the queue where invocation messages will be written to. We need to double-check that both client and server use the same name.

@Bean 
Queue queue() {
    return new Queue("remotingQueue");
}

At client-side, we need a slightly more complex setup than on the server side. In fact, we need to define an Exchange with the related Binding:

@Bean 
Exchange directExchange(Queue someQueue) {
    DirectExchange exchange = new DirectExchange("remoting.exchange");
    BindingBuilder
      .bind(someQueue)
      .to(exchange)
      .with("remoting.binding");
    return exchange;
}

A good intro on the main concepts of RabbitMQ as Exchanges and Bindings is available here.

Since Spring Boot does not auto-configure the AmqpTemplate, we must set one up ourselves, specifying a routing key. In doing so, we need to double-check that the routing key and the exchange match with the one used to define the Exchange in the previous step:

@Bean RabbitTemplate amqpTemplate(ConnectionFactory factory) {
    RabbitTemplate template = new RabbitTemplate(factory);
    template.setRoutingKey("remoting.binding");
    template.setExchange("remoting.exchange");
    return template;
}

Then, as we did with other Spring Remoting implementations, we define a FactoryBean that will produce local proxies of the service that is remotely exposed. Nothing too fancy here, we just need to provide the interface of the remote service:

@Bean AmqpProxyFactoryBean amqpFactoryBean(AmqpTemplate amqpTemplate) {
    AmqpProxyFactoryBean factoryBean = new AmqpProxyFactoryBean();
    factoryBean.setServiceInterface(CabBookingService.class);
    factoryBean.setAmqpTemplate(amqpTemplate);
    return factoryBean;
}

We can now use the remote service as if it was declared as a local bean:

CabBookingService service = context.getBean(CabBookingService.class);
out.println(service.bookRide("13 Seagate Blvd, Key Largo, FL 33037"));

5.2. Setup

Also for the client application, we have to properly choose the values in the application.properties file. In a common setup, those would exactly match the ones used on the server side.

5.3. Run the Example

This should be enough to demonstrate the remote invocation through RabbitMQ. Let’s then start RabbitMQ, the server application, and the client application that invokes the remote service.

What happens behind the scenes is that the AmqpProxyFactoryBean will build a proxy that implements the CabBookingService.

When a method is invoked on that proxy, it queues a message on the RabbitMQ, specifying in it all the parameters of the invocation and a name of a queue to be used to send back the result.

The message is consumed from the AmqpInvokerServiceExporter that invokes the actual implementation. It then collects the result in a message and places it on the queue which name was specified in the incoming message.

The AmqpProxyFactoryBean receives back the result and, finally, returns the value that has been originally produced at the server side.

6. Conclusion

In this article, we saw how we can use Spring Remoting to provide RPC on top of a messaging system.

It’s probably not the way to go for the main scenarios where we probably prefer to leverage the asynchronicity of RabbitMQ, but in some selected and limited scenarios, a synchronous call can be easier to understand and quicker and simpler to develop.

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.

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 – LS – NPI – (cat=Spring)
announcement - icon

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

>> CHECK OUT THE COURSE

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