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.

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

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

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this tutorial, we’ll take a look at the Continuous Integration/Continuous Deployment (CI/CD) process and implement its essential parts.

We’ll create a simple Spring Boot application and then push it to the shared Git repository. After that, we’ll build it with a building integration service, create a Docker image, and push it to a Docker repository.

In the end, we’ll automatically deploy our application to a PaaS service (Heroku).

2. Version Control

The crucial part of CI/CD is the version control system to manage our code. In addition, we need a repository hosting service that our build and deploy steps will tie into.

Let’s choose Git as the VCS and GitHub as our repository provider as they are the most popular at the moment and free to use.

First, we’ll have to create an account on GitHub.

Additionally, we should create a Git repository. Let’s name it baeldung-ci-cd-process. Also, let’s pick a public repository since it will allow us to access other services for free. Lastly, let’s initialize our repository with a README.md.

Now that our repository has been created, we should clone our project locally. To do so, let’s execute this command on our local computer:

git clone https://github.com/$USERNAME/baeldung-ci-cd-process.git

This will initialize our project in the directory where we executed the command. At the moment, it should only contain the README.md file.

3. Creating the Application

In this section, we’ll create a simple Spring Boot application that will take part in the process. We’ll also use Maven as our build tool.

First, let’s initialize our project in the directory where we have cloned the version control repository.

For instance, we can do that with Spring Initializer, adding the web and actuator modules.

3.1. Creating the Application Manually

Or, we can add the spring-boot-starter-web and spring-boot-starter-actuator dependencies manually:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

The first is to introduce a REST endpoint and the second, a health check endpoint.

In addition, let’s add the plugin that’ll allow us to run our application:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
</plugin>

And finally, let’s add a Spring Boot main class:

@SpringBootApplication
public class CiCdApplication {

    public static void main(String[] args) {
        SpringApplication.run(CiCdApplication.class, args);
    }
}

3.2. Pushing

Whether using Spring Initializr or manually creating the project, we’re now ready to commit and push our changes to our repository.

Let’s do that with the following commands:

git add .
git commit -m 'Initialize application'
git push

We can now check if our changes exist in the repository.

4. Build Automation

Another part of the CI/CD process is a service that will build and test our pushed code.

We’ll use Travis CI here, but any building service will work as well.

4.1. Maven Wrapper

Let’s begin by adding a Maven Wrapper to our application. If we’ve used the Spring Initializr, we can skip this part since it’s included by default.

In the application directory, let’s do:

mvn -N io.takari:maven:0.7.7:wrapper

This will add Maven wrapper files, including the mvnw and the mvnw.cmd files that can be used instead of Maven.

While Travis CI has its own Maven, other building services might not. This Maven Wrapper will help us to be prepared for either situation. Also, developers won’t have to install Maven on their machines.

4.2. Building Service

After that, let’s create an account on Travis CI by signing in with our GitHub account. Going forward, we should allow access to our project in GitHub.

Next, we should create a .travis.yml file which will describe the building process in Travis CI. Most of the building services allow us to create such a file, which is located at our repository’s root.

In our case, let’s tell Travis to use Java 11 and the Maven Wrapper to build our application:

language: java
jdk:
  - openjdk11
script:
  - ./mvnw clean install

The language property indicates we want to use Java.

The jdk property says which Docker image to download from DockerHub, openjdk11 in this case.

The script property says what command to run – we want to use our Maven wrapper.

Lastly, we should push our changes to the repository. The Travis CI should automatically trigger the build.

5. Dockerizing

In this section, we’ll build a Docker image with our application and host it on DockerHub as a part of the CD process. It’ll allow us to run it on any machine with ease.

5.1. Repository for Docker Images

First, we should create a Docker repository for our images.

Let’s create an account on DockerHub. Also, let’s create the repository for our project by filling out the appropriate fields:

  • name: baeldung-ci-cd-process
  • visibility: Public
  • Build setting: GitHub

5.2. Docker Image

Now, we’re ready to create a Docker image and push it to DockerHub.

First, let’s add the jib-maven-plugin that will create and push our image with the application to the Docker repository (replace DockerHubUsername with the correct username):

<profile>
    <id>deploy-docker</id>
    <properties>
        <maven.deploy.skip>true</maven.deploy.skip>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>com.google.cloud.tools</groupId>
                <artifactId>jib-maven-plugin</artifactId>
                <version>2.2.0</version>
                <configuration>
                    <to>
                        <image>${DockerHubUsername}/baeldung-ci-cd-process</image>
                        <tags>
                            <tag>${project.version}</tag>
                            <tag>latest</tag>
                        </tags>
                    </to>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

