I want to make an ArchUnit rule that picks up calls to Spring's ResponseEntity that look like this:
new ResponseEntity<>("No record", HttpStatus.NOT_FOUND);
I tried a rule like this:
ArchRule rule = noClasses().should().
callConstructor(ResponseEntity.class, String.class, HttpStatus.class).
because("foo");
but it doesn't seem to be match. My guess at the moment is that this is because of the generic type, as I changing the rule to target a non-generic type and that seemed to work.
I have a feeling that using callConstructorWhere()
might be part of the solution but I'm struggling to find an example of how to use that and can't seem to find the right part of the documentation. I'm using ArchUnit 0.23.1.
CodePudding user response:
Your guess is correct: The generic constructor ResponseEntity(T, HttpStatus)
has erased parameter types (Object, HttpStatus)
,¹ and callConstructor
looks for these raw types.
Unfortunately, even if you use callConstructorWhere
with a custom predicate for the JavaConstructorCall
, you can only get access to the target owner as (raw) JavaClass
, but not as JavaParameterizedType
that could hold the specific type argument T = String
in your case.
So I fear that your issue cannot be solved with the current version of ArchUnit.
¹ With your spring-web.jar
at hand, you can investigate this using
jar xf spring-web-*.jar
javap -v org/springframework/http/ResponseEntity.class \
| grep -A1 'ResponseEntity(T, org.springframework.http.HttpStatus)'
For spring-web-5.3.22.jar
, I get:
public org.springframework.http.ResponseEntity(T, org.springframework.http.HttpStatus);
descriptor: (Ljava/lang/Object;Lorg/springframework/http/HttpStatus;)V