Duplicate class error when both axistools and clover plugin are included in maven project - clover

We have a maven project which uses clover and axistools-wsdl2java plugin. Platfrom is windows.
We are using clover 2.4.0 plugin to get code coverage which integrated in project's pom.xml.
Configured the clover plugin as shown below.
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>2.4.0</version>
<configuration> <generatePdf>true</generatePdf>
<generateXml>true</generateXml>
<generateHtml>true</generateHtml>
<licenseLocation>C:/EcasSVNCO/ews/ews-mvn/ewsbase/src/test/resources/license/clover.license</licenseLocation>
<reportDescriptor>C:/EcasSVNCO/ews/ews-mvn/ewsbase/src/test/resources/descriptor/default-clover-report.xml</reportDescriptor>
<excludes>
<exclude>${basedir}/src/main/java/*.java</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>install</id>
<phase>install</phase>
<goals>
<goal>instrument</goal>
<goal>clover</goal>
</goals>
</execution>
<!--
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>instrument</goal>
<goal>clover</goal>
</goals>
</execution>
<execution>
<id>site</id>
<phase>pre-site</phase>
<goals>
<goal>instrument</goal>
<goal>clover</goal>
</goals>
</execution>
-->
</executions>
</plugin>
Also, there is axistools plugin used to generate classes using wsdl file, which is configured as below.
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>axistools-maven-plugin</artifactId>
<version>1.4</version>
<configuration>
<sourceDirectory>${base.dir}/src/main/resources/wsdl</sourceDirectory>
<outputDirectory>${base.dir}/src/main/java</outputDirectory>
<wsdlFiles>
<wsdlFiles>wsecas.wsdl</wsdlFiles>
</wsdlFiles>
<packageSpace>com.symantec.wsecas</packageSpace>
<testCases>true</testCases>
<serverSide>true</serverSide>
<phase>install</phase>
<subPackageByFileName>true</subPackageByFileName>
</configuration>
<executions>
<execution>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
When we execute a command 'mvn clean install' , compilation will go fine. Then first axistool's wsdl2java goal is ran and source files are generated in respective directory.
Next clover plugin tries to instrument the source code by running unit test cases, when this plugin places the instrumented source code under
{basedir}/target/clover/src/main/java/...
Then it fires "compile" goal to compile all the source code. While compiling the source code, two source paths are getting added i.e.
{basedir}/src/main/java/... and {basedir}/target/clover/src/main/java/... , both have same classes.
When maven compiler tries to compile these sources compilation is failing by throwing "Duplicate Class Error".
But when we comment out axistools plugin, clover instrumentation and report generation goes fine.
If any of you have come across similar issue 'Duplicate class error', please guide us on this regard.
Any suggestion and help will be greatly appreciated.

It seems that the problem is that your Axis plugin generates sources to src/main/java (it should be rather a target/src-generated).
When the Clover is invoked it will first take 'normal' sources from src/main/java, instrument them and put into target/clover/java. Next Clover will change list of source roots replacing src/main/java by target/clover/java.
Next the AXIS code generation comes into play and it generates new sources again into src/main/java adding also this directory as extra source root.
As a consequence a compiler sees the same set of sources (i.e. non-generated ones) in two locations and complains about it.
This case is very similar to the one described in Clover's Knowledge Base:
https://confluence.atlassian.com/display/CLOVERKB/Duplicate+class+errors+with+Clover+and+JAXB+or+JAXB2+plugin
https://confluence.atlassian.com/display/CLOVERKB/Duplicate+class+errors+with+Clover+and+jaxws-maven+plugin
you will find possible solutions in these articles.

Related

Compiling gRPC,with both Kotlin and Java using Maven (various packages not found)

I have a mixed kotlin/java project and I wanted to add gRPC to it. I configured the gRPC plugin as usual:
<extensions>
<extension>
<groupId>kr.motd.maven</groupId>
<artifactId>os-maven-plugin</artifactId>
<version>1.6.2</version>
</extension>
</extensions>
<plugins>
<plugin>
<groupId>org.xolstice.maven.plugins</groupId>
<artifactId>protobuf-maven-plugin</artifactId>
<version>0.6.1</version>
<configuration>
<protocArtifact>
com.google.protobuf:protoc:3.11.2:exe:${os.detected.classifier}
</protocArtifact>
<pluginId>grpc-java</pluginId>
<pluginArtifact>
io.grpc:protoc-gen-grpc-java:1.25.0:exe:${os.detected.classifier}
</pluginArtifact>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>compile-custom</goal>
</goals>
</execution>
</executions>
</plugin>
...
but when building from scratch
mvn clean && mvn package
the kotlin code would never find the generated sources. When building first from IntelliJ it would work fine - IntelliJ knows what to do.
I tried configuring build-helper-maven-plugin to include the generated-sources directories that the protobuf compiler and stub generator use, but that didn't seem to have any effect (and in fact seems unnecessary).
The answer it turns out is because of the order plugins execute. Generally for kotlin-java hybrid projects you want to compile the kotlin first so that the java compiler knows how to find kotlin classes. The problem is, if you do that the kotlin compiler doesn't see the protoc-generated java classes yet. It's a circular dependency.
It took me a while to figure it out, but to fix it you just have to tell the kotlin compiler where to find the protoc-generated sources like this:
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<executions>
<execution>
<id>compile</id>
<goals> <goal>compile</goal> </goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
<sourceDir>${project.build.directory}/generated-sources/protobuf/java/</sourceDir>
<sourceDir>${project.build.directory}/generated-sources/protobuf/grpc-java/</sourceDir>
</sourceDirs>
</configuration>
</execution>
...
</plugin>
It took me entirely too long to figure that out, so I'm posting this as a self-answered question to perhaps save somebody else some time.
I saw a number of related questions but none exactly the same. Good luck.

How to stop Apache maven <outputDirectory> to overwrite the folder

I have the following directory hierarchy:
generated
|
| -->java
Java directory has the following package: com.model
that contains java models that I copy/paste from somewhere before I compile the application.
The issue that I use Protocol buffer and I tell maven to output the generated files on same previous directory BUT over a new package:
Result : Protocol buffer generates the new package and deletes the old package.
I have no idea why does it do that although the package names are different?
Here is that part of pom I use to generate java from protocol buffer:
<plugin>
<groupId>com.google.protobuf.tools</groupId>
<artifactId>maven-protoc-plugin</artifactId>
<configuration>
<protocExecutable>C:\protoc.exe</protocExecutable>
<protoSourceRoot>./src/proto</protoSourceRoot>
<outputDirectory>./src/generated/java</outputDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
if you look at the code for the plugin you'll see that the code has been hardcoded to clean the directory:
https://github.com/dtrott/maven-protoc-plugin/blob/master/src/main/java/com/google/protobuf/maven/AbstractProtocMojo.java#L154
// Quick fix to fix issues with two mvn installs in a row (ie no clean)
cleanDirectory(outputDirectory);
There's 2 ways to solve this..either set the output directory to a temp directory and then use the maven copy plugin or the maven build plugin to copy the files into the directory of your choice, or modify the maven plugin to remove that line (or better yet make it configurable).
Tommy
I have solved my issue by the following :
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-resources</phase>
<goals>
<goal>run</goal>
</goals>
<configuration>
<tasks>
<delete dir="./destination"/>
<copy todir="./destination">
<fileset dir="./source"/>
</copy>
<delete dir="./source"/>
</tasks>
</configuration>
</execution>
</executions>
</plugin>
However , I get this error "An Ant BuildException has occured: Only one of tofile and todir may be set"

Maven annotation processing with maven-compiler-plugin

I try to compile my code that contains annotations that generate source code. I use the maven-compiler-plugin and build-helper-maven-plugin. My POM is looking like that:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<generatedSourcesDirectory>${project.build.directory}/generated-sources/apt</generatedSourcesDirectory>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/apt</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
When I run mvn compile, ${project.build.directory}/generated-sources/apt is added as a source directory, and the generated sources are generated in the correct directory. But I get compiler errors because of missing references to the generated classes. It's like the generated source directory is not included in the compilation process.
I also try apt-maven-plugin which does not generate anything. And maven-annotation-plugin but it behaves as describe above.
The release 2.0.7-SNAPSHOT of maven-annotation-plugin should solve the problem
fwiw I just downgraded from 3.0 to 2.5.1 and fixed an issue I was seeing with APT processing not being executed after a few runs, using maven so just downgraded one version:
http://search.maven.org/#search%7Cgav%7C1%7Cg%3A%22org.apache.maven.plugins%22%20AND%20a%3A%22maven-compiler-plugin%22
Can you try with the latest version of maven compiler plugin (2.3.2)?
Also build-helper-maven-plugin is not required since it looks like you are using the maven-compiler-plugin itself to generate the sources from the annotation.

Is it possible to single out and run a specific goal bound to a maven phase?

Updated to (hopefully) clarify: If a goal is defined to run during a given phase, is it possible to run the individual goal without running thru all phases. In other words would it be possible to run the antrun:run goal (which is defined as part of the install phase below) without getting dependencies, generate-resources, compiling, testing, package, etc?
I'm using the antrun plugin to create a zip file during the package phase and to delete and copy some files during the install phase. I understand how to run single maven plugin goals, for example: mvn antrun:run. However, is there a way to run a specific execution's goal? Something like mvn antrun:run:execution-id, or mvn phase:antrun:run?
Basically, I'd be nice if I can tell maven to do nothing else but run the ant tasks defined below inside the deploy phase, for example. It's kind of tedious having to wait for maven to go thru all the phases just to check if the ant tasks in the deploy phase are working correctly.
<executions>
<!-- create zip file -->
<execution>
<id>create-zip</id>
<phase>package</phase>
<configuration>
<tasks>
...create zip...
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
<!-- do some other stuff -->
<execution>
<id>copy-files</id>
<phase>install</phase>
<configuration>
<tasks>
...delete some files, copy some files ...
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
In other words would it be possible to run the antrun:run goal (which is defined as part of the install phase below) without getting dependencies, generate-resources, compiling, testing, package, etc?
No it's not. While you can configure a plugin (with a <configuration> section under the <plugin> element) and call in on the command line, you can't invoke a specific executionid (and consequently the <configuration> specific to an <execution>).
The only solution in your case would be to declare the antrun plugin in a profile, let's say my-profile, to duplicate the following part of the configuration to configure the plugin in this profile:
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<version>1.3</version>
<configuration>
<tasks>
... delete some files, copy some files ...
</tasks>
</configuration>
</plugin>
and to call with the right active profile:
mvn antrun:run -Pmy-profile
Try the exec maven plugin...
For ex:
When you run jboss with maven, you can't see the jboss console output, but I need it to display, so what I did is I wrote a java file that reads in server.log(the server console output) as it changes to display the changes so it appears that jboss console is actually showing(a bit hack-ish but working). So I come to the point of answering your question, during the pre-integration-test I executed a java goal which starts my java program. Here is how , using execute plugin of course :
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1</version>
<executions>
<execution>
<id>console-start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
</execution>
</executions>
<configuration>
<mainClass>org.eclipse.console.Main</mainClass>
</configuration>
</plugin>
You just run the install and it executes during the pre-integration-test, however if you just want to execute something like java, use the execute plugin. Sorry if the answer not appropriate, I didn't have the patience to read your question in details, my work hours are over .. cheers

Maven-2: avoid default packaging?

My project uses many assemblies, hence I'm interested only in the assemblies.
On executing mvn install apart from the assemblies, I'm getting the default packaged .jar.
How can I avoid this?
I have a pom.xml similar to the one you have provided.
On executing mvn install, I'm getting App1.jar, App2.jar, and snapshot jar containing all contents
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<executions>
<execution>
<id>assemblyone</id>
<phase>compile</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>App1</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>${basedir}/src/main/resources/assemblies/report.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>assemblytwo</id>
<phase>compile</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<finalName>App2</finalName>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>${basedir}/src/main/resources/assemblies/src.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
How can I avoid this snapshot (not sure of the exact term) jar and ensure that only assemblies are created?
I can read your question two ways, I've outlined answers for both below. If neither is correct, can you modify your question with a bit more explanation please.
1) Do you mean you have a project with default (jar) packaging, and you want to avoid the creation of the jar when no assembly is defined? If this is the case, what is the build achieving if no assembly is defined?
2) Do you instead mean that you are running mvn assembly:assembly to generate the assembly and want to know how to get that assembly when running the install goal?
For option 2, you can bind the assembly-plugin to a lifecycle phase to ensure it is always run, if you specify that <appendAssemblyId> should be false, then the assembly will replace the default jar.
For example, this configuration will invoke the assembly plugin during the packaging phase and replace the default jar:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-2</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<appendAssemblyId>false</appendAssemblyId>
<descriptors>
<descriptor>src/main/assembly/archive.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
For option 1, this is actually quite tricky to do. The best I can think of is to specify that the project has pom packaging and configure the project with the executions normally bound to the jar lifecycle in a profile. The lifecycle bindings you'd need to configure are listed in the introduction to the build lifecycle
I'm not sure that you can really do that in a really simple way.
A solution is to call the clean plugin once the build is achieved, by doing that:
<build>
<plugins>
<plugin>
<artifactId>maven-clean-plugin</artifactId>
<executions>
<execution>
<id>auto-clean</id>
<phase>package</phase>
<goals>
<goal>clean</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
This way, the JAR created in the target/ directory will be deleted at the end of the Maven2 execution.
However, you will have to define another directory to store the assemblies created by Maven2. Otherwise, it will be deleted by the call of the clean plugin... If you want to store them in the directory assemblies-target/, you can add that in the pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2-beta-4</version>
<configuration>
...
<!-- Copy the ZIP in target/ of the ROOT directory. -->
<outputDirectory>assemblies-target</outputDirectory>
</configuration>
...
I think it would be much more clear if you showed us your whole POM and the artifacts that are being built. I can only guess as to what the problem is because your terminology is not what I am familiar with. This is my guess as to the problem: you have a POM configured to generated two assembly JARs, but you get a third JAR for the POM itself. In other words, if your POM's artifactId is MyApp, you are getting a MyApp-1.0.0.jar or similar in addition to the two JARs you actually want.
If that is the case, the problem boils down to that you are using Maven to create multiple artifacts from a single module. Maven is designed to produce only one primary artifact from each module. What I would do is change your POM to have a packaging type of "pom" and give it two modules in a <modules> section named App1 and App2. Create sub-directories under your module, one for each App. Give them each a POM configured for a single assembly, with a packaging type of "jar". Move the code/files/etc. as appropriate into each sub-module so there aren't any remaining in the parent module.
With Maven, if you find yourself generating two artifacts from one module (which you are), you should first consider that you are probably violating a Maven best-practice and rearrange things so you only produce one artifact per module.
Please let me know if this doesn't make sense and I will try to clarify.