Steps

Add clover-maven-plugin to <build> section

  • set the includesAllSourceRoots property to true (default is false) if you're interested in code coverage for JAXB generated sources
  • bind the clover:setup goal to process-sources phase (so that it's executed after sources generation)
  • bind the clover:clover goal to verify or install phase (so that report is generated after test execution)

 

<plugin>
    <groupId>org.openclover</groupId>
    <artifactId>clover-maven-plugin</artifactId>
    <version>${clover.version}</version>
    <configuration>
        <!-- Instrument all source files, also generated by JAXB. Set to false if
        you're not interested in such details (default is false) -->
        <includesAllSourceRoots>true</includesAllSourceRoots>
    </configuration>
    <executions>
        <execution>
            <!-- Call the clover:setup after JAXB sources are generated but before compilation -->
            <id>main1</id>
            <phase>process-sources</phase>
            <goals>
                <goal>setup</goal>
            </goals>
        </execution>
        <execution>
            <!-- Call the clover:clover and generate report after tests are run -->
            <id>main2</id>
            <phase>verify</phase>
            <goals>
                <goal>clover</goal>
            </goals>
        </execution>
    </executions>
</plugin>

 

Add jaxb-api plugin to <dependencies> section

  • this is required to run unit tests
<dependencies>
    <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>${jaxb.version}</version>
    </dependency>
</dependencies>

 

Add maven-jaxb2-plugin to <build> section

  • you might need to add jaxb-xjc and jaxb-impl as plugin's dependencies (see Troubleshooting chapter)
  • you can use extensions like property-listener-injector

<plugin>
    <groupId>org.jvnet.jaxb2.maven2</groupId>
    <artifactId>maven-jaxb2-plugin</artifactId>
    <version>0.8.1</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <extension>true</extension>
                <schemaLanguage>DTD</schemaLanguage>
                <schemaIncludes>
                    <schemaInclude>*.dtd</schemaInclude>
                </schemaIncludes>
                <bindingIncludes>
                    <bindingInclude>*.jaxb</bindingInclude>
                </bindingIncludes>
                <args>
                    <arg>-Xinject-listener-code</arg>
                </args>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-xjc</artifactId>
            <version>${jaxb.version}</version>
        </dependency>
        <dependency>
            <groupId>com.sun.xml.bind</groupId>
            <artifactId>jaxb-impl</artifactId>
            <version>${jaxb.version}</version>
        </dependency>
        <dependency>
            <groupId>org.jvnet.jaxb2-commons</groupId>
            <artifactId>property-listener-injector</artifactId>
            <version>1.0</version>
        </dependency>
    </dependencies>
</plugin>

 

Sample project

 

  • Checkout code from Bitbucket: clover-maven-plugin
  • Go to src/it/jaxb
  • Run mvn clean install
  • Generated report will be available in target/site/clover directory

 

Troubleshooting

Problem: Class not found - javax.activation.DataHandler with an error message like below:

[INFO] [jaxb2:generate {execution: default}]
[FATAL ERROR] org.jvnet.mjiip.v_2.XJC2Mojo#execute() caused a linkage error (java.lang.NoClassDefFoundError) and may be
out-of-date. Check the realms:
[...]
[ERROR] FATAL ERROR
[INFO] ------------------------------------------------------------------------
[INFO] javax/activation/DataHandler
[INFO] ------------------------------------------------------------------------
[INFO] Trace
java.lang.NoClassDefFoundError: javax/activation/DataHandler
        at com.sun.tools.xjc.model.CBuiltinLeafInfo.<clinit>(CBuiltinLeafInfo.java:303)
        at com.sun.tools.xjc.reader.dtd.TDTDReader.<clinit>(TDTDReader.java:442)
[...]

Solution: Define com.sun.xml.bind::jaxb-xjc and com.sun.xml.bind::jaxb-impl as <dependencies> for maven-jaxb2-plugin as in example chapter above.

 

 

Problem: When using the Clover Plugin together with the the JAXB2 Plugin, the build fails during instrumentation due to an unresolved clover.jar with an error message like below:

[ERROR] BUILD ERROR
[INFO] ------------------------------------------------------------------------
[INFO] Error configuring: 
org.jvnet.jaxb2.maven2:maven-jaxb2-plugin. Reason: Error evaluating 
plugin parameter expression: project.compileClasspathElements
[INFO] ------------------------------------------------------------------------
[INFO] Trace
 org.apache.maven.lifecycle.LifecycleExecutionException: Error configuring: org.jvnet.jaxb2.maven2:maven-jaxb2-plugin. 
Reason: Error evaluating plugin parameter expression: project.compileClasspathElements
 at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:707)
[...]
Caused by: org.apache.maven.artifact.DependencyResolutionRequiredException: Attempted to access the artifact 
>>>>>org.openclover:clover:jar:X.Y.Z:compile<<<<<;
which has not yet been resolved
	at org.apache.maven.project.MavenProject.addArtifactPath(MavenProject.java:1906)
[...]

Solution: Define a dependency to org.openclover:clover in your POM, for example:

<dependency>
    <groupId>org.openclover</groupId>
    <artifactId>clover</artifactId>
    <version>4.2.0</version>
</dependency>