Best practice for packaging resource files and classes with Maven - java

Currently I have a sample maven project with the following build part where I specify a second resource location directory:
<project>
...
<build>
<resources>
<resource>
<directory>src/main/second-resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<finalName>${artifactId}</finalName>
<outputDirectory>${jarBuildPath}</outputDirectory>
</configuration>
</plugin>
</plugins>
</build>
</project>
I can get my jar packaged with this configuration having my classes and resource files just in right place and with no issue.
But when adding the property <classesDirectory> to my maven-jar-plugin configuration snippet with value src/main/java:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<classesDirectory>src/main/java</classesDirectory>
<finalName>${artifactId}</finalName>
<outputDirectory>${jarBuildPath}</outputDirectory>
</configuration>
</plugin>
then when packaging my archive, hell, my resource files are no longer there.
From maven official documentation for the classesDirectory property, it says that Directory containing the classes and resource files that should be packaged into the JAR. and that makes all sense for me and it is quite fair that my resource files get disappeared since maven assumes that no file has the right to be packaged unless it is under src/main/java.
But my big thought was when specifying my resource files location (with one of the options below), Maven will be aware of the files location even if I had specified the <classesDirectory> entry.
With top level <resources> entry
<resources>
<resource>
<directory>src/main/second-resources</directory>
</resource>
</resources>
or via the maven-resource-plugin
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<configuration>
<resources>
<resource>
<directory>src/main/second-resources</directory>
</resource>
</resources>
</configuration>
</plugin>
I can tell you that I'm quite familiar with maven but this issue seemed weird for me: Is it not recommended to have in maven-jar-plugin when you have a some custom resource directory?
Can anyone kindly drop some light on this?
BR.

The classesDirectory is the directory where
the compiler plugin stores compiled java classes
the resources-plugin copies resources to be included in the file
created by the jar-plugin.
You have changed it to your java source code directory in the jar-plugin configuration.
Therefore, I imagine that your jar now only contains java source files.
Is this what you want, or are you just trying to include a second source of resource files?
If the latter, then just adding:
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/second-resources</directory>
</resource>
</resources>
should accomplish what you want without adding any configuration to the jar plugin. Note that the first <resource>..</resource> section is needed if you still have stuff you want in the default src/main/resources location.

Related

Log4j file not excluded from Maven build

