I'm trying to mavenize a project. The code base is beginning to bloat and it needs to be split into multiple modules. However, we already have a somewhat proprietary deployment process in place and the directory structure cannot be compromised in favor of the Maven way.
The simplified structure is as follows:
/workspace/basesrc/
|_ superpom.xml
|_ com/company/parentpkg/
|_ ModuleA/
|_ pom.xml
|_SubAModuleA/
|_ SubAModuleAClass.java
|_ pom.xml
|_SubAModuleB/
|_ SubAModuleBClass.java
|_ pom.xml
|_ ModuleB/
|_ ModuleBClass.java
|_ pom.xml
I was able to build the project using the following setup:
Approach A
(superpom.xml):
<build>
<sourceDirectory>.</sourceDirectory>
</build>
This is inherited by the submodules, in effect building only its current directory.
However, Sonar seems to have trouble resolving package names if this is the case as stated in this thread: mvn sonar:sonar throws exception while doing Java AST scan.
Approach B: Specify the root source directory and use maven compiler inclusions, as explained here: http://maven.apache.org/guides/mini/guide-using-one-source-directory.html
(superpom.xml)
<build>
<sourceDirectory>/workspace/basesrc/</sourceDirectory>
</build>
(SubAModuleA pom.xml)
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<includes><include>com/company/parentpkg/ModuleA/SubAModuleA/**/*.java</include></includes>
</configuration>
</plugin>
</plugins>
</build>
Again, this works for the case of maven build. But Sonar seems to include the whole /workspace/basesrc/ folder despite running mvn sonar:sonar from a submodule directory.
SO my question is,
If I use Approach A, is there a way to configure/override the root directory property in which Sonar Maven Plugin is searching for Java source files? Can it be different from the ${project.build.sourceDirectory} maven property?
Using Approach B, How can Sonar be configured to analyze only what is being built by maven-compiler-plugin?
For those who are interested, just to reiterate <sonar.includes> must be placed under <properties> instead of <configuration> under <plugin>. And sonar must be version 3.5 up.
well, I think following should help you to setup your project: http://maven.apache.org/guides/mini/guide-using-one-source-directory.html
See the section:
Producing Multiple Unique JARs from a Single Source Directory
Please understand that it's not the way things should be setup in maven, as you're breaking the convention, that makes maven so strong. On the other hand I understand that in some projects there is no option for changing the source structure to the way maven convention says it.
Related
I am regularly deploying a Maven project to a Tomcat server, using Travis CI. My project is a web app, so I have configured my pom.xml for building a WAR file, instead of a JAR:
...
<packaging>war</packaging>
...
With Maven, I can generate a directory containing all the JavaDoc files for my project; Maven puts them in the target/site/apidocs directory. But then, when I deploy my project, Travis doesn't perform any mvn site phase so I don't have my JavaDocs on the server.
Should I edit my pom.xml so that Maven puts the JavaDoc files somewhere in the src directory (instead of target) or is there a way to package the JavaDoc files together with the WAR file? I thought that I could create a docs/ directory inside src/main/webapp/. Specifically: is it "good practice" to generate my JavaDoc in src instead of target? if not, how can I have a WAR file containing my JavaDoc?
What would you suggest is the best thing to do?
I already know how to generate a standalone JAR containing my JavaDoc files (see here), but this is not what I'm looking for.
Use the site plugin https://maven.apache.org/plugins/maven-site-plugin/ and the javdoc plugin https://maven.apache.org/plugins/maven-javadoc-plugin/usage.html.
Add the following to your pom.xml
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<configuration>
<links>
<link>http://commons.apache.org/lang/api</link>
<link>http://java.sun.com/j2se/1.5.0/docs/api</link>
<link>http://this-one-will-not-work</link>
</links>
</configuration>
</plugin>
</plugins>
</reporting>
then mvn site:site your documentation will be in target/site you can also deploy it.
I encounter issue to configure a multilevel maven modules for Sonar Analysis.
It is working fine with the following structure:
parent module
|- level 1
|- module with code to analyze
But if I add a depth to the module with code to analyze, I'm not able to configure it.
parent module
|- level 1
|- level 2
|- module with code to analyze
I tried several configurations:
with no special configuration:
I get an Can not execute SonarQube analysis: The project 'level 2' is already defined in SonarQube but not as a module of project 'level 1'. If you really want to stop directly analysing project 'level 2', please first delete it from SonarQube and then relaunch the analysis of project 'level 1'. error. I don't want to launch on level 1 because I have my integration tests at the same level, directly in parent module.
using skippedModules property on level 1 and level 2: Only the parent module is analyzed.
using includedModules by specifying "module with code to analyze": Only the parent module is analyzed.
Does someone has an idea on how to handle it? (I mean without to modifying the hierarchy folder which is really helpful for some other requirements)
Thanks by advance
I found a workaround:
- I launch mvn clean install on parent project
- then I launch sonar:sonar at 'level 2' module, I can do it because all the code source to be analyzed is under the same module.
At least it is working on my sample project but currently I didn't handle yet to make it working on my real project.
Building my Maven multi-module project is consistently working for me. I'm using SonarQube v4.3.
I placed a sonar-project.properties file at the root level of the parent Maven project.
Here's the contents:
# Root project information
sonar.projectKey=<I used the project pom's groupId + artifactId>
sonar.projectName=<can be anything>
sonar.projectVersion=<I used the project pom's version>
# Some properties that will be inherited by the modules
sonar.sources=src
In my parent project's pom, I declared this property:
<sonar.language>java</sonar.language>
Within the same pom, I declared the following:
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
<version>2.2</version>
</plugin>
</plugins>
</pluginManagement>
</build>
I'm building only the parent project, which results in the parent and all of its children getting analyzed by SonarQube. I'm using:
mvn clean install sonar:sonar
or
mvn sonar:sonar
I think that you have one module in SonarQube as a project. First, you need to remove it and then execute the new analysis.
This happen when a project already exist but in different level (project, module and so on)
This behaviour is related to this JIRA : http://jira.codehaus.org/browse/SONAR-4245
The only solution is using old version of Sonar..
I've spent the day yesterday up and down StackOverflow and Google and have come close to some solutions, but nothing is working. I hope someone could just tell me whether this is even possible.
We have a multi-module Maven project. I just learned that the structure is like this:
Web Service XYX
+- pom.xml
+- Web Module
+- pom.xml (parent pom is WebService 123)
+- API Module
+- pom.xml (parent pom is API ABC)
+- API Implementation
+- pom.xml (parent pom is API ABC)
What I have done is setup UT and IT Code Coverage from Jacoco to Sonar via Jenkins. The UT Coverage gets sent to Sonar correctly for the UT combined.
The IT Coverage is always 0%. My IT is run against the Web Module after starting the WAR up using the Maven Tomcat plugin. The code that it should be exercising lives inside the module API Implementation. Even though a jacoco-it.exec file was generated and analyzed by Sonar, it always shows me that no lines of code were hit. Is there a way to actually do this?
BTW - I know it can be done because this article indicates exactly what I need:
http://www.sonarqube.org/measure-code-coverage-by-integration-tests-with-sonar/
However, the article fails to mention if the modules are referred to the same parent in the project. I'm making an assumption that it does.
After searching up and down the interwebs, the best solution seem to have been add another module for ITs that actually referred to the main pom as the parent. Used Cargo to grab and run the WAR from the IT module using the Tomcat Maven Module. The Code Coverage now has all the classes, not just the ones from the Web Module.
I doubt it's due to using different parent poms.
When analyzing the coverage sonar checks the code of each module against the coverage file that is specified in the sonar.jacoco.itReportPath property. The default is target/jacoco-it.exec. So when analyzing WebModule it checks for coverage info in WebModule/target/jacoco-it.exec.
So what I do for my projects, is to use a central file in the root module for the the IT coverage data instead.
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.7.4.201502262128</version>
<executions>
<execution>
<id>prepare-it-agent</id>
<phase>pre-integration-test</phase>
<goals>
<goal>prepare-agent</goal>
</goals>
<configuration>
<destFile>${session.executionRootDirectory}/target/jacoco-it.exec</destFile>
<append>true</append>
<propertyName>failsafeArgLine</propertyName>
</configuration>
</execution>
</executions>
</plugin>
The ${session.executionRootDirectory} property is the root of execution, in your case the WebServiceXYZ if you run the build of that. This also works if you have multi-module with more than one level of nesting.
Now you need to point sonar to use that file when analyzing IT coverage. So you have to set the sonar.jacoco.itReportPath to that file. Unfortunately, this does not work with the session.executionRootDirectory property and you have to set the absolute path to the file manually. I do not recommend to specify the absolute path in the pom.xml as this path is specific to your build environment. So either set the path in Sonar or as System property of your build environment. I set it directly in the Sonar Project Settings (Java > Jacoco), for example /opt/buildroot/myProject/target/jacoco-it.exec.
Now sonar will check that file for the IT coverage analysis of each module.
I'm trying to share the same pmd configuration across all my submodules. I'm looking for the best way to achieve that
I thought that I could place it in the parent project, like I did it for checkstyle plugin
Parent pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.9.1</version>
<configuration>
<configLocation>/src/main/config/checkstyle.xml</configLocation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-pmd-plugin</artifactId>
<version>2.7.1</version>
<configuration>
<rulesets>
<ruleset>pmd.xml</ruleset>
</rulesets>
<linkXref>true</linkXref>
<sourceEncoding>${project.build.sourceEncoding}</sourceEncoding>
<targetJdk>${maven.compiler.target}</targetJdk>
</configuration>
</plugin>
</plugins>
</build>
Multi Module Structure
Here my structure
parent
|-- src
| `-- main
| `-- resources
| |-- pmd.xml
| `-- checkstyle.xml
|-- pom.xml
|-- model
| `-- pom.xml
`-- webapp
`-- pom.xml
Error
With this configuration, I only obtain the following error :
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-pmd-plugin:2.7.1:pmd (default-cli) on project model: An error has occurred in PMD Report report generation. Could not find resource 'pmd.xml'. -> [Help 1]
Solution 1
I tried this solution that works for me, because I only have one level on submodules :
But in a close future, I may have more levels, so I'm not convinced that's THE method
${basedir}/../src/main/resources/pmd.xml
Solution 2
Without writing all the solution, I can use an assembly to zip my config and use it in all my submodule as an dependency. This would work for any levels, but this is overkilling !
Here a link that would explain it: How to include resources from war to another maven project
So I'm looking for a Maven trick, but I don't what or how ! Every advice / clue is welcome.
Have a separate module that contains those generic config files like build-tools. Then you can add this module as a dependency to your plugin config and load it.
I have implemented an example of this with a checkstyle config file across a multiple modules in the ksoap2-android project.
https://github.com/mosabua/ksoap2-android/blob/master/pom.xml
I was reading the documentation for the ruleset tag and it says
The rule sets may reside in the classpath, filesystem or at a URL. For
rule sets that are bundled with the PMD tool, you do not need to
specificy the absolute path of the file. It will be resolved by the
plugin. But if the rule set is a custom rule set, you need to specify
its absolute path.
I solved the problem of sharing my PMD settings across my multi-maven build by specifying the URL to the ruleset file in my parent pom. (My repo was http accessible). Unfortunately this won't work though if you don't have your repo http accessible, but many people may.
Short version:
I would like the maven-glassfish-plugin to only be executed in the root project in a hierarchical (inheritance based) maven multiproject setup.
Long version:
Following setup:
project-root
|
+-pom.xml
|
+ ear-module
| |
| +-pom.xml
|
+ jar-module
|
+-pom.xml
All submodules are included in the root project via <modules>...</modules> and all submodules inherit the root project pom.xml.
In my root project pom I include the maven-glassfish-plugin:
...
<plugin>
<groupId>org.glassfish.maven.plugin</groupId>
<artifactId>maven-glassfish-plugin</artifactId>
<version>2.1</version>
<inherited>false</inherited>
<configuration>
<glassfishDirectory>${glassfish.home}</glassfishDirectory>
<passwordFile>${glassfish.home}/masterpassword.txt</passwordFile>
<domain>
<name>${project.name}</name>
<adminPort>4848</adminPort>
<httpPort>8080</httpPort>
<httpsPort>8443</httpsPort>
<iiopPort>3700</iiopPort>
<jmsPort>7676</jmsPort>
</domain>
<components>
<component>
<name>poc.vermittler</name>
<artifact>${project.basedir}/ear-module/target/ear-project-1.0-SNAPSHOT.ear</artifact>
</component>
</configuration>
</plugin>
...
(Note: This is just an simplified version of my pom. It may not run :)
I want to only deploy the ear-module module to glassfish, this is why I added <inherited>false</inherited> section, and depict the modules to be deployed as <components>...</components> in the root pom.
Now the command:
mvn glassfish:deploy
Will deploy the ear to glassfish, all well so far... but then maven will decent recursively to all submodules, which will all fail with:
No plugin found for prefix 'glassfish' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories
I could tell maven to only run the root project with the -pl option but for my gusto, deploying shouldn't rely on such additional information.
Thanks a lot for your help!
It seems that there is no good solution to this problem:
either the plugin supports a "NOP"/silent discard functionality
or it will fail in all subprojects
Another method could be to create a new subproject (which is not included in the root project by <modules>...</modules> but inherits from the root project) and add dependencies to only the projects that have a deployment artifact.
The plugin can now be included in this subproject without it wanting to run any subproject.
Or for anybody who is lazy: mvn clean package glassfish:redeploy -pl . to selectively only run the root project without descending into child projects.