We have added it as part of a Maven profile in order to not trigger it with the default build.

Additionally, we have specified two tags for the image. To learn more about the plugin, visit our article about Jib.

Going forward, let’s adjust our build file (.travis.yml):

before_install:
  - echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
  - docker pull openjdk:11-jre-slim-sid

script:
  - ./mvnw clean install
  - ./mvnw deploy jib:build -P deploy-docker

With these changes, the build service will log in to DockerHub before building the application. Additionally, it’ll execute the deploy phase with our profile. During that phase, our application will be pushed as an image to the Docker repository.

Lastly, we should define DOCKER_PASSWORD and DOCKER_USERNAME variables in our build service. In Travis CI, these variables can be defined as part of the build settings.

Now, let’s push our changes to the VCS. The build service should automatically trigger the build with our changes.

We can check if the Docker image has been pushed to the repository by running locally:

docker run -p 8080:8080 -t $DOCKER_USERNAME/baeldung-ci-cd-process

Now, we should be able to access our health check by accessing http://localhost:8080/actuator/health.

6. Code Analysis

The next thing we’ll include in our CI/CD process is static code analysis. The main goal of such a process is to ensure the highest code quality. For instance, it could detect that we don’t have enough test cases or that we have some security issues.

Let’s integrate with CodeCov, which will inform us about our test coverage.

Firstly, we should log in to CodeCov with our GitHub profile to establish integration.

Secondly, we should make changes to our code. Let’s begin by adding the jacoco plugin:

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>0.8.11</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>report</id>
            <phase>test</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

The plugin is responsible for generating test reports that will be used by CodeCov.

Next, we should adjust the script section in our build service file (.travis.yml):

script:
  - ./mvnw clean org.jacoco:jacoco-maven-plugin:prepare-agent install
  - ./mvnw deploy jib:build -P deploy-docker

after_success:
  - bash <(curl -s https://codecov.io/bash)

We instructed the jacoco plugin to trigger during the clean install phase. Additionally, we’ve included the after_success section, which will send the report to CodeCov after the build is successful.

Going forward, we should add a test class to our application. For instance, it could be a test for the main class:

@SpringBootTest
class CiCdApplicationIntegrationTest {

    @Test
    public void contextLoads() {

    }
}

Lastly, we should push our changes. The build should be triggered and the report should be generated in our CodeCov profile related to the repository.

7. Deploying the Application

As the last part of our process, we’ll deploy our application. With a Docker image available for use, we can deploy it on any service. For instance, we could deploy it on cloud-based PaaS or IaaS.

Let’s deploy our application to Heroku, which is a PaaS that requires minimal setup.

First, we should create an account and then log in.

Next, let’s create the application space in Heroku and name it baeldung-ci-cd-processThe name of the application must be unique, so we might need to use another one.

We’ll deploy it by integrating Heroku with GitHub, as it’s the simplest solution. However, we could also have written the pipeline that would use our Docker image.

Going forward, we should include the heroku plugin in our pom:

<profile>
    <id>deploy-heroku</id>
    <properties>
        <maven.deploy.skip>true</maven.deploy.skip>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>com.heroku.sdk</groupId>
                <artifactId>heroku-maven-plugin</artifactId>
                <version>3.0.2</version>
                <configuration>
                    <appName>spring-boot-ci-cd</appName>
                    <processTypes>
                        <web>java $JAVA_OPTS -jar -Dserver.port=$PORT target/${project.build.finalName}.jar</web>
                    </processTypes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</profile>

Like with Docker, we’ve added it as part of the Maven profile. Additionally, we’ve included a startup command in the web section.

Next, we should adjust our build service file (.travis.yml) to deploy the application to Heroku as well:

script:
  - ./mvnw clean install
  - ./mvnw heroku:deploy jib:build -P deploy-heroku,deploy-docker

Additionally, let’s add the Heroku API-KEY in a HEROKU_API_KEY variable in our building service.

Lastly, let’s commit our changes. The application should be deployed to Heroku after the build has finished.

We can check it by accessing https://baeldung-ci-cd-process.herokuapp.com/actuator/health

8. Conclusion

In this article, we’ve learned what the essential parts of the CI/CD process are and how to prepare them.

First, we prepared a Git repository in GitHub and pushed our application there. Then, we used Travis CI as a build tool to build our application from that repository.

After that, we created a Docker image and pushed it to DockerHub.

Next, we added a service that’s responsible for static code analysis.

Lastly, we deployed our application to PaaS and accessed it.

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.

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