Archive for the ‘Maven’ Category

Maven site generation error: DTDDVFactoryImpl does not extend from DTDDVFactory

When generating a site with Maven, we encountered the following exception when a particular reporting plugin was executed:

org.apache.xerces.impl.dv.DVFactoryException:
DTD factory class org.apache.xerces.impl.dv.dtd.DTDDVFactoryImpl does not extend from DTDDVFactory.

This basically meant that an incompatible version of xerces was trying to be run. We have everything set to use Java 1.6, which ships with its own version of xerces. After some debugging, it was tracked down to the maven-site-plugin which we had recently upgraded to use version 2.1 of the plugin by specifying it in our pom file like so:

<pluginManagement>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-site-plugin</artifactId>
			<version>2.1</version>
		</plugin>
	</plugins>
</pluginManagement>

The maven-site-site plugin has the following dependency structure:

  • org.apache.maven.plugins:maven-site-plugin:maven-plugin:2.1
    • org.apache.maven.doxia:doxia-module-xhtml:jar:1.1.2 (compile)
      • org.apache.maven.doxia:doxia-core:jar:1.1.2 (compile)
        • xerces:xercesImpl:jar:2.8.1 (compile)

It is the dependency of the xercesImpl jar 2.8.1 that is the problem. To get around this issue, you can tell the maven-site-plugin to exclude a particular dependency. This can be done like so:

<pluginManagement>
	<plugins>
		<plugin>
			<groupId>org.apache.maven.plugins</groupId>
			<artifactId>maven-site-plugin</artifactId>
			<version>2.1</version>
			<dependencies>
				<dependency>
					<groupId>org.apache.maven.doxia</groupId>
					<artifactId>doxia-core</artifactId>
					<version>1.1.2</version>
					<exclusions>
						<exclusion>
							<groupId>xerces</groupId>
							<artifactId>xercesImpl</artifactId>
						</exclusion>
					</exclusions>
				</dependency>
			</dependencies>
		</plugin>
	</plugins>
</pluginManagement>

There are a couple of maven reporting plugins that we found produced this exception when run with maven-site-plugin 2.1. These plugins are:

If you use an older version of the maven-site-plugin then the above mentioned reporting plugins should work ok. It is only when specifying a version of 2.1 or above that the exception occurs.

Some of the solutions suggested on the net didn’t work for us, like adding the xercesImpl jar as a dependency to the actual reporting plugin in question, so hopefully the solution mentioned in this post is helpful.

Suppress logging in java unit tests

Here are a couple of different ways of suppressing logging when running unit tests. If you are using apache commons logging then you can suppress logging with the following code:

LogFactory.getFactory().setAttribute(
                "org.apache.commons.logging.Log",
                "org.apache.commons.logging.impl.NoOpLog");

If running your unit tests with JUnit, it is probably best to put this code in the setUp() method. However, if you only wanted it suppressed on particular tests, it could go at the top of the test method instead. Bear in mind that if the logger is a static in the class you are testing, you  may need to then reset the attribute at the end of the test method, otherwise, any tests being run after that one will also have their logging suppressed.

If you run your unit tests within an IDE, you may want to see the logging, but not see the logging when you actually run the build of your project with something like Maven. Thankfully, there is a very simple answer to this if you are using Maven. The maven-surefire-plugin is responsible for running the tests and there is a configuration option which needs to be specified to redirect all the test output to file instead of to the console. This keeps your build reports much cleaner as you aren’t interested in seeing the logging messages. As a bonus, since all output is saved to file, exceptions will also be output to file, so whenever exceptions are thrown in the methods being tested, the stack trace wont show up in the build report.

The configuration option that needs specifying is <redirectTestOutputToFile> and this needs to be set to true, as shown below.

<plugin>
	<artifactId>maven-surefire-plugin</artifactId>
	<configuration>
		<redirectTestOutputToFile>true</redirectTestOutputToFile>
	</configuration>
</plugin>

Cobertura code coverage with Maven and PowerMock

If you use Powermock for unit testing with Maven and Cobertura for code coverage, you are likely to be affected by the following issue noted on the PowerMock issue tracker. If you did not have the maven-surefire-plugin forkmode configured to ‘pertest’, you would find that any tests annotated with @RunWith(PowerMockRunner.class) had zero percentage code coverage when you viewed the resulting code coverage report produced by the cobertura-maven-plugin. Whilst running with ‘pertest’ fixed the issue, it was very slow to run the Maven build compared against a forkmode of ‘once’.

In September 2009, Cobertura released version 1.9.3 and one of the changes mentioned was the following:

  • Support the case where multiple classloaders each load the Cobertura classes.

Seeing this, I decided to test if that would fix the issue. At present, the latest version of the cobertura-maven-plugin is 2.3 which runs with Cobertura 1.9.2. There are some snapshots in the codehaus snapshot repository which run with Cobertura 1.9.3.  However, I found that the snapshots were constantly changing, and each run of the Maven build downloaded the latest version and sometimes the latest version had issues. There is probably a way to stop this from happening but if you don’t want to use snapshots, there is a change you can make to the 2.3 version which will also fix the issue. The cobertura-maven-plugin-2.3.pom file needs to be edited. It can be found in your repository under the following directory: org/codehaus/mojo/cobertura-maven-plugin/2.3/

Find the dependencies section of the pom file and change the versions of Cobertura from 1.9.2 to 1.9.3. There are two instances that need changing:

<dependency>
	<groupId>net.sourceforge.cobertura</groupId>
	<artifactId>cobertura</artifactId>
	<version>1.9.3</version>
</dependency>
<dependency>
	<groupId>net.sourceforge.cobertura</groupId>
	<artifactId>cobertura-runtime</artifactId>
	<version>1.9.3</version>
	<type>pom</type>
</dependency>

With that change, you should find that you can safely remove the ‘pertest’ forkmode configuration since by default the surefire plugin will run with forkmode set to ‘once’, and your cobertura code coverage results should be reporting correctly.

UPDATE (26th April 2010):

There is actually a better way of doing this which doesn’t involve having to edit the pom file for the actual plugin.

In your pom file you will have defined the cobertura-maven-plugin in the reporting section. The reporting section does not allow to add dependencies to a plugin. However the build section does, and the plugins defined in the reporting section will also pick up those dependencies. Therefore, you can also define the cobertura-maven-plugin in the build section as a plugin. This will allow you to specify some dependencies, as shown below.

<build>
	<plugins>
		<plugin>
			<groupId>org.codehaus.mojo</groupId>
			<artifactId>cobertura-maven-plugin</artifactId>
			<version>2.3</version>
			<dependencies>
				<dependency>
					<groupId>net.sourceforge.cobertura</groupId>
					<artifactId>cobertura</artifactId>
					<version>1.9.4.1</version>
				</dependency>
				<dependency>
					<groupId>net.sourceforge.cobertura</groupId>
					<artifactId>cobertura-runtime</artifactId>
					<version>1.9.4.1</version>
					<type>pom</type>
				</dependency>
			</dependencies>
		</plugin>
    </plugins>
</build>

This will then use cobertura 1.9.4.1.  Any version above 1.9.2 should fix the issue, but 1.9.4.1 is currently the latest and supposedly a lot faster than previous versions.

UPDATE (11th May 2010):

Good news! There is now version 2.4 of the cobertura-maven-plugin. This uses 1.9.4.1 version of Cobertura, so none of the above is now necessary.