Skip to content

Commit

Permalink
consider Jakarta EE9 injection annotations for general coding rule
Browse files Browse the repository at this point in the history
The condition `BE_ANNOTATED_WITH_AN_INJECTION_ANNOTATION` and the rule `NO_CLASSES_SHOULD_USE_FIELD_INJECTION`
previously considered the `javax.inject.Inject` and `javax.annotation.Resource` annotations,
but not their jakarta variants (`jakarta.inject.Inject` and `jakarta.annotation.Resource`).

Resolves: #1285

Signed-off-by: Manfred Hanke <[email protected]>
  • Loading branch information
hankem committed Apr 8, 2024
1 parent 8266ffe commit 56f8ecb
Show file tree
Hide file tree
Showing 5 changed files with 33 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;

Expand All @@ -21,8 +19,12 @@ public class ClassViolatingInjectionRules {
private Set<?> badBecauseJavaxInjectField;
@com.google.inject.Inject
private Map<?, ?> badBecauseComGoogleInjectField;
@Resource
private File badBecauseResourceField;
@javax.annotation.Resource
private File badBecauseJavaxResourceField;
@jakarta.inject.Inject
private Object badBecauseJakartaInjectField;
@jakarta.annotation.Resource
private Object badBecauseJakartaResourceField;

ClassViolatingInjectionRules(String okayBecauseNotInjected) {
}
Expand Down Expand Up @@ -60,7 +62,15 @@ void someMethod(Set<?> okayBecauseJavaxInjectMethod) {
void someMethod(Map<?, ?> okayBecauseComGoogleInjectMethod) {
}

@Resource
void someMethod(File okayBecauseResourceMethod) {
@javax.annotation.Resource
void someMethod(File okayBecauseJavaxResourceMethod) {
}

@jakarta.inject.Inject
void someMethod(Void okayBecauseJakartaInjectMethod) {
}

@jakarta.annotation.Resource
void someMethod(Integer okayBecauseJavaxResourceMethod) {
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
import java.util.function.Function;
import java.util.stream.Stream;

import javax.annotation.Resource;
import javax.persistence.EntityManager;

import com.google.common.base.Joiner;
Expand Down Expand Up @@ -266,7 +265,9 @@ Stream<DynamicTest> CodingRulesTest() {
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseValueField").beingAnnotatedWith(Value.class))
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseJavaxInjectField").beingAnnotatedWith(javax.inject.Inject.class))
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseComGoogleInjectField").beingAnnotatedWith(com.google.inject.Inject.class))
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseResourceField").beingAnnotatedWith(Resource.class));
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseJavaxResourceField").beingAnnotatedWith(javax.annotation.Resource.class))
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseJakartaInjectField").beingAnnotatedWith(jakarta.inject.Inject.class))
.by(ExpectedField.of(ClassViolatingInjectionRules.class, "badBecauseJakartaResourceField").beingAnnotatedWith(jakarta.annotation.Resource.class));

expectFailures.ofRule("no classes should access standard streams and no classes should throw generic exceptions");
expectAccessToStandardStreams(expectFailures);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import com.tngtech.archunit.lang.ArchCondition;
import com.tngtech.archunit.lang.ArchRule;
import com.tngtech.archunit.lang.ConditionEvents;
import com.tngtech.archunit.lang.conditions.ArchConditions;

import static com.tngtech.archunit.PublicAPI.Usage.ACCESS;
import static com.tngtech.archunit.base.DescribedPredicate.not;
Expand Down Expand Up @@ -371,19 +372,15 @@ private static ArchCondition<JavaClass> throwGenericExceptions() {
* @see #NO_CLASSES_SHOULD_USE_FIELD_INJECTION
*/
@PublicAPI(usage = ACCESS)
public static final ArchCondition<JavaField> BE_ANNOTATED_WITH_AN_INJECTION_ANNOTATION = beAnnotatedWithAnInjectionAnnotation();

private static ArchCondition<JavaField> beAnnotatedWithAnInjectionAnnotation() {
ArchCondition<JavaField> annotatedWithSpringAutowired = beAnnotatedWith("org.springframework.beans.factory.annotation.Autowired");
ArchCondition<JavaField> annotatedWithSpringValue = beAnnotatedWith("org.springframework.beans.factory.annotation.Value");
ArchCondition<JavaField> annotatedWithGuiceInject = beAnnotatedWith("com.google.inject.Inject");
ArchCondition<JavaField> annotatedWithJakartaInject = beAnnotatedWith("javax.inject.Inject");
ArchCondition<JavaField> annotatedWithJakartaResource = beAnnotatedWith("javax.annotation.Resource");
return annotatedWithSpringAutowired.or(annotatedWithSpringValue)
.or(annotatedWithGuiceInject)
.or(annotatedWithJakartaInject).or(annotatedWithJakartaResource)
.as("be annotated with an injection annotation");
}
public static final ArchCondition<JavaField> BE_ANNOTATED_WITH_AN_INJECTION_ANNOTATION =
ArchConditions.<JavaField>beAnnotatedWith("org.springframework.beans.factory.annotation.Autowired")
.or(beAnnotatedWith("org.springframework.beans.factory.annotation.Value"))
.or(beAnnotatedWith("com.google.inject.Inject"))
.or(beAnnotatedWith("javax.inject.Inject"))
.or(beAnnotatedWith("javax.annotation.Resource"))
.or(beAnnotatedWith("jakarta.inject.Inject"))
.or(beAnnotatedWith("jakarta.annotation.Resource"))
.as("be annotated with an injection annotation");

/**
* A rule that checks that none of the given classes uses field injection.
Expand Down
4 changes: 2 additions & 2 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ ext {
javaxAnnotationApi : [group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'],
springBeans : [group: 'org.springframework', name: 'spring-beans', version: '5.3.23'],
springBootLoader : [group: 'org.springframework.boot', name: 'spring-boot-loader', version: '2.7.13'],
jakartaInject : [group: 'jakarta.inject', name: 'jakarta.inject-api', version: '1.0'],
jakartaAnnotations : [group: 'jakarta.annotation', name: 'jakarta.annotation-api', version: '1.3.5'],
jakartaInject : [group: 'jakarta.inject', name: 'jakarta.inject-api', version: '2.0.1'],
jakartaAnnotations : [group: 'jakarta.annotation', name: 'jakarta.annotation-api', version: '2.1.1'],
guice : [group: 'com.google.inject', name: 'guice', version: '5.1.0'],
// NOTE: The pure javaee-api dependencies are crippled, so to run any test we need to choose a full implementation provider
geronimoEjb : [group: 'org.apache.geronimo.specs', name: 'geronimo-ejb_3.1_spec', version: '1.0.2'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ dependencies {
// `api` dependencies so we can access them within `archunit-integration-test`
api dependency.jodaTime
api dependency.javaxAnnotationApi
api dependency.jakartaInject
api dependency.jakartaAnnotations
api dependency.springBeans
api dependency.guice
api dependency.geronimoEjb
Expand Down

0 comments on commit 56f8ecb

Please sign in to comment.