-
Notifications
You must be signed in to change notification settings - Fork 87
guide migration spring quarkus
This guide will cover the migration process of a Spring application to a Quarkus application. There are already articles about migrating from Spring to Quarkus (e.g. https://developers.redhat.com/blog/2020/04/10/migrating-a-spring-boot-microservices-application-to-quarkus, https://dzone.com/articles/migrating-a-spring-boot-application-to-quarkus-cha). This guide will focus more on the devon4j specific aspects. We assume that a working Spring application exists, built in the classic devon4j specific way (e.g. Jump The Queue or My Thai Star).
We start with an empty Quarkus project. You can create the project with Maven on the command line or use the online generator. The advantage of the online generator is that you have a pre-selection of dependencies to use in your project. For starters, let’s select the basic dependencies required to develop a REST service with database connectivity (you can use one of the links in the Quarkus template guide): RESTEasy JAX-RS, RESTEasy Jackson, Hibernate ORM, Spring Data JPA API, JDBC Driver (choose the type of database you need), Flyway (if you have database migration schemas), SmallRye Health (optional for Health Monitoring)
The list does not include all required dependencies. We will add more dependencies to the project later. For now, generate the application with these dependencies.
Red Hat provides a migration toolkit (MTA, Migration Toolkit for Applications), that supports migration of a Spring to a Quarkus application. There are several versions of this toolkit (e.g., a web console, a Maven plugin, or an IDE plugin). The MTA analyzes your existing application and generates a report with hints and instructions for migrating from Spring to Quarkus. For example, it gives you an indication of which dependencies are not supported in your project for a Quarkus application and which dependencies you need to swap them with. The analysis is rule-based, and you can also add your own rules that will be checked during analysis.
There is nothing special to consider when creating the entities. In most cases, you can simply take the code from your Spring application and use it for your Quarkus application. Usually, the entities extend a superclass ApplicationPersistenceEntity
containing, for example, the id
property. You can also take this class from your Spring application and reuse it.
The next step is to create the appropriate transfer objects for the entities. In a devon4j Spring application, we would use CobiGen to create these classes. Since CobiGen is not usable for this purpose in Quarkus applications yet, we have to create the classes manually.
First, we create some abstract base classes for the search criteria and DTO classes. Normally, these would also be created by CobiGen.
public abstract class AbstractSearchCriteriaTo extends AbstractTo {
private static final long serialVersionUID = 1L;
private Pageable pageable;
//getter + setter for pageable
}
public abstract class AbstractDto extends AbstractTo {
private static final long serialVersionUID = 1L;
private Long id;
private int modificationCounter;
public AbstractDto() {
super();
}
//getter + setter
@Override
protected void toString(StringBuilder buffer) {
...
}
}
The class AbstractTo
, extended by other classes, would be provided by the devon4j-basic
module in a devon4j Spring application. You can take the code from here and reuse it in your Quarkus project.
Now you can create your transfer objects. Most of the code of the transfer objects of your Spring application should be reusable. For Quarkus, we recommend (as mentioned here) to use *Dto
instead of *Eto
classes. Be sure to change the names of the classes accordingly.
In devon4j, we propose to use Spring Data JPA to build the data access layer using repositories and Querydsl to build dynamic queries. We will also use this approach for Quarkus applications, but we need to change the implementation because the devon4j modules are based on reflection, which is not suitable for Quarkus. In Quarkus we will use Querydsl using code generation. So for this layer, more changes are required and we can’t just take the existing code.
First, create a repository interface for your entity class that extends JpaRepository
(see here).
To add QueryDSL support to your project, add the following dependencies to your pom.xml file:
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-jpa</artifactId>
<version>4.3.1</version>
</dependency>
<dependency>
<groupId>com.querydsl</groupId>
<artifactId>querydsl-apt</artifactId>
<scope>provided</scope>
<version>4.3.1</version>
</dependency>
As mentioned above, we will use QueryDSL with code generation. For this, add the QueryDSL annotation processor to your plugins:
<plugins>
...
<plugin>
<groupId>com.mysema.maven</groupId>
<artifactId>apt-maven-plugin</artifactId>
<version>1.1.3</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>process</goal>
</goals>
<configuration>
<outputDirectory>target/generated-sources/annotations</outputDirectory>
<processor>com.querydsl.apt.jpa.JPAAnnotationProcessor</processor>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
To implement the queries, follow the corresponding guide.
Set the following properties in the application.properties file to configure the connection to your database (see also here):
quarkus.datasource.db-kind=...
quarkus.datasource.jdbc.url=...
quarkus.datasource.username=...
quarkus.datasource.password=...
For the logic layer, devon4j uses a use-case approach. You can reuse the use case interfaces from the api module of the Spring application. Again, make sure to rename the transfer objects.
Create the appropriate class that implements the interface. Follow the implementation section of the use-case guide to implement the methods. For mapping the entities to the corresponding transfer objects, see the next section.
For bean mapping, we need to use a completely different approach in the Quarkus application than in the Spring application. For Quarkus, we use MapStruct, which creates the mapper at build time rather than at runtime using reflection. Add the following dependencies to your pom.xml.
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct-processor</artifactId>
<version>1.4.2.Final</version>
</dependency>
<dependency>
<groupId>org.mapstruct</groupId>
<artifactId>mapstruct</artifactId>
<version>1.4.2.Final</version>
</dependency>
Then you can create the mapper as follows:
@Mapper(componentModel = "cdi")
public interface YourEntityMapper {
YourEntityDto map(YourEntity entity);
YourEntity map(YourEntityDto dto);
...
}
Inject the mapper into your use-case implementation and simply use the methods. The method implementations of the mapper are created when the application is built.
For the implementation of the service layer, we use the JAX-RS for both Quarkus and Spring applications to create the REST services. Classic devon4j Spring applications rely on Apache CFX as the implemention of JAX-RS. For Quarkus, we use RESTEasy. Since both are implementations of JAX-RS, much of the Spring application code can be reused.
Take the definition of the REST endpoints from the api module of the Spring application (make sure to rename the transfer objects), inject the use-cases from the logic layer and use them in the REST service methods as follows:
@Path("/path/v1")
public class YourComponentRestService {
@Inject
UcFindYourEntity ucFindYourEntity;
@Inject
UcManageYourEntity ucManageYourEntity;
@GET
@Path("/yourEntity/{id}/")
public YourEntityDto getYourEntity(@PathParam("id") long id);
return this.ucFindYourEntity.findYourEntity(id);
}
...
}
As you have seen, some parts hardly differ when migrating a Spring application to a Quarkus application, while other parts differ more. The above sections describe the parts needed for simple applications that provide REST services with a data access layer. If you add more functionality, more customization and other frameworks, dependencies may be required. If that is the case, take a look at the corresponding guide on the topic in the devon4j documentation or check if there is a tutorial on the official Quarkus website.
Furthermore, we can summarize that migrating from a Spring application to a Quarkus representative is not complex. Although Quarkus is a very young framework (release 1.0 was in 2019), it brings a lot of proven standards and libraries that you can integrate into your application. This makes it easy to migrate and reuse code from existing (Spring) applications. Also, Quarkus comes with Spring API compatibility for many Spring modules (Spring Data JPA, Spring DI, etc.), which makes it easier for developers to reuse their knowledge.
This documentation is licensed under the Creative Commons License (Attribution-NoDerivatives 4.0 International).