Imagine you are working on a project where you use some Java code generated from a tool.
For the moment, you generate the code and integrate it yourself to the project:
How would you automate this code generation step in your Maven build?
1. Create a separate Maven project where you will package the result of the code generation.
We package the result of the code generation in a separate JAR. Therefore, we need a different project structure.
We create a parent project with two child Maven modules. One with the original code, the other where the generated code will be located.
The parent POM looks like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.clempinch</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.clempinch</groupId> <artifactId>sample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.clempinch</groupId> <artifactId>generated-code</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
2. Automate the code generation in Maven.
If a Maven plugin is not already provided to generate the source code, then you can probably use the Exec Maven plugin to do the job.
Here is the pom.xml
of the code generation project (we assume you generate the code via a Java application – hence the use the exec:java
plugin).
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.clempinch</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.clempinch</groupId> <artifactId>generated-code</artifactId> <dependencies> <!-- For generating source code --> <dependency> <groupId>com.clempinch</groupId> <artifactId>some-generation-jar</artifactId> <version>1.0.0</version> <scope>runtime</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <executions> <execution> <id>generateCode</id> <phase>generate-sources</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.clempinch.generation.MainClass</mainClass> <classpathScope>runtime</classpathScope> <sourceRoot>${project.build.directory}/generated-sources/main/java</sourceRoot> </configuration> </execution> </executions> </plugin> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>build-helper-maven-plugin</artifactId> <executions> <execution> <id>addtoSourceFolder</id> <goals> <goal>add-source</goal> </goals> <phase>process-sources</phase> <configuration> <sources> <source>${project.build.directory}/generated-sources/generation_place</source> </sources> </configuration> </execution> </executions> </plugin> </plugins> </build> </project>
3. Add the dependency to your initial project.
The pom.xml
of the initial project needs to add a dependency to the generated-code JAR package:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.clempinch</groupId> <artifactId>myproject</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <groupId>com.clempinch</groupId> <artifactId>sample</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <dependency> <groupId>com.clempinch</groupId> <artifactId>generated-code</artifactId> <version>0.0.1-SNAPSHOT</version> </dependency> </dependencies> </project>
4. Build the project from the parent POM.
mvn clean install
Now everything should be done automatically: the code generation and the build of the project.
I have a different approach:the code I generate belongs in the module it is now, so I will not create a different module.
Still, it is generated code, and as such, should be in the target folder. I therefore create a target/generated-sources folder to include it into. You then need to add this folder as a source folder to your Eclipse project, to make sure it will not complain about the missing classes.
I think you do not even need special configuration in your POM for the sources in that folder to be compiled, it might be a default. But I might be wrong, and I am willing to check some of my POMs if that approach suits you.
(this is actually something I am eager to apply in the project I joined lately, since we have Java sources generated from XSD schemas among others, and which are versioned inside the src folder… :s )
Hi Cyrille,
Glad to know that my blog is read by you :-)
Actually, you might be right and we may not need to have this special separate project for the generated sources… However, with my approach, you do not need to add the target/generated-source as source folder in Eclipse… I also find a bit clearer to have what is generated in a separate project, at least it is what I thought in the use case I had.
Are you using JAXB for the project you talk about? In that case, a Maven plugin may already do everything for you.