Skip to main content
Redhat Developers  Logo
  • Products

    Platforms

    • Red Hat Enterprise Linux
      Red Hat Enterprise Linux Icon
    • Red Hat AI
      Red Hat AI
    • Red Hat OpenShift
      Openshift icon
    • Red Hat Ansible Automation Platform
      Ansible icon
    • View All Red Hat Products

    Featured

    • Red Hat build of OpenJDK
    • Red Hat Developer Hub
    • Red Hat JBoss Enterprise Application Platform
    • Red Hat OpenShift Dev Spaces
    • Red Hat OpenShift Local
    • Red Hat Developer Sandbox

      Try Red Hat products and technologies without setup or configuration fees for 30 days with this shared Openshift and Kubernetes cluster.
    • Try at no cost
  • Technologies

    Featured

    • AI/ML
      AI/ML Icon
    • Linux
      Linux Icon
    • Kubernetes
      Cloud icon
    • Automation
      Automation Icon showing arrows moving in a circle around a gear
    • View All Technologies
    • Programming Languages & Frameworks

      • Java
      • Python
      • JavaScript
    • System Design & Architecture

      • Red Hat architecture and design patterns
      • Microservices
      • Event-Driven Architecture
      • Databases
    • Developer Productivity

      • Developer productivity
      • Developer Tools
      • GitOps
    • Automated Data Processing

      • AI/ML
      • Data Science
      • Apache Kafka on Kubernetes
    • Platform Engineering

      • DevOps
      • DevSecOps
      • Ansible automation for applications and services
    • Secure Development & Architectures

      • Security
      • Secure coding
  • Learn

    Featured

    • Kubernetes & Cloud Native
      Openshift icon
    • Linux
      Rhel icon
    • Automation
      Ansible cloud icon
    • AI/ML
      AI/ML Icon
    • View All Learning Resources

    E-Books

    • GitOps Cookbook
    • Podman in Action
    • Kubernetes Operators
    • The Path to GitOps
    • View All E-books

    Cheat Sheets

    • Linux Commands
    • Bash Commands
    • Git
    • systemd Commands
    • View All Cheat Sheets

    Documentation

    • Product Documentation
    • API Catalog
    • Legacy Documentation
  • Developer Sandbox

    Developer Sandbox

    • Access Red Hat’s products and technologies without setup or configuration, and start developing quicker than ever before with our new, no-cost sandbox environments.
    • Explore Developer Sandbox

    Featured Developer Sandbox activities

    • Get started with your Developer Sandbox
    • OpenShift virtualization and application modernization using the Developer Sandbox
    • Explore all Developer Sandbox activities

    Ready to start developing apps?

    • Try at no cost
  • Blog
  • Events
  • Videos

Migrating a Spring Boot microservices application to Quarkus

April 10, 2020
Cheng Kuan Gan
Related topics:
JavaKubernetesQuarkus
Related products:
Red Hat build of Quarkus

