I have a piece of code with field injections I am trying to convert to use constructor injections instead. The initial code looks like this:
@Autowired
private Environment env;
@Autowired
private YYYAdaptor yyyAdaptor;
@Autowired
private JAXBContext jaxbContext;
And this is how I rewrite it:
private Environment env;
private YYYAdaptor yyyAdaptor;
private JAXBContext jaxbContext;
@Autowired
public YYYResource(Environment env, YYYAdaptor yyyAdaptor,
@Qualifier("YYYYReq") JAXBContext jaxbContext) {
this.env = env;
this.yyyAdaptor = yyyAdaptor;
this.jaxbContext = jaxbContext;
}
Doing this gives me a critical vulnerability on the sonar scan, with "this member" referring to each of the declared variables:
Annotate this member with "@Autowired", "@Resource", "@Inject", or "@Value", or remove it
What is the best way I can avoid using field injections while avoiding sonar throwing a fit?
Check-out the SonarQube rule RSPEC-4288: Spring components should use constructor injection. Although it doesn't explain why the final usage is triggered as non-compliant, there is a compliant code sample.
In recent SonarQube installations, these rules about constructor injections are disabled by default. Update : There would be an other use case for constructor injection, it's when you are in a configuration class where each "method" is a bean constructor.
And as of version 5, Spring Framework can infer constructor arguments. Due to this, you can drop the @Autowired completely for all constructor based injection. Why Constructor Injection is important?
Integrating SonarQube into a CI Making SonarQube part of a Continuous Integration process is possible. This will automatically fail the build if the code analysis did not satisfy the Quality Gate condition. For us to achieve this, we're going to be using SonarCloud which is the cloud-hosted version of SonaQube server.
Check-out the SonarQube rule RSPEC-4288: Spring components should use constructor injection. Although it doesn't explain why the final
usage is triggered as non-compliant, there is a compliant code sample. Initialize the fields as null
to make it SonarQube compliant:
private Environment env = null;
private YYYAdaptor yyyAdaptor = null;
private JAXBContext jaxbContext = null;
However, what SonarQube says is not sacred and is filled with lots of false-positives. These static-analyzers hits the issues that are worth the further introspection, yet not definitive and based on the rules made by people with opinions.
Personally, I'd mark this issue as won't fix and declare the fields as final
to make the object immutable:
private final Environment env;
private final YYYAdaptor yyyAdaptor;
private final JAXBContext jaxbContext;
The rationale for this SonarQube rule is to avoid NullPointerException
like explained for this rule : https://rules.sonarsource.com/java/RSPEC-3306
But when you have @Autowired
with required = true (default value), you will never have a NullPointerException
with a field injection.
So I think the good practice would be to deactivate and ignore this rule which is deprecated.
In recent SonarQube installations, these rules about constructor injections are disabled by default.
Update : There would be an other use case for constructor injection, it's when you are in a configuration class where each "method" is a bean constructor. You don't want to use field injection when a bean (like RestTemplateBuilder
) is only used in some of the constructors, so you use pure constructor injection with no field declaration at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With