Reputation: 3068
I'm working on a Maven plugin for JCasGen, which takes an XML type system description file and generates some Java classes. The type system description file often points to other type system description files in the same project via the classpath. JCasGen therefore needs a classpath containing all the XML type system description files in order to run. (These XML files must also be placed in the project's final jar file because Java code may refer to them via the classpath too.)
The XML files are in src/main/resources
so that Maven will copy them over to target/classes
and they will be included in the project's jar file. So the natural classpath to give to the plugin would be target/classes
. However, if my plugin runs at the intuitive generate-sources
phase, then the XML files in src/main/resources
will not yet have been copied to target/classes
, and JCasGen will fail.
So how do I structure things so that I can give the right classpath to JCasGen?
Here are a couple things I've thought of, but I don't really know whether they make sense:
Run the plugin on the process-resources
phase, and just use target/classes
for the classpath. This is what I'm currently doing and it seems to work. (I was worried about ensuring that my plugin always runs after the standard Maven copying of resources, but that seems to be what happens by default.) The main problem with this approach is that process-resources
is not the intuitive phase for a plugin that generates sources.
Build a classpath by concatenating the resource directories and target/classes
:
StringBuilder classpath = new StringBuilder();
for (Resource resource : this.project.getBuild().getResources()) {
classpath.append(resource.getDirectory());
classpath.append(File.pathSeparatorChar);
}
classpath.append(this.project.getBuild().getOutputDirectory());
I tried something like this and it seemed to work, but I worry that this could fail for complicated resources with includes or excludes.
Upvotes: 1
Views: 1616
Reputation: 3068
Just run the plugin on the process-resources
phase. This solution is used by other plugins that generate sources and require access to the classpath:
Note though that to get the classpath you should use project.getCompileClasspathElements()
, not project.getBuild().getOutputDirectory()
. The former will make sure you get, e.g. the target/classes
directories of projects on which the current project depends.
Upvotes: 1
Reputation: 48055
Create a multi module project where the first module just copies the xml files into a jar. The second module uses that jar as input and execute the plugin.
. ├── pom.xml ├── xml | ├── pom.xml | └── src | └── main | └── resources | └── com | └── stackoverflow | ├── package1 | | └── FirstClass.xml | └── package2 | └── SecondClass.xml └── gen └── pom.xml
pom.xml
<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>
<groupId>com.stackoverflow</groupId>
<artifactId>Q12682078</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<name>${project.artifactId}-${project.version}</name>
<modules>
<module>xml</module>
<module>gen</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.stackoverflow</groupId>
<artifactId>Q12682078-xml</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
xml/pom.xml
<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.stackoverflow</groupId>
<artifactId>Q12682078</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Q12682078-xml</artifactId>
<name>${project.artifactId}-${project.version}</name>
</project>
gen/pom.xml
<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.stackoverflow</groupId>
<artifactId>Q12682078</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>Q12682078-gen</artifactId>
<name>${project.artifactId}-${project.version}</name>
<dependencies>
<dependency>
<groupId>com.stackoverflow</groupId>
<artifactId>Q12682078-xml</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<!-- your plugin that now has the xml files in the classpath -->
</plugin>
</plugins>
</build>
</project>
Upvotes: 1
Reputation: 29897
I don't fully understand your question and I'm adding this as an aswer to be able to format it properly (so please don't vote unless it's of actual use!).
I do know that your plugin should run during the generate-sources phase: it's the correct phase, full stop :).
The maven standard says that generated code should go under target/generated-sources/, for example the jaxb2 plugin puts the files under target/generated-sources/jaxb and maven adds this folder automatically during compilation.
I suggest you to look at the jaxb2 plugin to find some guidance.
Upvotes: 1