diff --git a/src/main/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullable.java b/src/main/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullable.java new file mode 100644 index 0000000000..a1f2992585 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullable.java @@ -0,0 +1,60 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaVisitor; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.Space; +import org.openrewrite.marker.Markers; +import org.openrewrite.staticanalysis.RemoveUnusedLocalVariables; +import org.openrewrite.staticanalysis.SimplifyConstantIfBranchExecution; + +import static org.openrewrite.Tree.randomId; + +public class RemoveBeanIsNullable extends Recipe { + @Override + public String getDisplayName() { + return "Remove `Bean.isNullable()`"; + } + + @Override + public String getDescription() { + return "`Bean.isNullable()` has been removed in CDI 4.0.0, and now always returns `false`."; + } + + private static final MethodMatcher BEAN_ISNULLABLE = new MethodMatcher("jakarta.enterprise.inject.spi.Bean isNullable()", false); + + @Override + public TreeVisitor getVisitor() { + return new JavaVisitor() { + @Override + public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + if (BEAN_ISNULLABLE.matches(method)) { + // clean up leftover conditions and remove unused variables + doAfterVisit(new SimplifyConstantIfBranchExecution().getVisitor()); + doAfterVisit(new RemoveUnusedLocalVariables(null).getVisitor()); + return new J.Literal(randomId(), Space.SINGLE_SPACE, Markers.EMPTY, Boolean.FALSE, "false", null, JavaType.Primitive.Boolean); + } + return super.visitMethodInvocation(method, ctx); + } + }; + } +} \ No newline at end of file diff --git a/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypes.java b/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypes.java new file mode 100644 index 0000000000..b70b4a0e7b --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypes.java @@ -0,0 +1,56 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.J; + +public class UpdateAddAnnotatedTypes extends Recipe { + @Override + public String getDisplayName() { + return "Replace `BeforeBeanDiscovery.addAnnotatedType(AnnotatedType)` with `addAnnotatedType(AnnotatedType, String)`"; + } + + @Override + public String getDescription() { + return "`BeforeBeanDiscovery.addAnnotatedType(AnnotatedType)` is deprecated in CDI 1.1. It is Replaced by `BeforeBeanDiscovery.addAnnotatedType(AnnotatedType, String)`."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaIsoVisitor() { + private final MethodMatcher methodInputPattern = new MethodMatcher( + "*.enterprise.inject.spi.BeforeBeanDiscovery addAnnotatedType(*.enterprise.inject.spi.AnnotatedType)", false); + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + if (methodInputPattern.matches(method)) { + return JavaTemplate.builder("#{any(jakarta.enterprise.inject.spi.AnnotatedType)}, null\"") + .build() + .apply(updateCursor(method), + method.getCoordinates().replaceArguments(), + method.getArguments().get(0)); + } + return super.visitMethodInvocation(method, ctx); + } + }; + } +} diff --git a/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethods.java b/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethods.java new file mode 100644 index 0000000000..80fe9364d6 --- /dev/null +++ b/src/main/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethods.java @@ -0,0 +1,68 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.JavaParser; +import org.openrewrite.java.JavaTemplate; +import org.openrewrite.java.MethodMatcher; +import org.openrewrite.java.tree.J; + +public class UpdateBeanManagerMethods extends Recipe { + @Override + public String getDisplayName() { + return "Update `fireEvent()` and `createInjectionTarget()` calls"; + } + + @Override + public String getDescription() { + return " Updates `BeanManager.fireEvent()` or `BeanManager.createInjectionTarget()`."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaIsoVisitor() { + private final MethodMatcher fireEventMatcher = new MethodMatcher("*.enterprise.inject.spi.BeanManager fireEvent(..)", false); + private final MethodMatcher createInjectionTargetMatcher = new MethodMatcher("*.enterprise.inject.spi.BeanManager createInjectionTarget(..)", false); + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ec) { + J.MethodInvocation mi = super.visitMethodInvocation(method, ec); + if (fireEventMatcher.matches(method)) { + return JavaTemplate.builder("#{any(jakarta.enterprise.inject.spi.BeanManager)}.getEvent().fire(#{any(jakarta.enterprise.inject.spi.BeforeBeanDiscovery)})") + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ec, "jakarta.enterprise.cdi-api-3.0.0-M4")) + .build() + .apply(updateCursor(mi), + mi.getCoordinates().replace(), + mi.getSelect(), + mi.getArguments().get(0)); + } else if (createInjectionTargetMatcher.matches(method)) { + return JavaTemplate.builder("#{any(jakarta.enterprise.inject.spi.BeanManager)}.getInjectionTargetFactory(#{any(jakarta.enterprise.inject.spi.AnnotatedType)}).createInjectionTarget(null)") + .javaParser(JavaParser.fromJavaVersion().classpathFromResources(ec, "jakarta.enterprise.cdi-api-3.0.0-M4")) + .build() + .apply(updateCursor(mi), + mi.getCoordinates().replace(), + mi.getSelect(), + mi.getArguments().get(0)); + } + return mi; + } + }; + } +} diff --git a/src/main/resources/META-INF/rewrite/classpath/jakarta.enterprise.cdi-api-3.0.0-M4.jar b/src/main/resources/META-INF/rewrite/classpath/jakarta.enterprise.cdi-api-3.0.0-M4.jar new file mode 100644 index 0000000000..3952d8da8d Binary files /dev/null and b/src/main/resources/META-INF/rewrite/classpath/jakarta.enterprise.cdi-api-3.0.0-M4.jar differ diff --git a/src/main/resources/META-INF/rewrite/jakarta-ee-10.yml b/src/main/resources/META-INF/rewrite/jakarta-ee-10.yml index f369b42bde..e30dfd4f01 100644 --- a/src/main/resources/META-INF/rewrite/jakarta-ee-10.yml +++ b/src/main/resources/META-INF/rewrite/jakarta-ee-10.yml @@ -27,6 +27,7 @@ recipeList: - org.openrewrite.java.migrate.jakarta.RemovedSOAPElementFactory - org.openrewrite.java.migrate.jakarta.WsWsocServerContainerDeprecation - org.openrewrite.java.migrate.jakarta.ServletCookieBehaviorChangeRFC6265 + - org.openrewrite.java.migrate.jakarta.DeprecatedCDIAPIsRemoved40 - org.openrewrite.java.migrate.BeanDiscovery - org.openrewrite.java.migrate.jakarta.BeanValidationMessages - org.openrewrite.java.migrate.jakarta.JavaxBeansXmlToJakartaBeansXml @@ -126,6 +127,16 @@ recipeList: newValue: https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/beans_4_0.xsd --- type: specs.openrewrite.org/v1beta/recipe +name: org.openrewrite.java.migrate.jakarta.DeprecatedCDIAPIsRemoved40 +displayName: Remove deprecated API's not supported in CDI4.0 +description: > + Deprecated APIs have been removed in CDI 4.0. This recipe removes and updates the corresponding deprecated methods. +recipeList: + - org.openrewrite.java.migrate.jakarta.RemoveBeanIsNullable + - org.openrewrite.java.migrate.jakarta.UpdateAddAnnotatedTypes + - org.openrewrite.java.migrate.jakarta.UpdateBeanManagerMethods +--- +type: specs.openrewrite.org/v1beta/recipe name: org.openrewrite.java.migrate.jakarta.JavaxToJakartaCdiExtensions displayName: Rename CDI Extension to Jakarta description: Rename `javax.enterprise.inject.spi.Extension` to `jakarta.enterprise.inject.spi.Extension`. @@ -133,3 +144,4 @@ recipeList: - org.openrewrite.RenameFile: fileMatcher: '**/javax.enterprise.inject.spi.Extension' fileName: jakarta.enterprise.inject.spi.Extension + diff --git a/src/test/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullableTest.java b/src/test/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullableTest.java new file mode 100644 index 0000000000..f66c7cd530 --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/jakarta/RemoveBeanIsNullableTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2023 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class RemoveBeanIsNullableTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new RemoveBeanIsNullable()) + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "jakarta.enterprise.cdi-api-3.0.0-M4")); + } + + @Test + @DocumentExample + void removeBeanIsNullable() { + rewriteRun( + //language=java + java( + """ + import jakarta.enterprise.inject.spi.Bean; + + class Test { + void test(Bean bean) { + if (bean.isNullable()) { + System.out.println("is null"); + } else { + System.out.println("not null"); + } + } + } + """, + """ + import jakarta.enterprise.inject.spi.Bean; + + class Test { + void test(Bean bean) { + System.out.println("not null"); + } + } + """ + ) + ); + } +} \ No newline at end of file diff --git a/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypesTest.java b/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypesTest.java new file mode 100644 index 0000000000..e2b438c200 --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateAddAnnotatedTypesTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.junit.jupiter.api.Test; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class UpdateAddAnnotatedTypesTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "jakarta.enterprise.cdi-api-3.0.0-M4", "jakarta.enterprise.cdi-api-4.0.1")) + .recipe(new UpdateAddAnnotatedTypes()); + } + + @Test + void addAnnotatedType() { + rewriteRun( + //language=java + java( + """ + import jakarta.enterprise.inject.spi.AnnotatedType; + import jakarta.enterprise.inject.spi.BeanManager; + import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; + + class Foo { + void bar(BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) { + AnnotatedType producerType = beanManager.createAnnotatedType(String.class); + beforeBeanDiscovery.addAnnotatedType(producerType); // Flag this one + beforeBeanDiscovery.addAnnotatedType(producerType, "my unique id"); // Not this one + beforeBeanDiscovery.addAnnotatedType(String.class, "my other unique id"); // Not this one + } + } + """, + """ + import jakarta.enterprise.inject.spi.AnnotatedType; + import jakarta.enterprise.inject.spi.BeanManager; + import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; + + class Foo { + void bar(BeforeBeanDiscovery beforeBeanDiscovery, BeanManager beanManager) { + AnnotatedType producerType = beanManager.createAnnotatedType(String.class); + beforeBeanDiscovery.addAnnotatedType(producerType, null); // Flag this one + beforeBeanDiscovery.addAnnotatedType(producerType, "my unique id"); // Not this one + beforeBeanDiscovery.addAnnotatedType(String.class, "my other unique id"); // Not this one + } + } + """ + ) + ); + } + +} \ No newline at end of file diff --git a/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethodsTest.java b/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethodsTest.java new file mode 100644 index 0000000000..d8cce54561 --- /dev/null +++ b/src/test/java/org/openrewrite/java/migrate/jakarta/UpdateBeanManagerMethodsTest.java @@ -0,0 +1,96 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://www.apache.org/licenses/LICENSE-2.0 + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.openrewrite.java.migrate.jakarta; + +import org.junit.jupiter.api.Test; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class UpdateBeanManagerMethodsTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec + .parser(JavaParser.fromJavaVersion() + .classpathFromResources(new InMemoryExecutionContext(), "jakarta.enterprise.cdi-api-3.0.0-M4", "jakarta.enterprise.cdi-api-4.0.1")) + .recipe(new UpdateBeanManagerMethods()); + } + + @Test + void fireEvent() { + rewriteRun( + //language=java + java( + """ + import jakarta.enterprise.inject.spi.BeanManager; + import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; + import java.util.Set; + + class Foo { + void bar(BeanManager beanManager, BeforeBeanDiscovery beforeBeanDiscovery) { + beanManager.fireEvent(beforeBeanDiscovery); + } + } + """, + """ + import jakarta.enterprise.inject.spi.BeanManager; + import jakarta.enterprise.inject.spi.BeforeBeanDiscovery; + import java.util.Set; + + class Foo { + void bar(BeanManager beanManager, BeforeBeanDiscovery beforeBeanDiscovery) { + beanManager.getEvent().fire(beforeBeanDiscovery); + } + } + """ + ) + ); + } + + @Test + void createInjectionTarget() { + rewriteRun( + //language=java + java( + """ + import jakarta.enterprise.inject.spi.AnnotatedType; + import jakarta.enterprise.inject.spi.BeanManager; + + class Foo { + void bar(BeanManager beanManager) { + AnnotatedType producerType = beanManager.createAnnotatedType(String.class); + beanManager.createInjectionTarget(producerType); + } + } + """, + """ + import jakarta.enterprise.inject.spi.AnnotatedType; + import jakarta.enterprise.inject.spi.BeanManager; + + class Foo { + void bar(BeanManager beanManager) { + AnnotatedType producerType = beanManager.createAnnotatedType(String.class); + beanManager.getInjectionTargetFactory(producerType).createInjectionTarget(null); + } + } + """ + ) + ); + } +} \ No newline at end of file