Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,25 @@
import org.openrewrite.java.search.FindAnnotations;
import org.openrewrite.java.search.UsesType;
import org.openrewrite.java.tree.J;
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.Space;
Comment on lines +24 to 25
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
import org.openrewrite.java.tree.JavaType;
import org.openrewrite.java.tree.Space;
import org.openrewrite.java.tree.Space;

import org.openrewrite.marker.Markers;
import org.openrewrite.xml.XPathMatcher;
import org.openrewrite.xml.XmlVisitor;
import org.openrewrite.xml.tree.Xml;

import java.util.HashSet;
import java.util.Set;

import static java.util.Collections.emptyList;

public class AddStaticVariableOnProducerSessionBean extends Recipe {
public class AddStaticVariableOnProducerSessionBean extends ScanningRecipe<Set<String>> {

private static final XPathMatcher EJB_PATH = new XPathMatcher("ejb-jar/enterprise-beans/session");

@Override
public String getDisplayName() {
return "Adds `static` modifier to `@Produces` field that are on session bean";
return "Adds `static` modifier to `@Produces` fields that are in session beans";
}

@Override
Expand All @@ -38,26 +48,51 @@ public String getDescription() {
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor() {
public Set<String> getInitialValue(ExecutionContext ctx) {
// Class names of session beans found in XML
return new HashSet<>();
}

@Override
public TreeVisitor<?, ExecutionContext> getScanner(Set<String> acc) {
return Preconditions.check(
Preconditions.and(
new UsesType<>("jakarta.enterprise.inject.Produces", false),
Preconditions.or(
new UsesType<>("jakarta.ejb.Singleton", false),
new UsesType<>("jakarta.ejb.Stateful", false),
new UsesType<>("jakarta.ejb.Stateless", false)
)
),
new FindSourceFiles("**/ejb-jar.xml"),
new XmlVisitor<ExecutionContext>() {
@Override
public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) {
if (EJB_PATH.matches(getCursor())) {
Xml.Tag ejbClassTag = tag.getChild("ejb-class").orElse(null);
Xml.Tag sessionTag = tag.getChild("session-type").orElse(null);
if (ejbClassTag != null && sessionTag != null) {
String className = ejbClassTag.getValue().orElse(null);
String sessionType = sessionTag.getValue().orElse(null);
if (className != null &&
("Singleton".equalsIgnoreCase(sessionType) ||
"Stateless".equalsIgnoreCase(sessionType) ||
"Stateful".equalsIgnoreCase(sessionType))) {
acc.add(className);
}
}
}
return super.visitTag(tag, ctx);
}
});
}

@Override
public TreeVisitor<?, ExecutionContext> getVisitor(Set<String> acc) {
return Preconditions.check(
new UsesType<>("jakarta.enterprise.inject.Produces", false),
new JavaVisitor<ExecutionContext>() {
@Override
public J visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) {
if (!multiVariable.hasModifier(J.Modifier.Type.Static) &&
hasAnnotation(multiVariable, "@jakarta.enterprise.inject.Produces") &&
isInSessionBean()) {
hasAnnotation(multiVariable, "@jakarta.enterprise.inject.Produces") &&
(isInSessionBean() || isInXml())) {
return multiVariable.withModifiers(ListUtils.concat(multiVariable.getModifiers(),
new J.Modifier(Tree.randomId(), Space.SINGLE_SPACE, Markers.EMPTY, null, J.Modifier.Type.Static, emptyList())));
}
return super.visitVariableDeclarations(multiVariable, ctx);
return multiVariable;
}

private boolean isInSessionBean() {
Expand All @@ -66,13 +101,22 @@ private boolean isInSessionBean() {
return false;
}
return hasAnnotation(parentClass, "@jakarta.ejb.Singleton") ||
hasAnnotation(parentClass, "@jakarta.ejb.Stateful") ||
hasAnnotation(parentClass, "@jakarta.ejb.Stateless");
hasAnnotation(parentClass, "@jakarta.ejb.Stateful") ||
hasAnnotation(parentClass, "@jakarta.ejb.Stateless");
}

private boolean isInXml() {
J.ClassDeclaration parentClass = getCursor().firstEnclosing(J.ClassDeclaration.class);
if (parentClass != null && parentClass.getType() != null) {
return acc.contains(parentClass.getType().getFullyQualifiedName());
}
return false;
}

private boolean hasAnnotation(J j, String annotationPattern) {
return !FindAnnotations.find(j, annotationPattern).isEmpty();
}
});
}
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import org.openrewrite.test.RewriteTest;

import static org.openrewrite.java.Assertions.java;
import static org.openrewrite.xml.Assertions.xml;

class AddStaticVariableOnProducerSessionBeanTest implements RewriteTest {

Expand Down Expand Up @@ -55,8 +56,8 @@ public class SomeDependency {}
);
}

@Test
@DocumentExample
@Test
void addStaticOnProducesMarkedStateless() {
rewriteRun(
//language=java
Expand Down Expand Up @@ -93,6 +94,104 @@ void exampleMethod() {
);
}

@Test
void addStaticToProducesFieldFromXml() {
rewriteRun(
xml(
//language=xml
"""
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1">
<display-name>testTransaction</display-name>
<enterprise-beans>
<session>
<ejb-name>MySessionBean</ejb-name>
<ejb-class>com.test.MySessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
""",
sourceSpecs -> sourceSpecs.path("ejb-jar.xml")
),
//language=java
java(
"""
package com.test;
import jakarta.enterprise.inject.Produces;

public class MySessionBean {
@Produces
private SomeDependency someDependency;
void exampleMethod() {
return;
}
}
""",
"""
package com.test;
import jakarta.enterprise.inject.Produces;

public class MySessionBean {
@Produces
private static SomeDependency someDependency;
void exampleMethod() {
return;
}
}
"""
)
);
}

@Test
void noChangeWhenBeanNotMentionedInXml() {
rewriteRun(
xml(
//language=xml
"""
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/ejb-jar_3_1.xsd" version="3.1">
<display-name>testTransaction</display-name>
<enterprise-beans>
<session>
<ejb-name>TestProducerFieldStaticOnSessionBean</ejb-name>
<ejb-class>org.test.ejb.TestProducerFieldStaticOnSessionBean</ejb-class>
<session-type>Stateless</session-type>
<transaction-type>Container</transaction-type>
</session>
<session>
<ejb-name>TestProducerFieldNonStaticOnSessionBean</ejb-name>
<ejb-class>org.test.ejb.TestProducerFieldNonStaticOnSessionBean</ejb-class>
<session-type>Singleton</session-type>
<transaction-type>Container</transaction-type>
</session>
</enterprise-beans>
</ejb-jar>
""",
sourceSpecs -> sourceSpecs.path("ejb-jar.xml")
),
//language=java
java(
"""
package com.test;
import jakarta.enterprise.inject.Produces;

public class MySessionBean {
@Produces
private SomeDependency someDependency;
void exampleMethod() {
return;
}
}
"""
)
);
}

@Test
void addStaticOnProducesMarkedStateful() {
rewriteRun(
Expand Down