Share:

    While Spring Boot has long been the de-facto framework for developing container-based applications in Java, the performance benefits of a Kubernetes-native framework are hard to ignore. In this article, I will show you how to quickly migrate a Spring Boot microservices application to Quarkus. Once the migration is complete, we'll test the application and compare startup times between the original Spring Boot application and the new Quarkus app.

    Note: For developers interested in migrating from Spring Boot to Quarkus, it's important to know that Quarkus does not support all of Spring Boot's extensions and features. As one example, it only supports a subset of the Java EE Contexts and Dependency Injection (CDI) API. Migrating microservices or container-based applications to Quarkus will be easier than migrating monolithic ones.

    About Quarkus

    Quarkus is a Kubernetes-native Java framework tailored for Java virtual machines (JVMs) such as GraalVM and HotSpot. Being Kubernetes-native means that Quarkus takes a container-first approach to Java application development. The smaller footprint inherent in container-first development makes Quarkus one of the best options for running Java applications on Kubernetes and serverless platforms today.

    The Spring Boot application

    For our example application, we'll use the AccountBalance microservices application from my previous article, Event-based microservices with Red Hat AMQ Streams. The AccountBalance service has its own MongoDB database, which holds account-balance information. The database is also called by other services, such as the EventCorrelator service.

    You can find the source code for the example application on GitHub. I'll guide you through each step of migrating this application from Spring Boot to Quarkus.

    The following shows the content of the sample source code. This is typical standard Java project file structure. mvnw is Maven wrapper plugin that we generated. We will need to modify the pom.xml and the source codes under the src/main.

    Sample Codes Content
    Sample Codes Content
    img class=

    Sample Codes Content">

     

    Step 1: Modify the pom.xml for your application

    The simplest way to migrate from Spring Boot to Quarkus is to bootstrap a sample Quarkus application and use that application's pom.xml as a template for modifying the same file in your Spring Boot application.

    Note: In addition to the example pom.xml, the Quarkus team provides a web-based user interface (UI) that you can use for migration. I won't demonstrate using the web UI in this article.

    Take a minute to set up your terminal and project, as described in the bootstrapping instructions. Once you have your project set up, we can begin modifying the Spring Boot pom.xml. We'll start by removing Spring Boot configurations we no longer need, then we'll replace those elements with the corresponding configurations for a Quarkus app.

    Remove the Spring Boot configurations

    First, we remove the packing configuration from the example application's pom.xml. This no longer needed because it is taken care by the <build> part in the pom.xml configuration.

    <!--- Remove the packing configuration -->
    
    <packaging>jar</packaging>
    

    spring-boot-starter-parent is for Spring Boot application which is no longer needed here.

    <!--- Remove spring-boot-starter-parent -->
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.4.2.RELEASE</version>
    </parent>
    

    same goes to spring-cloud-dependencies:

    <!-- Remove the following from the <dependencyManagement> -->
    
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-dependencies</artifactId>
    <version>Brixton.SR4</version>
    

    Now, we can remove all of the remaining Spring Boot dependencies:

    <!-- Remove all Spring Boot-related dependencies -->
    
    <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-data-mongodb</artifactId>
     </dependency>
     <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.data</groupId>
      <artifactId>spring-data-commons</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-websocket</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-messaging</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-context</artifactId>
    </dependency>
    <dependency>
      <groupId>javax.ws.rs</groupId>
      <artifactId>javax.ws.rs-api</artifactId>
      <version>2.0.1</version>
    </dependency>
    <dependency>
      <groupId>org.apache.maven</groupId>
      <artifactId>maven-model</artifactId>
      <version>3.3.9</version>
    </dependency>
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.2.11</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-core</artifactId>
      <version>2.2.11</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.2.11</version>
    </dependency>
    <dependency>
      <groupId>javax.activation</groupId>
      <artifactId>activation</artifactId>
      <version>1.1.1</version>
    </dependency>
    

    We can also take out the spring-boot-maven-plugin in the build section:

    <!-- Remove the spring-boot-maven plugin from the build section -->
    
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
    </plugin>
    

    Add Quarkus elements to the pom.xml

    Next, we'll copy the properties and dependencies from the bootstrapped Quarkus pom.xml and paste them in at the top of the pom.xml for our example application. This section is important to tell the compiler which version of components that we want to use for our Quarkus. Quarkus release is moving fast, you may want to check the latest version for <quarkus.platform.version>

    <!-- Place this at the top of the pom.xml -->
    
    <properties>
      <compiler-plugin.version>3.8.1</compiler-plugin.version>
      <maven.compiler.parameters>true</maven.compiler.parameters>
      <maven.compiler.source>1.8</maven.compiler.source>
      <maven.compiler.target>1.8</maven.compiler.target>
      <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
      <quarkus-plugin.version>1.2.1.Final</quarkus-plugin.version>
      <quarkus.platform.artifact-id>quarkus-universe-bom</quarkus.platform.artifact-id>
      <quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
      <quarkus.platform.version>1.2.1.Final</quarkus.platform.version>
      <surefire-plugin.version>2.22.1</surefire-plugin.version>
    </properties>
    

    Add this under dependencyManagement:

    <!-- Add this under dependencyManagement -->
    
    <dependencyManagement>
      <dependencies>
        <dependency>
          <groupId>${quarkus.platform.group-id}</groupId>
          <artifactId>${quarkus.platform.artifact-id}</artifactId>
          <version>${quarkus.platform.version}</version>
          <type>pom</type>
          <scope>import</scope>
        </dependency>
      </dependencies>
    </dependencyManagement>
    

    Now we can copy the Quarkus dependencies from the bootstrap file and paste them into the pom.xml. Note that in the code below, I also manually added the MongoDB Panache dependency, which the example application requires. I added this dependency manually because I did not use the web UI to bootstrap it in earlier. Note, also, that AccountBalance uses a repository to connect to and query the MongoDB database. The Panache extension allows us to migrate the existing code with minimal changes. (You can find the source code for Panache on GitHub.)

    Start by adding these dependencies to the pom.xml:

    <dependency>
      <groupId>io.quarkus</groupId>
    
      <!-- notice this app is using jsonb -->
    
      <artifactId>quarkus-resteasy-jsonb</artifactId>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-junit5</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.rest-assured</groupId>
      <artifactId>rest-assured</artifactId>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-mongodb-panache</artifactId>
    </dependency>
    

    Add the quarkus-maven-plugin under the build configuration:

    <!-- Add the following plugin under the build configuration -->
    
    <build>
      <finalName>${project.artifactId}-${project.version}</finalName>
      <plugins>
        <plugin>
          <groupId>io.quarkus</groupId>
          <artifactId>quarkus-maven-plugin</artifactId>
          <version>${quarkus-plugin.version}</version>
          <executions>
            <execution>
              <goals>
                <goal>build</goal>
              </goals>
            </execution>
          </executions>
        </plugin>
        <plugin>
          <artifactId>maven-compiler-plugin</artifactId>
            <version>${compiler-plugin.version}</version>
        </plugin>
        <plugin>
          <artifactId>maven-surefire-plugin</artifactId>
          <version>${surefire-plugin.version}</version>
          <configuration>
            <systemProperties>
              <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
            </systemProperties>
          </configuration>
        </plugin>
      </plugins>
    </build>
    

    Finally, add the profiles settings:

    <!-- Add the following profiles settings -->
    
    <profiles>
      <profile>
        <id>native</id>
        <activation>
          <property>
            <name>native</name>
          </property>
        </activation>
        <build>
          <plugins>
            <plugin>
              <artifactId>maven-failsafe-plugin</artifactId>
                <version>${surefire-plugin.version}</version>
                <executions>
                  <execution>
                    <goals>
                      <goal>integration-test</goal>
                      <goal>verify</goal>
                    </goals>
                    <configuration>
                      <systemProperties>
                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
                      </systemProperties>
                    </configuration>
                  </execution>
                </executions>
              </plugin>
            </plugins>
         </build>
         <properties>
           <quarkus.package.type>native</quarkus.package.type>
         </properties>
      </profile>
    </profiles>
    

    Step 2: Migrate the Spring Boot application code

    The Maven POM is all set. We're now ready to migrate the Spring Boot application code to Quarkus.

    First, remove the Application.java class. We don't need it anymore. You can also modify the application.properties for the application port and the MongoDB client properties files, as shown here:

    ### --- Remove the Spring Boot properties
    # spring.application.name=accountbalance-service
    # spring.data.mongodb.host=localhost
    # spring.data.mongodb.port=27017
    # spring.data.mongodb.username=checkbalance
    # spring.data.mongodb.password=checkbalance
    # spring.data.mongodb.database=checkbalance
    # server.port=8082
    ### --- Replace with equivalent Quarkus MongoDB properties
    quarkus.mongodb.connection-string=mongodb://checkbalance:checkbalance@localhost:27017/checkbalance
    # --- Note the wrong context of database name ... planning and design before coding is so important.
    quarkus.mongodb.database=checkbalance
    quarkus.http.port=8082
    

    The entity bean code

    Next, we'll change the entity bean code in Balance.java. To start, remove the Spring Boot-related import statements. We are going to replace these with Quarkus equivalent components in the next section.

    /// --- Remove the Spring Boot-related import statements
    
    import org.bson.types.ObjectId;
    import org.springframework.data.annotation.Id;
    import org.springframework.data.mongodb.core.mapping.Document;
    

    Add the equivalent import statements for Quarkus. Quarkus framework provides its own supported components for MongoDB via the MongoDB Panache extension. Quarkus also provides its own version of CDI annotation. This where we provide the correct import statements for those.

    /// --- Add the following Quarkus-related import statements
    
    import io.quarkus.mongodb.panache.MongoEntity;
    import io.quarkus.mongodb.panache.PanacheMongoEntity;
    import org.bson.codecs.pojo.annotations.BsonProperty;
    import org.bson.codecs.pojo.annotations.BsonId;
    import io.quarkus.mongodb.panache.PanacheQuery;
    

    Replace the existing @Document annotation with @MongoEntity:

    /// --- Replace @Document annotation with @MongoEntity
    
    // --- @Document(collection = "balance") <--- Remove this
    @MongoEntity(collection="balance")
    public class Balance extends PanacheMongoEntity{
    /// --- More codes here are omitted ...
    ...

    Replace Spring Boot's @Id annotation with Quarkus's @BsonId:

    /// --- Replace @Id annotation with @BsonId
    
    // @Id <--- Remove this
    @BsonId  //In fact, we do not need this. Just leave it here for now.
    private String _id;
    

    The repository class

    We also need to modify the Spring Boot repository class, BalanceRepository.java. To start, remove the following import statement:

    /// --- Remove the following import statement
    
    import org.springframework.data.mongodb.repository.MongoRepository;
    

    Replace it with this one:

    /// --- Add the following import statements
    
    import io.quarkus.mongodb.panache.PanacheMongoRepository;
    import javax.enterprise.context.ApplicationScoped;
    import io.quarkus.mongodb.panache.PanacheQuery;
    

    Then make three more quick changes:

    /// --- Change the BalanceRepository to implement PanacheMongoRepository
    // --- Change the BalanceRepository from interface to class
    // --- Drop in the @ApplicationScoped annotation
    
    @ApplicationScoped
    public class BalanceRepository implements PanacheMongoRepository<Balance> {
       // --- Change the findByAccountId(String accountId) to the following implementation
       public Balance findByAccountId(String accountId){
          return find("accountId", accountId).firstResult();
       }
    }
    

    The REST class

    We'll also modify AccountBalance.java. Start by removing all of the Spring Boot-related import statements:

    /// --- Remove all the Spring Boot-related import statements
    
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestBody;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.bind.annotation.RestController;
    import org.springframework.core.env.Environment;
    import org.springframework.data.domain.Example;
    import org.springframework.data.repository.Repository;
    import org.springframework.http.HttpStatus;
    import org.springframework.http.ResponseEntity;
    import org.springframework.beans.factory.annotation.Autowired;
    

    Add the following import statements for Quarkus. (We're not using all of these imports in the .java files, but we can leave them for now.)

    /// --- Add the following import statements.
    
    import javax.ws.rs.Consumes;
    import javax.ws.rs.DELETE;
    import javax.ws.rs.GET;
    import javax.ws.rs.POST;
    import javax.ws.rs.PUT;
    import javax.ws.rs.Path;
    import javax.ws.rs.PathParam;
    import javax.ws.rs.Produces;
    import javax.ws.rs.core.Response;
    import javax.ws.rs.core.MediaType;
    import javax.inject.Inject;
    

    Remove the Spring Boot @RequestMapping and @RestController annotations:

    /// --- Remove the @RequestMapping and @RestController and
    update as follows
    
    // @RequestMapping("/ws/pg")      <--- Remove this
    // @RestController      <--- Remove this
    @Path("/ws/pg")         // <---- Add this
    @Produces(MediaType.APPLICATION_JSON)         // <---- Add this
    @Consumes(MediaType.APPLICATION_JSON)        // <---- Add this
    public class AccountBalance{
    /// --- I have omitted more code here
    ...
    

    You will also need to remove the @Autowire and @Inject annotations:

    /// --- Remove @Autowire with @Inject
    
    // @Autowired      <--- Remove this
    @Inject
    private BalanceRepository repository;
    

    Note that we changed the @RequestMapping annotation to @Path, and we also removed @ResponseBody. As our last step, we need to change the @PathVariable to @PathParam, as shown below. (While not shown, we would apply similar changes to all the other methods in this Java class. See the example application's source code to review all of the changes):

    @Path("/balance/{accountid}")
    @GET
    public Balance get(@PathParam("accountid") String accountId) {
       Balanceresult = repository.findByAccountId(accountId);
       return result;
    }
    

    That completes the migration, although I left out some steps to keep this exercise brief. As an example, the AccountBalance application is meant to be deployed onto Red Hat OpenShift, so I modified the Heathz.java file for that. You can view those changes in the application source.

    Step 3: Test the Quarkus application

    Next, we'll test our new application. Figure 1 shows the Spring Boot execution before migration.

    SpringBoot at command prompt
    SpringBoot at command prompt

    Figure 1. The Spring Boot app starts within 3.166 seconds.">

    Let's see how the Quarkus application's startup compares to Spring Boot. From the command prompt, switch over to the AccountBalance directory. Execute the following command to run the migrated application:

    mvn quarkus:dev
    

    Note that the first time you run the application, it can take longer than it will on subsequent runs. Maven needs additional time to download the Quarkus repositories to your local machine. Figure 2 shows the start time for the new Quarkus application.

    A screenshot of the Quarkus application's start time on first execution.
    Quarkus execution

    Figure 2. Quarkus starts within 1.540 seconds.">

    That's an improvement. Now let's do a Quarkus-native build. Remember to execute the native build from the project's root directory:

    /mvnw package -Pnative
    

    The output in Figure 3 indicates a successful Quarkus-native build.

    Quarkus native build completed sucessfully
    Quarkus native build completed sucessfully

    Figure 3. The Quarkus-native build completes successfully.">

    Enter the following to run the native binary:

    ./target/account-service-1.0.0-runner
    

    Figure 4 shows the execution time for the Quarkus-native build.

    A screenshot of the execution time for the Quarkus native build.
    Quarkus native execution

    Figure 4. The Quarkus-native build starts within 0.071 seconds.">

    Finally, I created a simple UI to call the AccountBalance service and display an account balance. As shown in Figure 5, the migrated application works as expected.

    An account balance is displayed in the AccountBalance app's UI.
    The account balance is shown on the UI apps

    Figure 5. The AccountBalance application works as it should.">

    The migration from Spring Boot to Quarkus was a success.

    Conclusion

    Migrating the example application from Spring Boot to Quarkus was a pretty straightforward exercise. For a more complicated application, the migration path would be more complex. The biggest challenge with migrating my microservices application from Spring Boot to Quarkus was determining which annotations and libraries to use. The documentation for Quarkus provides good examples but omits import statements. Many IDEs will handle those configuration details for you, but I chose to migrate manually.

    I hope this article serves as a starting point for migrating your Java applications from Spring Boot to Quarkus. If you want to take what you've learned to the next level, you could follow these steps to containerize your application.

    Resources

    Check out the following resources to learn more:

    • Find the complete source code for the example application on GitHub.
    • See the Quarkus Configuration Guide to learn how to configure your application using the Quarkus ConfigProperty, application.properties, and so on.
    • Learn more about the MongoDB Panache extension. Also, see the PanacheMongoRepositoryBase repository on GitHub—reading source code is what developers do right!
    • Get more information about building a native Quarkus executable.
    Last updated: May 30, 2023

    Recent Posts

    • A deep dive into Apache Kafka's KRaft protocol

    • Staying ahead of artificial intelligence threats

    • Strengthen privacy and security with encrypted DNS in RHEL

    • How to enable Ansible Lightspeed intelligent assistant

    • Why some agentic AI developers are moving code from Python to Rust

    Red Hat Developers logo LinkedIn YouTube Twitter Facebook

    Products

    • Red Hat Enterprise Linux
    • Red Hat OpenShift
    • Red Hat Ansible Automation Platform

    Build

    • Developer Sandbox
    • Developer Tools
    • Interactive Tutorials
    • API Catalog

    Quicklinks

    • Learning Resources
    • E-books
    • Cheat Sheets
    • Blog
    • Events
    • Newsletter

    Communicate

    • About us
    • Contact sales
    • Find a partner
    • Report a website issue
    • Site Status Dashboard
    • Report a security problem

    RED HAT DEVELOPER

    Build here. Go anywhere.

    We serve the builders. The problem solvers who create careers with code.

    Join us if you’re a developer, software engineer, web designer, front-end designer, UX designer, computer scientist, architect, tester, product manager, project manager or team lead.

    Sign me up

    Red Hat legal and privacy links

    • About Red Hat
    • Jobs
    • Events
    • Locations
    • Contact Red Hat
    • Red Hat Blog
    • Inclusion at Red Hat
    • Cool Stuff Store
    • Red Hat Summit
    © 2025 Red Hat

    Red Hat legal and privacy links

    • Privacy statement
    • Terms of use
    • All policies and guidelines
    • Digital accessibility

    Report a website issue