There are several ways to do code quality checks in SOA Suite. In this blog post I will describe a minimal effort setup which uses Jenkins 2.9, SonarQube 5.6 and the SonarQube XML Plugin 1.4.1. SonarQube is a popular tool to check and visualize code quality. An XML Plugin is available for SonarQube which allows you to define custom XPath rules. At the end of this post I will shortly describe several other options which you can consider to help you improve code quality by doing automated checks.
Using SonarQube and the XML Plugin to do code quality checks on SOA Suite components has several benefits compared to other options described at the end of this post.
- It is very flexible and relatively technology independent. It allows you to scan any XML file such as BPEL, BPMN, OSB, Mediator, Spring, composite.xml files
- It requires only configuration of SonarQube, the SonarQube XML Plugin and the CI solution (Jenkins in this example)
- It has few dependencies. It does not require an Oracle Home or custom JAR files on your SonarQube server.
- The XML Plugin has support (by SonarSource) so high probability it will still work in future versions of SonarQube.
- Writing rules is simple; XPath expressions. it does not require you to write Java code to create checks.
What we can’t do with this setup is check relations between files since the XPath expressions are executed on single documents (defined with an Ant-style file-mask). Usually though when compiling or deploying SOA Suite composites, it will fail if there are references to files which are not present.
Jenkins / SonarQube setup
Setting up the environment
In this setup I’ve used Git, Jenkins, Maven, SonarQube. I’ve used an Ubuntu Server 16.04 install. The installation of the tools is pretty straightforward. Git and Maven are easiest: sudo apt-get install git maven. Jenkins is also pretty easy since there is a Debian package available. See here. For SonarQube I’ve installed a MySQL server (sudo apt-get install mysql-server). Next I’ve used the following manual. After the installation I’ve set the default admin password to admin (see here). I have also got Sonatype Nexus 3 installed on the server. This required a bit more effort. Nexus 2.x and Nexus 3.x use different API locations. Maven needed to be able to find Nexus (settings.xml file used for Nexus 2 cannot be used OOTB for Nexus 3). The init.d script had some different installation steps. See here.
Of course most people will know how to use Git. I prefer a setup in which the server has a single Git user who owns the repository and grant other users access with SSH keys to that repository. You can see how this is done here.
SonarQube
I’ve used the XML Plugin in SonarQube to define XPath rules. This first needs to be installed. Administration, System, Update Center and install the plugin:
You have to define a project in SonarQube. Administration, Projects, Management, Create Project.
The SonarQube Scanner (called from the CI tool) requires some configuration in order to know where in SonarQube to store the results of the analysis and what to analyse. This configuration can be stored in your source code project in a sonar.properties. In my case this file contained the following (match the settings from when you created the project in SonarQube):
sonar.projectKey=SampleApplication:master
sonar.projectName=SampleApplication
sonar.projectVersion=1.0
sonar.sources=SampleApplication/HelloWorldProject/SOA
I put this sonar.properties in the project directory (SampleApplication/HelloWorldProject). The sources location is relative to the checkout directory. I checked out the entire application so that is the root of my SonarQube analysis. For a composite compilation you might want to make the build more specific in that you only checkout a specific project and not the entire application. In that case the source path will also be different.
SonarQube rules
In order to create rules in SonarQube, you can go to Rules, Language XML, Xpath rule. Here you can create custom XPath rules.
In this case I’m checking .bpel files. The rule will be violated if the value of the name attribute of the process tag does not end with Process. Thus my BPEL process should have a name ending in Process. You should mind that XPath 1.0 is used (see here) in this plugin and not XPath 2.0. Thus you cannot use the ends-with function (which is why I needed to use the substring/string-length XPath expression).
There are two options for defining XPath rules which become apparent from browsing the source code of the XPath check here. You can use a boolean expression (false = violation) and XPath queries selecting violating nodes. First the boolean expression:
not(count(/process[substring(@name, string-length(@name) – string-length(‘Process’) +1) = ‘Process’])=1)
If this is true, then a rule violation is displayed on top of the page showing the source code (it cannot determine the specific node):
If however you want to have the rule violation displayed at the node which is violating the rule, you should restructure your rule to only select violating nodes, such as:
/process[not(substring(@name, string-length(@name) – string-length(‘Process’) +1) = ‘Process’)]
Now the rule violation can be pinpointed to the violating node.
SonarQube Quality Gate
SonarQube uses the concept of quality gates. You can define rules which define when the quality gate will be passed. In my case I have defined the rule as Critical in the Quality profile Sonar Way.
I have also defined a rule in the Quality Gate that Critical Issues are not allowed.
Jenkins configuration
You can make the SonarQube analysis part of your CI solution. In this example I’m using Jenkins. First install the following plugins:
Under Global Configuration, you have to add your SonarQube installation:
You can obtain the authentication token from SonarQube, Administration, My Account, Generate Token.
You also have to do this for the Quality Gates plugin.
Under Global Tool Configuration, you have to add SonarQube Scanner configuration. See below:
Below you can see part of the job configuration indicating the SonarQube Scanner will be used. If a SonarQube Quality Gate is not passed, the build will fail.
A failed build indicates the reason why it has failed:
After the issue is fixed, the Quality Gate has been passed.
Inside the Maven build or as a separate step?
You can make the SonarQube code quality checks part of the Maven pom.xml file (application or project level). This requires you to make the SonarQube configuration available to the pom file which is used to do the build. This has the risk a developer will send measures to SonarQube of code which has not yet been committed, polluting the measures in SonarQube. Also there is a loss of separation of concerns. The CI tool usually has the configuration of different tools (such as VCS, build tools, JVM, code quality tools, automated testing tools, etc) defined and the order in which they are executed (usually in jobs, stages). These tools such as Jenkins, Bamboo, Hudson are good at keeping this configuration and visualizing the progress during a build. This task for the code quality checks will (if you define the sonar properties in a pom.xml file) now be delegated to the Maven build. Having a separate CI tool to do this, allows you to implement a loose coupling between the tools used to execute the build and the source code.
Other options
Code Compliance Inspector
You can use the AIA Code Compliance Inspector (CCI). Using the Code Compliance Inspector allows you to define XPath expressions to do checks. You can only check a single file at a time and JDeveloper 11.1.1.7 or later is required (see here). You can call the Code Compliance Inspector from within JDeveloper. Read more here
You can use the following SonarQube plugin to put the Code Compliance Inspector output in SonarQube.
OJAudit
Oracle JDeveloper comes with its own audit framework called OJAudit. There is a plug-in available to put the ojaudit output in SonarQube. In order to use OJAudit, you should define your own rules using Java code. For ADF there is already a set of rules available. You can see how this works here. In the below picture you can see an example on how you can give suggestions to fix issues as part of the rules.
In order to get this working, as you can see from the (4 part) tutorial, you have to do several things such as (but not limited to): create a JDeveloper extension project, write your audit rules in Java, packaging the audit rules, making the audit rules available on your SonarQube server which requires an Oracle home since it is ojaudit you will be using. Of course as described in this post, you also need to do the described configuration of your CI tool and SonarQube.
You can create something similar for SOA/BPM/OSB and other components. This has the benefit that it can also be used within JDeveloper and not only in SonarQube. Also you can check references to files and consistency between files since the rules will be applied on application level.
Hi,
I’m following the example, but the sonar-scanner does not consider the .bpel file as a source. It indexes the .bpel, but only the .xml files are parsed, as log:
INFO: Index files
INFO: Included sources:
INFO: soa/ValidarPedidoCommerceISBPEL/*.xml
INFO: soa/ValidarPedidoCommerceISBPEL/*.bpel
INFO: 5 files indexed
INFO: 193 files ignored because of inclusion/exclusion patterns
INFO: Quality profile for xml: Multiplus-BPEL-QualityProfile
INFO: Sensor SonarJavaXmlFileSensor [java]
INFO: 4 source files to be analyzed
INFO: Sensor SonarJavaXmlFileSensor [java] (done) | time=1586ms
INFO: 4/4 source files have been analyzed
INFO: Sensor XML Sensor [xml]
INFO: Sensor XML Sensor [xml] (done) | time=801ms
INFO: Sensor Zero Coverage Sensor
INFO: Sensor Zero Coverage Sensor (done) | time=51ms
This is my sonar-project.properties:
sonar.projectKey=ValidarPedidoCommercev1
sonar.projectName=ValidarPedidoCommercev1
sonar.projectVersion=1.0
sonar.sources=soa/ValidarPedidoCommerceISBPEL
sonar.inclusions=soa/ValidarPedidoCommerceISBPEL/*.xml, soa/ValidarPedidoCommerceISBPEL/*.bpel
Thanks in advance
I found the solution.
I have edited the sonar-project.properties file with the following line:
sonar.xml.file.suffixes=.xml,.xsd,.xsl,.bpel
Hi,
Xapth expression which validates the BEPL Process name is not working.
Can’t compile XPath expression “/process{not(substring(@name, srting-length(@name) – string-length(‘Process’+1) = ‘Process’)]” for rule xml:BPELProcessName
at org.sonar.plugins.xml.checks.XPathCheck.createExpressionException(XPathCheck.java:149)
at org.sonar.plugins.xml.checks.XPathCheck.getXPathExpressionForDocument(XPathCheck.java:143)
at org.sonar.plugins.xml.checks.XPathCheck.evaluateXPath(XPathCheck.java:84)
at org.sonar.plugins.xml.checks.XPathCheck.validate(XPathCheck.java:169)
Can you please help me with correct Xpath expression.
Thanks,
Prasanth
Hi. Can you try with string-length instead of srting-length? With kind regards, Maarten
Note that copy-pasting the code might cause problems, the characters ‘ dash – are very evil in above code. Very undesirable, xpath-language is enough headache as it is..
Interesting read! Wanted to point you to the CCI SonarQube plug-in here: https://github.com/wvanderdeijl/oracle-cci-sonarqube
Thank you! I’ve updated the blog post with the link.