Skip to content

Commit 3689eda

Browse files
authored
Merge branch 'main' into spring-projects-experimentalgh-461
2 parents d6839b7 + cf6e286 commit 3689eda

File tree

7 files changed

+266
-7
lines changed

7 files changed

+266
-7
lines changed

README.adoc

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ ____
1717

1818
We are working on automated upgrade from Spring Boot 2.7 to Spring Boot 3.0.
1919

20-
If any of your applications is on 2.7 and uses Maven (Gradle is currently not supproted) we'd be happy if you
20+
If any of your applications is on 2.7 and uses Maven (Gradle is currently not supported), we'd be happy if you
2121
could give SBM a try and provide feedback of how it worked out.
2222
It is very hard to come up with all the possible setups found in the wild and therefor we need you - the community - to provide feedback to stabilize the recipe.
2323

components/sbm-core/src/main/java/org/springframework/sbm/java/impl/OpenRewriteType.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
import org.openrewrite.java.*;
1919
import org.openrewrite.java.format.WrappingAndBraces;
20+
import org.openrewrite.java.tree.*;
2021
import org.springframework.sbm.java.api.*;
2122
import org.springframework.sbm.java.migration.visitor.RemoveImplementsVisitor;
2223
import org.springframework.sbm.java.refactoring.JavaRefactoring;
@@ -26,20 +27,20 @@
2627
import org.openrewrite.ExecutionContext;
2728
import org.openrewrite.Recipe;
2829
import org.openrewrite.java.search.DeclaresMethod;
29-
import org.openrewrite.java.tree.J;
3030
import org.openrewrite.java.tree.J.ClassDeclaration;
31-
import org.openrewrite.java.tree.JavaType;
3231
import org.openrewrite.java.tree.JavaType.Class;
33-
import org.openrewrite.java.tree.TypeUtils;
3432
import org.springframework.sbm.support.openrewrite.GenericOpenRewriteRecipe;
3533
import org.springframework.sbm.support.openrewrite.java.AddAnnotationVisitor;
3634
import org.springframework.sbm.support.openrewrite.java.FindCompilationUnitContainingType;
3735
import org.springframework.sbm.support.openrewrite.java.RemoveAnnotationVisitor;
36+
import org.springframework.util.StringUtils;
3837

3938
import java.util.List;
4039
import java.util.Optional;
4140
import java.util.Set;
4241
import java.util.UUID;
42+
import java.util.function.BiFunction;
43+
import java.util.function.Function;
4344
import java.util.function.Supplier;
4445
import java.util.stream.Collectors;
4546
import java.util.stream.Stream;
@@ -351,4 +352,13 @@ public ClassDeclaration visitClassDeclaration(ClassDeclaration classDecl, Execut
351352
apply(new GenericOpenRewriteRecipe<JavaIsoVisitor<ExecutionContext>>(() -> javaIsoVisitor));
352353
}
353354

