Recipes to upgrade to Spring Boot 3.4
We want to support folks looking to migrate to Spring Boot 3.4
- https://spring.io/blog/2024/11/21/spring-boot-3-4-0-available-now
- https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.4-Release-Notes
Here's an incomplete list of tasks related to this migration
- [ ] https://github.com/openrewrite/rewrite-spring/issues/627
- [ ] Generate Spring Boot property migration recipes (runs on a schedule)
- [ ] WebJars Locator Integration: instead of
org.webjars:webjars-locator-coredepend onorg.webjars:webjars-locator-lite - [x] OkHttp Dependency Management Removed
- verify change parent already adds the explicit version where that was managed before
- [ ] Netty in Native Image: upgrade the GraalVM reachability metadata version
- [x] https://github.com/openrewrite/rewrite-spring/pull/646
- [ ] Deprecations in
RestTemplateBuilder- requestFactory -> requestFactoryBuilder
- setConnectTimeout ->connectTimeout
- setReadTimeout -> readTimeout
- setSslBundle -> sslBundle
- [ ] Bean configuration properties need to be marked with
@Validwhere previously only@Validatedwas required see
I created a recipe for the last point (replacing @MockBean and @SpyBean) which I can contribute. 😃 Probably needs some cleanup though since this is my first recipe. I'll try to create a pr for it tomorrow after work.
I also found one more point for the list. The RestTemplateBuilder has several deprecations with Spring Boot 3.4
https://docs.spring.io/spring-boot/api/java/org/springframework/boot/web/client/RestTemplateBuilder.html
requestFactory -> requestFactoryBuilder setConnectTimeout ->connectTimeout setReadTimeout -> readTimeout setSslBundle -> sslBundle
@timtebeek Can you add that as one TODO item on the list so it isn't forgotten? 😃
I'm thinking about trying to tackle the migration for RestTemplateBuilder.
Seems mostly straightforward apart from one method.
requestFactory -> requestFactoryBuilder
This would require code like this:
class BuilderClass {
void buildermethod() {
RestTemplateBuilder builder = new RestTemplateBuilder();
builder.requestFactory(requestFactory).build();
}
}
to look like this after the migration:
import org.springframework.boot.http.client.ClientHttpRequestFactoryBuilder;
class BuilderClass {
void buildermethod() {
RestTemplateBuilder builder = new RestTemplateBuilder();
builder.requestFactory(ClientHttpRequestFactoryBuilder.of(requestFactory)).build();
}
}
Is something like that possible with yaml recipes?
I'm also struggeling a bit to get the test cases to run for this because the method parameter of setConnectTimeout is java.time.Duration
I get:
LST contains missing or invalid type information Identifier->MethodInvocation->MethodInvocation->Block->MethodDeclaration->Block->ClassDeclaration->CompilationUnit /~~(Identifier type is missing or malformed)~~>/Duration
I know that I need to add it to the classpath somehow, but how do i do that for java internal classes like Duration? Currently my method for loading the recipe looks like this:
@Override
public void defaults(RecipeSpec spec) {
spec.recipeFromResources("org.openrewrite.java.boot3.resttemplatebuilder")
.parser(JavaParser.fromJavaVersion()
.classpathFromResources(new InMemoryExecutionContext(),
"spring-boot"));
}
Thanks for the continued work here @123Haynes ! For the requestFactory change I think a Refaster style recipe would be most appropriate, which will require the 3.4 on the classpath. similarly for the setConnectTimeout change I think the missing types are due to having 3.3 on the classpath still. We'll need to work out if the existing recipes can coexist, but I don't expect any issues just yet.
Alright. I'll take a look at how refaster recipes work then. 😃
I don't think the missing types are related to 3.3 still on the classpath. The issue is that the method parameter of setConnectTimeout is java.time.Duration which is not recognized. But this is part of the jdk so spring dependencies should not matter at all.
The test works fine if I just use something like 10 as the method argument instead of Duration.ofSeconds(10)
The method gets renamed just fine then, but technically the test would not represent the exact code.
Please note: The MockBean replacment recipe (#646) won't work correctly in all cases, as the new annotation is no full drop-in replacement (see https://github.com/spring-projects/spring-framework/issues/33934). E.g. on types or in TestConfiguration classes, the new annotation has no effect (or even cannot be used). The workarounds are not trivial...
Also, please check if https://github.com/GoogleCloudPlatform/spring-cloud-gcp/issues/3391 has to be considered. sm:// references in Spring properties (for Google Secret Manager) no longer work and have to be escaped in an ugly way.
Please note: The MockBean replacment recipe (#646) won't work correctly in all cases, as the new annotation is no full drop-in replacement (see spring-projects/spring-framework#33934). E.g. on types or in TestConfiguration classes, the new annotation has no effect (or even cannot be used). The workarounds are not trivial...
Thanks for the comment. I was not aware of that since i don't use @MockBean like that in my projects.
Given this reply https://github.com/spring-projects/spring-framework/issues/33934#issuecomment-2512136161 and that there is currently no clear upgrade path povided by the spring team for some specific use cases I wonder if we should just ignore this for the spring boot 3.4 recipe and take a look again later. The annotations will be around until spring boot 3.6.
Alternatively we could change the recipe so it only replaces the annotation for known, working usecases and ignores everything in @Configuration classes for example. But I don't think having a mix of @MockBean and @MockitoBean would be something that people want.
I'd probably still keep the current recipe in since even in it's current form the recipe can be used by many people and we can iterate on it.
For MockitoBean support at the type level, this thread is the "live" one: https://github.com/spring-projects/spring-framework/issues/33925
Looking at the broader list of open tasks, I think a recipe to transform type-level usage of MockBean to a field level MockitoBean pattern would be a low priority, unless some contributor has a specific pressing use case for it
Alternatively we could change the recipe so it only replaces the annotation for known, working usecases and ignores everything in
@Configurationclasses for example. But I don't think having a mix of@MockBeanand@MockitoBeanwould be something that people want.
TBH, that is exactly what I now have done in our project, but I was not quite happy about it. Maybe it is really the best to not to do that replacement at all, but that also could cause deprecation warnings (or even errors, depending on compiler settings) for many...
Keeping the old annotation would also "solve" the lacking support for the type-level usage of the new annotation.
TBH, that is exactly what I now have done in our project, but I was not quite happy about it. Maybe it is really the best to not to do that replacement at all, but that also could cause deprecation warnings (or even errors, depending on compiler settings) for many...
For the warnings the spring boot team provided a workaround to silence those: https://github.com/spring-projects/spring-framework/issues/33934#issuecomment-2514372031 But I don't think this should be included in a recipe because it just hides the warning and people wouldn't know they still have something to do.
Hi guys, It's almost 1 month that SpringBoot3.4 is released and we know that we have very limited contributor with there great effots, But still any tentative timeline to release 3.4 final recipe so base on that we can plan the work of upgrade to 3.4. Thanks.
Hi @A1016375 ; There is no set timeline; any help developing these recipes is welcome!
Netty in Native Image: upgrade the GraalVM reachability metadata version
About this one, according to the release notes it seems sufficient to upgrade to a version greater than 3.4.0
For
MockitoBeansupport at the type level, this thread is the "live" one: spring-projects/spring-framework#33925
That has now been addressed in Spring Framework 6.2.2 which got released today.
@MockitoBean may now be declared on test classes and reusable composed annotations. See the updated documentation for details.
Hi, Are there any plans to make the UpgradeSpringBoot_3_4 recipe available for execution with Maven command line? Thanks.
Seems moderne has created their take on a recipe for this this , I wonder if that makes this issue dead, it certainly seems to be stale?
hi! It's true that at Moderne we've developed recipes for ourselves and our customers to migrate to Spring Boot 3.4. We've chosen to keep these proprietary in response to seeing hyper scalers take our collective efforts and offering those as a paid service. By keeping these closed source, for now, we can differentiate our offerings for the long term viability of both OpenRewrite and Moderne.
We're still more than happy to work with the community to bring recipes to all open source users though; We've had some good and much appreciated efforts from @123Haynes early on above, but have so far not seen any contributions to tie this together into the usual declarative migration recipes as seen in src/main/resources/META-INF/rewrite.
We've understandably seen a lot of interest into recipes to upgrade to Spring Boot 3.4, and soon 3.5, but as openrewrite/rewrite-spring is now mostly community driven we're asking for help to make these a reality, and will happily review, merge & release contributions, and maintain these going forward.
When you say: in response to seeing hyper scalers take our collective efforts and offering those as a paid service
you talk about things like this ?
https://techdocs.broadcom.com/us/en/vmware-tanzu/spring/tanzu-spring/commercial/spring-tanzu/index-app-advisor.html
@timtebeek first, thanks for your support in this initiative. I would like to ask also if there is a fork and/or branch with the initial work mentioned above, provided by the community, to develop this OSS 3.4 upgrade recipe? Just wondering if we have had so far 0 code contributions or not (so anyone knows where to start from when contributing). Thanks.
The initial work above has all gone into the main branch of this project: https://github.com/openrewrite/rewrite-spring/tree/main We'll continue to review and merge any contributions we get; and would be happy to do so. If you take the 3.3 recipes as an example, it should be easy to create and contribute a similar structure for 3.4. Then we can fill in the gaps as reported here. Any help appreciated!
Here's yet another PR from @wapkch that helpfully adds a migration from Spring Framework 6.2
- https://github.com/openrewrite/rewrite-spring/pull/693
- https://github.com/openrewrite/rewrite-spring/issues/627
- https://github.com/openrewrite/rewrite-spring/commit/adbe569d2f4ed64ca7271f59dabf0f0be63b0daf
We'll continue to expand these recipes as contributions come in.