Last week, I migrated a sample Spring application to Micronaut. This week, I did the same for Quarkus.
Common changes
Spring Boot and Micronaut both offer a parent POM. Quarkus favors using a BOM.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.5.RELEASE</version>
<relativePath/>
</parent>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-bom</artifactId>
<version>1.9.2.Final</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Migrating the application
Quarkus provides dependencies that have the same interfaces and annotations as Spring. They map one to one. The next step is just a matter of replacing Spring's dependencies with Quarkus'.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-spring-web</artifactId>
</dependency>
To launch the application requires just a single main()
function, just as Micronaut:
@SpringBootApplication
class SpringToMicronautApplication
fun main(args: Array<String>) {
runApplication<SpringToMicronautApplication>(*args)
}
fun main(args: Array<String>) {
Quarkus.run(*args)
}
There's a glitch on the controller side. Quarkus doesn't read the @PathVariable
variable name from the bytecode. The name needs to be explicitly set in the annotation:
fun getOne(@PathVariable("id") id: Long): Optional<Person> = repo.findById(id)
The beauty of Quarkus is that no further steps are required!
More migration steps on the data layer
Though the database driver is on the classpath, it's necessary to configure the database:
quarkus.datasource.db-kind=h2
quarkus.datasource.jdbc.driver=org.h2.Driver
quarkus.datasource.jdbc.url=jdbc:h2:mem:test
Just as for Micronaut, Quarkus allow neither to create the schema nor to initialize the data, but has a Flyway integration:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
Moreover, you need to set the quarkus.flyway.migrate-at-start
property:
quarkus.flyway.migrate-at-start=true
Migrating the actuator
There's no actuator per se in the Quarkus universe. But it provides integration with SmallRye, which is an implementation of MicroProfile "(but not limited to) for the Cloud". Smallrye also provides a /health
endpoint. It just requires to add a dependency:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-smallrye-health</artifactId>
</dependency>
By default, the endpoint is available at the root. To mirror Spring's URL is a configuration knob away:
quarkus.smallrye-health.root-path=/actuator/health
In Spring applications, the /beans
endpoint queries the Spring context and return the list of beans it contains. I found no counterpart in Smallrye nor Microprofile. Of course, a CDI bean and a Spring Boot bean are different. Let's return the list of CDI beans.
In CDI, the BeanManager
is the object that's able to do that. The endpoint is a simple controller.
@RestController
class BeanController(private val manager: BeanManager) { // 1
@GetMapping(path = ["/actuator/beans"]) // 2
fun getAll(): Iterable<Bean<*>> = manager.getBeans(Any::class.java) // 3
}
- Inject the
BeanManager
- Configure the endpoint URL
- List the beans and return them
Conclusion
Within the scope of this sample application, migrating from Spring Boot to Quarkus is straightforward. The API dependencies play a big role in that. Except for explicitly setting the parameter name, it's seamless.
I was a bit surprised there's no AOT compilation as with Micronaut. I assume GraalVM native image creation leverages some mechanism to make reflection explicit.
The real gap lies in the actuator but it's possible to implement missing endpoints manually.
The complete source code for this post can be found on Github.
To go further:
- Quarkus website
- Quarkus Spring
- Quarkus Smallrye
- Quarkus Flyway
- Spring2quarkus — Spring Boot to Quarkus Migration
Originally published at A Java Geek on November 15th 2020