In this Story, I will show you what I have done for migrating the Spring Boot from 2.7.6 to 3.0 in my Event Sourcing P.O.C Repository.
(see also how to implement observability for spring boot 3)
For a brief introduction, my project is
- A multi-module Gradle Project (gradle-wrapper 7.2)
- Using Java 17
- A server Application integrates with Kafka
- Using H2 as an in-memory DB
the following is my original build.gradle file
plugins {
id 'org.springframework.boot' version '2.7.6' apply false
id 'io.spring.dependency-management' version '1.1.0'
id 'java'
}
subprojects {
group = 'org.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '17'
apply plugin: 'java'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'java-library'
repositories {
mavenCentral()
}
dependencyManagement {
imports {
mavenBom(SpringBootPlugin.BOM_COORDINATES)
}
}
dependencies {
implementation 'org.springdoc:springdoc-openapi-ui:1.6.13'
testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1'
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
runtimeOnly 'com.h2database:h2'
compileOnly 'org.projectlombok:lombok:1.18.20'
annotationProcessor 'org.projectlombok:lombok:1.18.20'
}
test {
useJUnitPlatform()
}
}
Migration step
1. update the gradle wrapper version
First, when I modify the ‘org.springframework.boot’ version to 3.0.0, and try to reload the project in my IDE(Intellij), I encounter the first problem:
- Root cause: PermittedSubclasses requires ASM9
org.gradle.api.ProjectConfigurationException: A problem occurred configuring root project 'event-sourcing-order-poc'.
Caused by: org.gradle.internal.UncheckedException: java.util.concurrent.ExecutionException: org.gradle.api.GradleException: Failed to create Jar file /Users/myname/.gradle/caches/jars-9/4d6cded054513435538f8c1f816f4acb/spring-core-6.0.2.jar.
...
Caused by: java.util.concurrent.ExecutionException: org.gradle.api.GradleException: Failed to create Jar file /Users/myname/.gradle/caches/jars-9/4d6cded054513435538f8c1f816f4acb/spring-core-6.0.2.jar.
... 156 more
Caused by: org.gradle.api.GradleException: Failed to create Jar file /Users/myname/.gradle/caches/jars-9/4d6cded054513435538f8c1f816f4acb/spring-core-6.0.2.jar.
... 3 more
Caused by: java.lang.UnsupportedOperationException: PermittedSubclasses requires ASM9
There is no useful information when just google with the “PermittedSubclasses requires ASM9”. But we can see that the problem is absolutely related to the Gradle. so I try to update the gradle wrapper version in my project( from 7.2 to 7.6). And it turns out to solve this issue.
2. replace the import package from “javax” to “jakarta”
This change is noted in the document in the [Official Migration Guide](https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide), so it is not a big problem.
But after replacing the package name, I encounter a warning message when trying to run the application:
jakarta.validation.NoProviderFoundException:
Unable to create a Configuration, because no Jakarta Bean Validation provider could be found.
Add a provider like Hibernate Validator (RI) to your classpath.
So we add the following dependency to the project and solve the issue.[(ref StackOverflow)](https://stackoverflow.com/questions/36329001/unable-to-create-a-configuration-because-no-bean-validation-provider-could-be-f)
implementation 'org.springframework.boot:spring-boot-starter-validation'
3. change the deprecated Method in CompletableFuture
There is a deprecated method called, “addCallback()” in the following Kafka event producer class. the method is officially removed after this change. so I have to find another way to implement the logic.
return kafkaTemplate.executeInTransaction(operations -> {
final String key = order.id();
operations
.send(ORDER_TOPIC, key, order)
.addCallback(this::onSuccess, this::onFailure);
return true;
});
...
private void onSuccess(final SendResult<String, OrderEvent> result) {...}
private void onFailure(final Throwable t) {
log.warn("Unable to write Order to topic {}.", ORDER_TOPIC, t);
}
Here, I replaced it with two functions, “thenAccept” and “exceptionally” to make the same logic. then modify the return type of “onFailure()” method:
return kafkaTemplate.executeInTransaction(operations -> {
final String key = order.id();
operations
.send(ORDER_TOPIC, key, order)
.thenAccept(this::onSuccess)
.exceptionally(this::onFailure);
return true;
});
...
private void onSuccess(final SendResult<String, OrderEvent> result) {...}
private Void onFailure(final Throwable t) {
log.warn("Unable to write Order to topic {}.", ORDER_TOPIC, t);
return null;
}
4. Use new dependency for swagger UI
Finally, I can build and run my project, but the server returns a not-found for the swagger UI URL. I go to the official website of the springdoc and found that it says:
so I change the dependency from
dependencies {
implementation 'org.springdoc:springdoc-openapi-ui:1.6.13'
}
to
dependencies {
implementation 'org.springdoc:springdoc-openapi-starter-webmvc-ui:2.0.0'
}
then the swagger UI is working fine again.
Summary
Here we just have done the very first step, migrating my project to using the 3.0.0 version. looking forward to integrating all the exciting features into my project next time. if you want to see the code change in detail, you can refer to this Pull Request in my P.O.C GitHub repository: https://github.com/NoahHsu/event-sourcing-order-poc/pull/16.
If you found this article valuable, please consider supporting my work by buying me a beer 🍺. Your generosity fuels my passion for creating more Spring boot content. Don’t forget to share and clap for this article, and follow me on Medium for future tech stories. Thanks for your support and happy reading!
Reference
- release note: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes
- migration guide: https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Migration-Guide
- springdoc official doc: https://springdoc.org/v2/
- StackOverflow about jakarta.validation: https://stackoverflow.com/questions/36329001/unable-to-create-a-configuration-because-no-bean-validation-provider-could-be-f