355+
public boolean isImplementing(String fqClassName){
356+
return getClassDeclaration()
357+
.getType()
358+
.getInterfaces()
359+
.stream()
360+
.map(JavaType.FullyQualified::getFullyQualifiedName)
361+
.anyMatch(fqClassName::equals);
362+
}
363+
354364
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.springframework.sbm.java.api.JavaSourceAndType;
20+
import org.springframework.sbm.java.impl.OpenRewriteJavaSource;
21+
import org.springframework.sbm.project.resource.ProjectResourceSet;
22+
import org.springframework.sbm.project.resource.filter.ProjectResourceFinder;
23+
import org.springframework.stereotype.Component;
24+
25+
import java.util.List;
26+
import java.util.stream.Collectors;
27+
28+
@Component
29+
public class ApacheSolrRepositoryBeanFinder implements ProjectResourceFinder<List<JavaSourceAndType>> {
30+
private static final String SOLR_REPOSITORY_CLASS = "org.springframework.data.solr.repository.SolrCrudRepository";
31+
32+
@Override
33+
public List<JavaSourceAndType> apply(ProjectResourceSet projectResourceSet) {
34+
return projectResourceSet.stream()
35+
.filter(OpenRewriteJavaSource.class::isInstance)
36+
.map(OpenRewriteJavaSource.class::cast)
37+
.filter(js -> js.getTypes().stream().anyMatch(o -> o.isImplementing(SOLR_REPOSITORY_CLASS)))
38+
.map(js -> js.getTypes().stream()
39+
.filter(o -> o.isImplementing(SOLR_REPOSITORY_CLASS))
40+
.findFirst()
41+
.map(o -> new JavaSourceAndType(js,o))
42+
.get()
43+
)
44+
.collect(Collectors.toList());
45+
}
46+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import lombok.RequiredArgsConstructor;
20+
import org.springframework.sbm.boot.asciidoctor.ChangeSection;
21+
import org.springframework.sbm.boot.asciidoctor.Section;
22+
import org.springframework.sbm.boot.asciidoctor.TodoList;
23+
import org.springframework.sbm.boot.upgrade_27_30.Sbu30_UpgradeSectionBuilder;
24+
import org.springframework.sbm.engine.context.ProjectContext;
25+
import org.springframework.sbm.java.api.JavaSourceAndType;
26+
import org.springframework.stereotype.Component;
27+
28+
import java.util.List;
29+
30+
@Component
31+
@RequiredArgsConstructor
32+
public class ApacheSolrRepositorySectionBuilder implements Sbu30_UpgradeSectionBuilder {
33+
34+
private final ApacheSolrRepositoryBeanFinder finder;
35+
36+
@Override
37+
public boolean isApplicable(ProjectContext projectContext) {
38+
return ! projectContext.search(finder).isEmpty();
39+
}
40+
41+
@Override
42+
public Section build(ProjectContext projectContext) {
43+
List<JavaSourceAndType> solrRepositories = projectContext.search(finder);
44+
45+
return ChangeSection.RelevantChangeSection.builder()
46+
.title("`Spring Data ApacheSolr` support has been removed")
47+
.paragraph("Support for `Spring Data ApacheSolr` has been removed in Spring Framework 6")
48+
.relevanceSection()
49+
.paragraph("The scan found bean declarations of type `SolrCrudRepository`.")
50+
.todoSection()
51+
.paragraph("Remove repositories of type `SolrCrudRepository`")
52+
.todoList(this.buildTodoList(solrRepositories))
53+
.build();
54+
}
55+
56+
private TodoList buildTodoList(List<JavaSourceAndType> solrRepositories) {
57+
TodoList.TodoListBuilder todoListBuilder = TodoList.builder();
58+
solrRepositories.forEach(m -> {
59+
todoListBuilder.todo(
60+
TodoList.Todo.builder()
61+
.text(String.format("Remove from class `%s`", m.getType().getFullyQualifiedName()))
62+
.build()
63+
);
64+
});
65+
return todoListBuilder.build();
66+
}
67+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
package org.springframework.sbm.boot.upgrade_27_30.checks;
2+
3+
4+
import org.intellij.lang.annotations.Language;
5+
import org.junit.jupiter.api.Test;
6+
import org.springframework.sbm.engine.context.ProjectContext;
7+
import org.springframework.sbm.java.api.JavaSourceAndType;
8+
import org.springframework.sbm.java.api.Type;
9+
import org.springframework.sbm.project.resource.TestProjectContext;
10+
11+
import java.util.List;
12+
13+
import static org.assertj.core.api.Assertions.assertThat;
14+
15+
public class ApacheSolrRepositoryBeanFinderTest {
16+
17+
@Language("java")
18+
private static String SOLR_REPO =
19+
"""
20+
package foo.bar;
21+
import org.springframework.data.solr.repository.SolrCrudRepository;
22+
public class ProductRepository implements SolrCrudRepository<Product, String> {}
23+
""";
24+
25+
@Language("java")
26+
private static String NO_SOLR_REPO =
27+
"""
28+
package foo.bar;
29+
public class ProductRepository {}
30+
""";
31+
32+
@Test
33+
public void givenModuleWithSolrRepository_find_expectNonEmptyList(){
34+
ProjectContext projectContext = TestProjectContext.buildProjectContext()
35+
.withJavaSources(SOLR_REPO)
36+
.withBuildFileHavingDependencies("org.springframework.data:spring-data-solr:4.3.15")
37+
.build();
38+
39+
ApacheSolrRepositoryBeanFinder solrRepositoryBeanFinder = new ApacheSolrRepositoryBeanFinder();
40+
List<JavaSourceAndType> solrRepositories = projectContext.search(solrRepositoryBeanFinder);
41+
assertThat(solrRepositories).isNotEmpty();
42+
Type type = solrRepositories.get(0).getType();
43+
assertThat(type.getFullyQualifiedName()).isEqualTo("foo.bar.ProductRepository");
44+
}
45+
46+
@Test
47+
public void givenModuleWithoutSolrRepository_find_expectNonEmptyList(){
48+
ProjectContext projectContext = TestProjectContext.buildProjectContext()
49+
.withJavaSources(NO_SOLR_REPO)
50+
.withBuildFileHavingDependencies("org.springframework.data:spring-data-solr:4.3.15")
51+
.build();
52+
53+
ApacheSolrRepositoryBeanFinder solrRepositoryBeanFinder = new ApacheSolrRepositoryBeanFinder();
54+
List<JavaSourceAndType> solrRepositories = projectContext.search(solrRepositoryBeanFinder);
55+
assertThat(solrRepositories).isEmpty();
56+
}
57+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/*
2+
* Copyright 2021 - 2022 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.sbm.boot.upgrade_27_30.checks;
18+
19+
import org.junit.jupiter.api.Test;
20+
import org.springframework.sbm.boot.asciidoctor.Section;
21+
import org.springframework.sbm.engine.context.ProjectContext;
22+
import org.springframework.sbm.java.api.JavaSource;
23+
import org.springframework.sbm.java.api.JavaSourceAndType;
24+
import org.springframework.sbm.java.api.Type;
25+
26+
import java.util.List;
27+
28+
import static org.assertj.core.api.Assertions.assertThat;
29+
import static org.mockito.Mockito.mock;
30+
import static org.mockito.Mockito.when;
31+
32+
class ApacheSolrRepositorySectionBuilderTest {
33+
34+
@Test
35+
void givenAContextWithSolrRepository_applySectionBuilder_validateReport() {
36+
ApacheSolrRepositoryBeanFinder finder = mock(ApacheSolrRepositoryBeanFinder.class);
37+
38+
Type type = mock(Type.class);
39+
Type type1 = mock(Type.class);
40+
JavaSource javaSource = mock(JavaSource.class);
41+
JavaSource javaSource1 = mock(JavaSource.class);
42+
JavaSourceAndType javaSourceAndType = new JavaSourceAndType(javaSource,type);
43+
JavaSourceAndType javaSourceAndType1 = new JavaSourceAndType(javaSource1,type1);
44+
45+
ProjectContext context = mock(ProjectContext.class);
46+
ApacheSolrRepositorySectionBuilder sut = new ApacheSolrRepositorySectionBuilder(finder);
47+
List<JavaSourceAndType> matches = List.of(
48+
javaSourceAndType,
49+
javaSourceAndType1
50+
);
51+
52+
when(context.search(finder)).thenReturn(matches);
53+
when(type.getFullyQualifiedName()).thenReturn("com.foo.bar.SomeClass");
54+
when(type1.getFullyQualifiedName()).thenReturn("com.foo.baz.AnotherClass");
55+
56+
Section section = sut.build(context);
57+
58+
String rendered = SectionRendererTestUtil.render(section);
59+
assertThat(rendered).isEqualTo(
60+
"""
61+
=== `Spring Data ApacheSolr` support has been removed
62+
Support for `Spring Data ApacheSolr` has been removed in Spring Framework 6
63+
64+
==== Relevance
65+
66+
The scan found bean declarations of type `SolrCrudRepository`.
67+
68+
==== Todo
69+
70+
Remove repositories of type `SolrCrudRepository`
71+
72+
73+
* [ ] Remove from class `com.foo.bar.SomeClass`
74+
* [ ] Remove from class `com.foo.baz.AnotherClass`
75+
"""
76+
);
77+
}
78+
79+
}

pom.xml

+3-3
Original file line numberDiff line numberDiff line change
@@ -30,13 +30,13 @@
3030
<maven.compiler.source>17</maven.compiler.source>
3131
<maven-compiler-plugin.version>3.10.1</maven-compiler-plugin.version>
3232
<java.version>17</java.version>
33-
<spring-shell.version>2.1.1</spring-shell.version>
33+
<spring-shell.version>2.1.2</spring-shell.version>
3434
<openrewrite.version>7.29.0</openrewrite.version>
3535
<openrewrite.spring.version>4.26.0</openrewrite.spring.version>
3636
<rewrite-migrate-java.version>1.11.0</rewrite-migrate-java.version>
3737
<spring-boot.version>2.7.4</spring-boot.version>
3838
<progressbar.version>0.9.4</progressbar.version>
39-
<testcontainers.version>1.17.4</testcontainers.version>
39+
<testcontainers.version>1.17.5</testcontainers.version>
4040
<maven-invoker.version>3.2.0</maven-invoker.version>
4141
<shrinkwrap.resolvers.version>3.1.4</shrinkwrap.resolvers.version>
4242
<lombok.version>1.18.24</lombok.version>
@@ -375,7 +375,7 @@
375375
<plugin>
376376
<groupId>io.spring.javaformat</groupId>
377377
<artifactId>spring-javaformat-maven-plugin</artifactId>
378-
<version>0.0.34</version>
378+
<version>0.0.35</version>
379379
</plugin>
380380

381381
<plugin>

0 commit comments

Comments
 (0)