Toolchains support for SonarQube Scanner for Maven

As per https://maven.apache.org/guides/mini/guide-using-toolchains.html,

Maven Toolchains provide a way for plugins to discover what JDK (or other tools) are to be used during the build, without the need to configure them in each plugin nin every pom.xml, or forcing a precise location among every machine building the project. […] For example, you want to use a different JDK version to build your project than the version used to run Maven,

(my) concrete use case: at work, we’ve some ancient java 7 application that must be examined. Latest sonarqube maven scanner requires java 8 so, initially, we had to split the build into two separate executions. Later on, we modified the build to make use of toolchains and set the JAVA_HOME to use a JDK8, which allowed us to go back to a one step build again. It’d be nice though, if the sonar scanner for maven could make use of toolchains too, thus not having to fallback to rely on $JAVA_HOME.

ref: https://github.com/spring-projects/spring-boot/issues/18686

thx in advance

Hi,
We don’t intend to support toolchains. The Scanner for Maven runs within the maven’s process so it would be a big effort to fork a separate process.
Couldn’t you have ran the maven build with JDK8, setting java source/target to Java 7?

Hi Duarte,
in our case, we use the same JVM as in production to make the build. We’ve had a couple of cases on production over the years, which were caused due to a bug on the JDK. Those cases would’ve been detected at build time if we’ve been using the same JDK at build/run time, so that is what we have ended up doing.

At some point SQ will require a JDK 11 to perform the analysis on the client/maven side (I recall reading somewhere this was next-LTS scoped? I may be mistaken, though). Then the suggested approach would not be feasible if the build is using jax-ws, or any of the other technologies noted at JEP-320. I’d suppose we could revert to multiple executions in that case, mungling with JAVA_HOME in between but, I’d hope for another workaround.

thanks for your time + best regards

Unfortunately, many plugin authors take this approach, which leads to problems if you use multiple plugins that have conflicting Java version requirements.

@leonard84 is right, the ensuing juggling of runtime class file versioning becomes burdensome. @dmeneses, supporting Maven Toolchains should be “rather simple.” It’s possible there is some underlying Sonarqube complication, but the reference is there for consideration. Additionally, no forked process is required. The instruction runs in the current Maven session as I understand the implementation, or forked automatically.

Maven Toolchain support would be a huge win and is the way to go IMHO. Additionally, “down compiling,” i.e., building 1.8 with an 11 JDK (the current requirement), is risky, albeit an unknown risk, especially if your legacy code is lacking a full test suite for confidence.

1 Like

Within my organization, upgrading SonarQube to version 9.0 became a lengthy process due to the SonarScanner’s requirement for Java 11 but lack of support for Maven Toolchains.

We bind the SonarScanner to Maven’s verify phase so that the install and deploy phases are not reached if the the Quality Gate fails (recap of the Maven lifecycle if you need it). Along with the SonarScanner, we also bind plugins such as Dependency-Check to Maven lifecycle phases in order to assist and enforce application security practices.

Maven phases execute sequentially, so in any normal setting it would be unnecessary for developers to configure their CI pipelines to call each Maven phase and plugin individually. Yet, SonarQube 9.0 left that as one of only two reasonable options for supporting projects developed to use Java 8. That is, in order to continue scanning projects supporting Java 8, each project’s pipeline would need to be updated to call the following Maven phases independently:

  • Call package with JAVA_HOME=%PATH_TO_JAVA_8%.
  • Call verify with JAVA_HOME=%PATH_TO_JAVA_11%.
  • Call deploy with JAVA_HOME=%PATH_TO_JAVA_8%.

In the case of organizations that do not bind the SonarScanner and other Maven plugins to the verify phase, the alternative is to call the sonar:sonar goal with JAVA_HOME=%PATH_TO_JAVA_11%. I imagine that the annoyance generated from updating and testing each project’s CI pipeline to achieve this change scales with the number of projects.

The only other reasonable solution involves taking advantage of Maven Toolchains for plugins that do support it. That is, the solution is to rely on maven-compiler-plugin, maven-surefire-plugin, jaxws-maven-plugin, maven-javadoc-plugin, and other plugins that provide Toolchains support or forking ability so that Java 8 can be used. We found this more reasonable because our parent POM, in use by most projects, already took advantage of the forking ability. We were still required to update each project’s CI pipeline to run Maven with Java 11 by setting JAVA_HOME=%PATH_TO_JAVA_11%.

Java 8 is a LTS version until December of 2030, it’s reasonable to assume that legacy systems will continue using it until very close to that date, and there are few security risks associated with doing so. By not supporting Maven Toolchains or the ability to fork with a different Java executable, the SonarScanner for Maven does not fulfill one of its primary capabilities, the ability to fit into the Maven build without need for manual configuration. I quote the official description of the Maven SonarScanner as follows:

The ability to execute the SonarQube analysis via a regular Maven goal makes it available anywhere Maven is available (developer build, CI server, etc.), without the need to manually download, setup, and maintain a SonarQube Runner installation. The Maven build already has much of the information needed for SonarQube to successfully analyze a project. By preconfiguring the analysis based on that information, the need for manual configuration is reduced significantly.