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
…1286)

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
  • Loading branch information
codecholeric authored Apr 10, 2024
2 parents 23c483b + 1d1a990 commit 40624f1
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 31 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,46 +19,58 @@ 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) {
}

@Autowired
ClassViolatingInjectionRules(Object badBecauseAutowiredField) {
ClassViolatingInjectionRules(Object okayBecauseAutowiredConstructor) {
}

ClassViolatingInjectionRules(@Value("${name}") List<?> badBecauseValueField) {
ClassViolatingInjectionRules(@Value("${name}") List<?> okayBecauseValueConstructorParameter) {
}

@javax.inject.Inject
ClassViolatingInjectionRules(Set<?> badBecauseJavaxInjectField) {
ClassViolatingInjectionRules(Set<?> okayBecauseJavaxInjectConstructor) {
}

@com.google.inject.Inject
ClassViolatingInjectionRules(Map<?, ?> badBecauseComGoogleInjectField) {
ClassViolatingInjectionRules(Map<?, ?> okayBecauseComGoogleInjectConstructor) {
}

void someMethod(String okayBecauseNotInjected) {
}

@Autowired
void someMethod(Object badBecauseAutowiredField) {
void someMethod(Object okayBecauseAutowiredMethod) {
}

void someMethod(@Value("${name}") List<?> badBecauseValueField) {
void someMethod(@Value("${name}") List<?> okayBecauseValueMethodParameter) {
}

@javax.inject.Inject
void someMethod(Set<?> badBecauseJavaxInjectField) {
void someMethod(Set<?> okayBecauseJavaxInjectMethod) {
}

@com.google.inject.Inject
void someMethod(Map<?, ?> badBecauseComGoogleInjectField) {
void someMethod(Map<?, ?> okayBecauseComGoogleInjectMethod) {
}

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

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

@Resource
void someMethod(File badBecauseResourceField) {
@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 40624f1

Please sign in to comment.