Creating a distributable JAR file with maven

In this entry I’m going to show how to package a jar file using a maven multi module project with different alternatives based on my working experience for microservices.

First, let’s take a look the project structure, demo-jar-assembly is composed by two maven modules (the java code it isn’t important here only the configuration files), the module1 is a dependency for module2.

\demo-jar-assembly
|   pom.xml
|
+---module1
|   |   pom.xml
|
\---module2
    |   pom.xml

Let’s shows some alternatives to build the distribution package.

Seguir leyendo

Maven, find security bugs using spotbugs

«SpotBugs is a program which uses static analysis to look for bugs in Java code. SpotBugs requires JRE (or JDK) 1.8.0 or later to run. However, it can analyze programs compiled for any version of Java, from 1.0 to 1.9.«

This tool is an option to execute a simple static code inspection to fing bugs in the code (arround of 400 bug patterns), and it could be a enxcelent option to integrate in a maven project. Read more about it into spotbugs documentation.

In this entry I’m going to show how to use in a single maven project (no multi module) and add the report to the maven site documentation.

Let’s get started.

Seguir leyendo

How to use maven release plugin with a git repository

Hi! this is a quick entry as reminder to know how to use the plugin to release a version of the project into git repository using maven.

1. Add the scm tag in your pom.xml:

    <scm>
        <developerConnection>${developerConnectionUrl}</developerConnection>
        <tag>HEAD</tag>
    </scm>

Note: I’ve declared ‘developerConnectionUrl‘ as argument because I’m going to overwrite it when execute the release.

Jenkins – Sonarqube, Nodejs dependency to analyse CSS and Javascript

sonar logo-title

I’ve upgraded my Sonarqube server from the 6.4 to 7.8 version, the last than support MySQL database, according to documentation, the Nodejs > 6.0 is required to analyse Javascript code.

But I didn’t know, until my Jenkins jobs failed. The error is clear, I need to install Nodejs:

org.sonarsource.nodejs.NodeCommandException: Error when running: 'node -v'. Is Node.js available during analysis?

I’ve installed Sonarqube over Red Hat Enterprise Linux 7 (RHEL), the process to install Nodejs is very simple. If the repository is enabled only have to execute this commands in terminal and check the version.

$ su -
$ yum install rh-nodejs8
$ scl enable rh-nodejs8 bash
$ node --version
v8.6.0

Seguir leyendo

Jenkins – Sonarqube error for bad encoding

sonar logo-title

Recently I had to upgrade my Sonarqube server from 6.4 to 7.8 and I noticed a problem in few projects when the jacoco report is loaded by Jenkins with the jacoco-maven-plugin to Sonarqube using the plugin sonar-jacoco (1.0.1.143) , the error show this message:

