Citrus Registry and Resource Injection
@BindToRegistry issues
This inspection reports various issues when using the @BindToRegistry
annotation
Non-public methods
According to the @BindToRegistry Citrus documentation, The annotation works with public methods…, thus this inspection, on one hand, reports non-public @BindToRegistry
annotated methods. When a non-public method is encountered by Citrus, the test execution results in a failure with a message like this:
class com.consol.citrus.annotations.CitrusAnnotations cannot access a member of class [some fully qualified class name] with modifiers “private”
Void methods
It also reports @BindToRegistry
methods with void
return types, because that would result in null values assigned to the respective Citrus registry objects.
Fields without initializers
@BindToRegistry
fields without initializers are reported too, because that would result in null values assigned to the respective Citrus registry objects.
Citrus resources injected into @CitrusTest methods without @CitrusResource
The Citrus documentation, for example the Test action runner injectionsection states that
The parameter requires the @CitrusResource annotations in order to mark the parameter for Citrus resource injection.
In order to make sure that injection happens, this inspection analyzes the parameters of @CitrusTest
annotated test methods: if a parameter of type TestCaseRunner
, TestActionRunner
or TestContext
is defined without the @CitrusResource
annotation, it is marked as a violation.
Additionally, a quick fix available to add the @CitrusResource
annotation to the selected parameter.
Convert @BindToRegistry field to method and vice versa
According to the Citrus documentation on the @BindToRegistry annotation, it can be placed on both fields and public methods, and they are interchangeable.
To make the conversion simpler between the two forms, there are two intention actions called Convert field to @BindToRegistry method and Convert method to @BindToRegistry field that can convert such fields to their corresponding method forms and back.
The intentions are available on the name of @BindToRegistry
annotated fields and methods when those fields don’t have any other annotation on them. In case of converting methods to fields, the method must have a single return
statement, in order for the intention to be available.
The conversions happen as follows:
- Field -> method:
- If the
@BindToRegistry
annotation’sname
attribute is set to a non-empty value, it is carried over tothe method as well, otherwise it isn’t. - The generated method is always public, as Citrus can access such methods only if they are public.
- The generated method’s name is always the original field’s name.
- The code block of the generated method is the field’s initializer as a
return
statement, or empty if the field has no initializer.
- If the
- Method -> field:
- If the
@BindToRegistry
annotation’sname
attribute is set to a non-empty value, it is carried over to the field as well, otherwise it isn’t. - The generated field has the same visibility as the original method (regardless of that non-public @BindToRegistry methods are not valid).
- The generated field’s name is always the original method’s name.
- The initializer of the generated method is the method’s single
return
statement.
- If the
Extract CitrusContext.bind() call to @BindToRegistry field and method
Using the @BindToRegistry
annotation is an alternative to calling CitrusContext.bind()
, thus this intention action extracts CitrusContext.bind()
calls to their corresponding @BindToRegistry
annotated field and method forms.
The intention is available:
- on the identifier of
CitrusContext.bind()
calls, - when the value of the name argument can be evaluated to a string literal by the IntelliJ Platform.
The name
attribute of @BindToRegistry
is set in the following cases:
- either when the name value is a Java keyword,
- or when there is at least one character in the object name that is not allowed to be used in a Java identifier, i.e. in a field name.
If the object name is a Java keyword, the field/method name gets prefixed with an underscore. Whether the name is a Java keyword is determined by the JDK version used in the current module. It falls back to the project-level JDK, and then the highest language level, if no JDK is found.
Static code checks of resource injections
This inspection provides multiple checks regarding Citrus-injected resources, and reports the following:
- A field is annotated with
@CitrusFramework
but the field type is notCitrus
. This would prevent injecting the Citrus object into the field.
- A field is annotated with
@CitrusEndpoint
but the field type is notEndpoint
or one of its inheritors. This would prevent injecting anEndpoint
object into the field.
- A field is annotated with one of the
@*EndpointConfig
/@*ClientConfig
/@*ServerConfig
annotations, but it is not annotated with@CitrusEndpoint
. This would prevent injecting anEndpoint
object into the field, and then be able to override its properties.
- A field has as type one of the inheritors of
Endpoint
but the@*EndpointConfig
/@*ClientConfig
/@*ServerConfig
annotation on the field doesn’t match the type. E.g.:DirectEndpoint
field annotated with@CamelEndpointConfig
.