Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Spring constructor injection with SonarQube

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?

like image 696
Layman Avatar asked Jan 12 '19 18:01

Layman


People also ask

Should spring components use constructor injection?

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.

What are the rules about constructor injections in SonarQube?

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.

Can Spring Framework infer constructor arguments?

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?

How do I integrate SonarQube with continuous integration?

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.


Video Answer


2 Answers

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;
like image 138
Nikolas Charalambidis Avatar answered Oct 06 '22 09:10

Nikolas Charalambidis


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.

like image 45
Tristan Avatar answered Oct 06 '22 07:10

Tristan