[INFO] Sensor JaCoCo XML Report Importer [jacoco]
[ERROR] Coverage report '/var/lib/jenkins/workspace/test/dummy/target/site/jacoco/jacoco.xml' could not be read/imported. Error: {}
java.lang.IllegalStateException: Failed to parse JaCoCo XML report: /var/lib/jenkins/workspace/test/sge-webapp/target/site/jacoco/jacoco.xml
	at org.sonar.plugins.jacoco.XmlReportParser.parse(XmlReportParser.java:96)
	at org.sonar.plugins.jacoco.JacocoSensor.importReport(JacocoSensor.java:73)
	at org.sonar.plugins.jacoco.JacocoSensor.importReports(JacocoSensor.java:64)
	at org.sonar.plugins.jacoco.JacocoSensor.execute(JacocoSensor.java:48)
	at org.sonar.scanner.sensor.AbstractSensorWrapper.analyse(AbstractSensorWrapper.java:48)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:85)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.lambda$execute$1(ModuleSensorsExecutor.java:59)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.withModuleStrategy(ModuleSensorsExecutor.java:77)
	at org.sonar.scanner.sensor.ModuleSensorsExecutor.execute(ModuleSensorsExecutor.java:59)
	at org.sonar.scanner.scan.ModuleScanContainer.doAfterStart(ModuleScanContainer.java:82)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.scanner.scan.ProjectScanContainer.scan(ProjectScanContainer.java:400)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:395)
	at org.sonar.scanner.scan.ProjectScanContainer.scanRecursively(ProjectScanContainer.java:392)
	at org.sonar.scanner.scan.ProjectScanContainer.doAfterStart(ProjectScanContainer.java:358)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.scanner.bootstrap.GlobalContainer.doAfterStart(GlobalContainer.java:141)
	at org.sonar.core.platform.ComponentContainer.startComponents(ComponentContainer.java:136)
	at org.sonar.core.platform.ComponentContainer.execute(ComponentContainer.java:122)
	at org.sonar.batch.bootstrapper.Batch.doExecute(Batch.java:73)
	at org.sonar.batch.bootstrapper.Batch.execute(Batch.java:67)
	at org.sonarsource.scanner.api.internal.batch.BatchIsolatedLauncher.execute(BatchIsolatedLauncher.java:46)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.sonarsource.scanner.api.internal.IsolatedLauncherProxy.invoke(IsolatedLauncherProxy.java:60)
	at com.sun.proxy.$Proxy43.execute(Unknown Source)
	at org.sonarsource.scanner.api.EmbeddedScanner.doExecute(EmbeddedScanner.java:189)
	at org.sonarsource.scanner.api.EmbeddedScanner.execute(EmbeddedScanner.java:138)
	at org.sonarsource.scanner.maven.bootstrap.ScannerBootstrapper.execute(ScannerBootstrapper.java:65)
	at org.sonarsource.scanner.maven.SonarQubeMojo.execute(SonarQubeMojo.java:104)
	at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:137)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:210)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:156)
	at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:148)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:117)
	at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:81)
	at org.apache.maven.lifecycle.internal.builder.singlethreaded.SingleThreadedBuilder.build(SingleThreadedBuilder.java:56)
	at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:128)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:305)
	at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:192)
	at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:105)
	at org.apache.maven.cli.MavenCli.execute(MavenCli.java:957)
	at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:289)
	at org.apache.maven.cli.MavenCli.main(MavenCli.java:193)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:282)
	at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:225)
	at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:406)
	at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:347)
Caused by: com.ctc.wstx.exc.WstxIOException: Input length = 1
	at com.ctc.wstx.sr.StreamScanner.constructFromIOE(StreamScanner.java:633)
	at com.ctc.wstx.sr.StreamScanner.loadMoreFromCurrent(StreamScanner.java:1063)
	at com.ctc.wstx.sr.StreamScanner.parseFullName2(StreamScanner.java:1994)
	at com.ctc.wstx.sr.StreamScanner.parseFullName(StreamScanner.java:1952)
	at com.ctc.wstx.sr.BasicStreamReader.handleNonNsAttrs(BasicStreamReader.java:3117)
	at com.ctc.wstx.sr.BasicStreamReader.handleStartElem(BasicStreamReader.java:2968)
	at com.ctc.wstx.sr.BasicStreamReader.nextFromTree(BasicStreamReader.java:2839)
	at com.ctc.wstx.sr.BasicStreamReader.next(BasicStreamReader.java:1073)
	at org.sonar.plugins.jacoco.XmlReportParser.parse(XmlReportParser.java:53)
	... 55 common frames omitted
Caused by: java.nio.charset.MalformedInputException: Input length = 1
	at java.nio.charset.CoderResult.throwException(CoderResult.java:281)
	at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:339)
	at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
	at java.io.InputStreamReader.read(InputStreamReader.java:184)
	at java.io.BufferedReader.fill(BufferedReader.java:161)
	at java.io.BufferedReader.read1(BufferedReader.java:212)
	at java.io.BufferedReader.read(BufferedReader.java:289)
	at com.ctc.wstx.io.MergedReader.read(MergedReader.java:105)
	at com.ctc.wstx.io.ReaderSource.readInto(ReaderSource.java:86)
	at com.ctc.wstx.io.BranchingReaderSource.readInto(BranchingReaderSource.java:56)
	at com.ctc.wstx.sr.StreamScanner.loadMoreFromCurrent(StreamScanner.java:1060)
	... 62 common frames omitted