I have a log4j.xml file in src/main/resources that I'm trying to exclude from the jar file. I have a property with version 3.0.0 in the parent pom file.
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>${maven-jar-plugin.version}</version>
<configuration>
<excludes>
<exclude>**/log4j.xml</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven-resources-plugin.version}</version>
<configuration>
<!-- specify UTF-8, ISO-8859-1 or any other file encoding -->
<encoding>UTF-8</encoding>
</configuration>
</plugin>
...
According to maven manual (https://maven.apache.org/plugins/maven-resources-plugin/examples/include-exclude.html), you have to put the files to include/exclude in resources section. So, if the file is located on src/resources, the configuration will be:
<project>
...
<name>My Resources Plugin Practice Project</name>
...
<build>
...
<resources>
<resource>
<directory>src/resources</directory>
<excludes>
<exclude>**/log4j.xml</exclude>
</excludes>
</resource>
...
</resources>
...
</build>
...
</project>
Hope that helps.
I upgraded to version 3.0.0 of the maven-jar-plugin and also changed the exclude back to "**/log4j.xml" from "src/main/resources/log4j.xml", which I had temporarily switched it to, so I'm not sure if one ore both fixes were required.
If you use <exclude>**/*log4j*</exclude> It should work if this pattern is acceptable for you.
Note what's written at the bottom of the doc: https://maven.apache.org/plugins/maven-jar-plugin/examples/include-exclude.html
Note that the patterns need to be relative to the path specified for the plugin's classesDirectory parameter.

Generating filtered resources from the maven sources:jar execution

I would like to generate a sources jar file for my project, so I have included the maven-source-plugin. However, I am also using the resource filtering plugin to set a version number in a property file for my project. When I generate a final jar file, the property file has been filtered and the version is set. However in the sources jar, is still has the unfiltered property. I would like for the sources plugin to also invoke the resource filtering. How can I do this?
Here is (part) of my pom.xml
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<sourceDirectory>src/main/java</sourceDirectory>
<testSourceDirectory>src/test/java</testSourceDirectory>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-release-plugin</artifactId>
<version>2.5.3</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
</plugins>
</build>
and here is the property file that I want filtered in
version = ${project.version}
EDIT
For clarification, the root of my issue is that I have another project that is a GWT project built using this library. Part of the requirements of a GWT project is that the source code has to also be made available for anything that is going to be compiled to client side javascript. Therefore, this project contains both the compiled jar and the sources jar in the classpath.
So there are now two properties files with the same package path and name, one exists in the compiled jar and one in the sources jar.
When I attempt to read this file, it seems to pick the properties file out of the sources jar, which has not been filtered.
Normally, you'd use the maven-source-plugin for this. However, I see in its documentation that you cannot remove src/main/resources from its processing, while simultaneously adding target/classes to its processing cycle (which is what you would need to do in order to accomplish your task)
Therefore, I think your best bet is through a maven-assembly-plugin configuration.

Leave FXML files in /src/main/java

Whenever I put FXML files into the /src/main/java catalog, it seems like they aren't being included into the final OSGi jar during compilation. I suppose Maven removes them from there because it thinks that FXML files should only reside in the /src/main/resouces catalog. Is there a way to stop Maven from doing this (i.e. just leave them there)?
EDIT 1
The only solution I have found for now is:
<build>
<plugins>
....
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>generate-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/classes/</outputDirectory>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.fxml</include>
<include>**/*.css</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
However, as far I understand, there is another, shorter way of achieving this, i.e. without the use of additional plugins, in the <build>...</build> node. How do I use the shorter method instead?
Yes by default src/main/resources is for resource files.
You can use maven resources plugin to override this behavior.
Here's an example. In your pom.xml
...
<build>
<resources>
<resource>
<targetPath>com/company/projectname</targetPath>
<directory>src/main/java/com/company/projectname</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
where <directory> is the source package which includes resource files(in your case xml files) and <targetPath> is the target where you want the resources to reside. You can omit <targetPath> if you are ok with having these resources in the root path of the jar.

Exclude a package from build path in POM

I have a package de.ht.ak.praktikum.hook in a project which is in a source folder src but it should be excluded from build path. I used to do this with right click on it and choosing Build Path -> Exclude. Since I added maven to the project every time I update the project the excluded folder turns into package again, i.e. the exclusion gets deleted. I tried to fix it this way:
...
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src</directory>
<excludes>
<exclude>de/ht/ak/praktikum/hook</exclude>
</excludes>
</resource>
</resources>
...
</build>
...
I tried also to do it as described there:
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>3.1</version>
<configuration>
<sourceExcludes>
<sourceExclude>de/ht/ak/praktikum/hook/</sourceExclude>
</sourceExcludes>
<sourceIncludes>
<sourceInclude>**/*.java</sourceInclude>
</sourceIncludes>
</configuration>
</plugin>
...
However none of the both methods help. Any ideas?
Your first attempt won't work because you're specifying to exclude it as a resource (i.e., those files that get packaged in your resulting JAR file - you don't usually want source files to be among them).
The second attempt is more on the right track. However, you want to exclude them from compilation, hence you need to set the exclude option of the maven-compiler-plugin. I.e., like this:
<build>
..
<plugins>
..
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.2</version>
<configuration>
<excludes>
<exclude>de/ht/ak/praktikum/hook/*.java</exclude>
</excludes>
</configuration>
</plugin>
..
</plugins>
</build>
When updating the project in Eclipse (Maven -> Update Project), Eclipse should honor this configuration and also exclude it from the Eclipse-internal build path.

Additional maven source folders such as src/main/javascript or src/main/css?

I've been developing a standard web app and its really annoying to have Eclipse show src/main/resources and src/main/java in such a convenient flat-package way, yet I have to frequently drill down into src/main/webapp and all its subdirectories to modify my css, js, and html files.
I've never seen a project use additional source folders for resources like those, but is it out of the question to try? Ideally I'd love to have a directory structure like
src/main/java
src/main/resources
src/main/jsp
src/main/javascript
src/main/css
Has anyone setup a project like this? Does it become more of a hassle to even try, breaking existing plugins and whatnot?
Add resource folders this way.
<project>
...
<build>
...
<resources>
<resource>
<directory>resource1</directory>
</resource>
<resource>
<directory>resource2</directory>
</resource>
<resource>
<directory>resource3</directory>
</resource>
</resources>
...
</build>
...
</project>
More information
However, if you want multiple web resources (WEB-INF directory in WAR file) than you need to configure Maven War plugin.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<resource>
<directory>src/main/jsp</directory>
</resource>
<resource>
<directory>src/main/javascript</directory>
</resource>
<resource>
<directory>src/main/css</directory>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>

Categories

Resources