Thursday, February 21, 2008

Maven2, Multiple Source Directories, and the Build Helper Plugin

I'm currently working on a project dealing a lot with Web Services. I'm using the CXF Codegen Plugin to generate Java classes from an existing WSDL. However, I need to write a few classes of my own to create a common client interface and a mock implementation in addition to the code generated by CXF.

My dilemma is that Maven2 supports only using a single <sourceDirectory> in the pom. I don't want to use a single source directory because of cluttering my code with the generated source or vice versa. I'd rather not use two separate modules because ... well, I don't want 2 different artifacts exposing virtually the same capabilities.

So, after a few Google searches, I found the Build Helper Maven Plugin.

This plugin allows you to add additional source directories to your module. See my example below. I'm adding the directory of my generated source files, ${basedir}/target/generated/src/main/java (in addition to the default source directory ${basedir}/src/main/java).


<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${basedir}/target/generated/src/main/java</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>2.0.2-incubator</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<!-- This is where the generated source files will be placed -->
<sourceRoot>${basedir}/target/generated/src/main/java</sourceRoot>
<wsdlOptions>
<wsdlOption>
<wsdl>${basedir}/src/main/resources/wsdl/my.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>

13 comments:

Immo Hüneke said...

I've found this really helpful - I was struggling with exactly the same problem, creating a Mojo class based on an existing Mojo that I declared as a dependency in the POM. It isn't obvious, but if you do this the compiler needs access to the source of the parent class and its parents as well, otherwise Plexus cannot process the annotations and the usual symptom is that this.project == null. So I got the maven-dependency-plugin to download the sources and unpack them into my target area. But until I found your posting I was tearing my hair out trying to work out how to get the compiler to recognise them.

By the way, may I make a comment on your example POM? It's dangerous to assume that the output of your build is in ${basedir}/target - sometimes it isn't, for example if you want to use certain code coverage analysers. These fork off a modified lifecycle to compile the instrumented code in a temporary target area. Much safer to use ${project.build.directory}.

Sam Bloomquist said...

Very helpful; just what I was looking for. Thanks!

CyberNomad said...

Actually, in your case, you do not need to explicitly add the cxf generated source code to Maven2 source. The codegen is performed in phase generate-sources, which will tell Maven2 to add the generated source to the sources to compile.

Rickard.Lundin said...

Cybernomad does maven really automaticly finds generated sources under /targ/generated-sources/MYPLGIN/

?

Wilem said...

Thanks a lot, just what I needed.

Disgruntled Dave: said...
This comment has been removed by the author.
Doha ROUAS said...

hi,

thanks a lot. that was really helpful.

however, it doen't seem to work if we want to generate javadoc or checkstyle report..

have any idea plz?

thanks in advance

h said...

This is exactly what I was looking for. Thanks for sharing.

James Kingsbery said...

I found this article very helpful! Thank you.

Franck Garcia said...

Thanks, I've just copy and paste your code.

Dietrich Schulten said...

A sidenote: the directory layout convention for generated sources seems to be generated-sources/[plugin prefix], not generated/src...

See http://www.mail-archive.com/users@maven.apache.org/msg30636.html.

Martin Gladdish said...

Thanks!

Parminder Singh said...

This was very helpful. Thanks!