Even the job finished with success status the Sonarqube server don’t show the coverage report over the source code.

After some research I found the problem is because my jacoco.xml report has some characters in ISO-8859-1 that can’t be parsed by the sonar-jacoco plugin, this one load the xml file with charset in UTF-8 by default,  you can check the source code in github.

https://github.com/SonarSource/sonar-jacoco/blob/2fa1baae841598238d02a945422b60348f75b52a/src/main/java/org/sonar/plugins/jacoco/XmlReportParser.java#L45-L47

I think the jacoco-maven-plugin is building the report in the right way because my project needs the charset encoding in ISO-8859-1 but the sonar-jacoco plugin only support UTF-8.

Then to resolve it there are two choices:

1. Change the output encoding for jacoco report

I don’t like this option but is the most rapid way, during the runtime the jacoco.xml report is built with the same charset encoding than sonar (sonar.sourceEncoding)  but the output of jacoco can be modified with this property:

-Dproject.reporting.outputEncoding=UTF-8

Taken from jacoco docs.

Then the inspection use correctly the encoding ISO-8859-1 but the output of the jacoco report is in UTF-8. The error in sonar-jacoco plugin is skipped but the impact of this change only affect the presentation in Sonarqube.

My step in jenkins looks like this:

clean verify -P sonar
-Dsonar.sourceEncoding=ISO-8859-1
-Dproject.reporting.outputEncoding=UTF-8

2020-04-04 15_51_26-test Config [Jenkins] - Brave

2. Improve the sonar-jacoco plugin

I downloaded the version release 1.0.2.475 and modified the source code to support other charset encoding, I’m not sure if is the best implementation but I’m gonna will send the pull request to the community. This is the class:


public class XmlReportParser {
private final Path xmlReportPath;
public XmlReportParser(Path xmlReportPath) {
this.xmlReportPath = xmlReportPath;
}
public List<SourceFile> parse() {
XMLInputFactory factory = XMLInputFactory.newInstance();
factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, false);
factory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
try {
XMLStreamReader parser = factory.createXMLStreamReader(Files.newBufferedReader(xmlReportPath, getCharsetForEncoding()));
// …
}
private Charset getCharsetForEncoding(){
if(System.getProperty("sonar.sourceEncoding")==null){
return StandardCharsets.UTF_8;
}
else{
return Charset.forName(System.getProperty("sonar.sourceEncoding"));
}
}
}

Because the jacoco use the same source encoding in maven, only if I set the parameter «sonar.sourceEncoding» the plugin will change the charset when the xml is loaded.

Even the plugin is not supported in my Sonarqube server, is working with my projects now.

2020-04-04 15_33_22-Marketplace - Administration - Brave

See you my friends!

 

 

Encoding in Maven (Character code)

Codificación en Maven (Código carácteres)

Si trabajas con sistemas bassados en Unix y Windows posiblemente te has deber encontrado con el pequeño problema del códgio de carácteres entre cada sistema.

Por ejemplo si escribes algún carácter como vocales con acentos o ñ’s, o cualquier otro ajeno al ingles te puedes encontrar con texto ilegible por el compilador, que es la causa por la cual falla al ejecutarse en otros sistemas.

Para visualizar los carácteres correctamente debes utilizar alguna de estas codificaciones:

  • Utilizar UTF-8 (nativo de Linux/Unix):
  • Utilizar Cp1252, (está por defecto en Windows XP)

Nota: Windows 7 utiliza UTF-8 por defecto.

Ahora hay que saber donde fue generado el código y donde lo quieres abrir,  para ahorrar la explicación a mi humilde opinión por la experiencia que tengo es » trabajar con UTF-8«, así puede ser cargado en la mayoría de los sistemas sin problemas, ya sea en equipos Mac, Linux o Windows.

Vamos a ver donde se puede configurar esto: Seguir leyendo