I have a Maven project where I want to have two build artifacts:
The jar file containing the compiled Java source.
A folder containing a number of .properties file.
How can I setup my Maven project to do this? And then, once I've done this, how can I consume them up the dependency graph?
Add a copy-resources goal of the Maven Resources Plugin to your POM.
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-property-files</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/property-files</outputDirectory>
<resources>
<resource>
...
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>
I can't understand what you mean exactly by "consume them up the dependency graph".
Related
I am using maven for build, downloading war from artifactory and in src/main/webapp/WEB-INF/ folder customized one of the file but in target//WEB_INF/ the file is not overwriting with the customized file in the final war.
I used true in maven resources plugin.
EG:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy-app</id>
<!-- <phase>process-resources</phase> -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.artifactId}-${project.version}/WEB-INF</outputDirectory>
<resources>
<resource>
<directory>src/main/webapp/WEB_INF</directory>
<includes>
<include>app.xml</include></includes>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
First run mvn clean which will remove target, and then run mvn install should create artifact with latest changes.
if mvn clean is not removing target folder, check if there are any access issues
I have a war file with application.properties in default resources. I want to, when deploying on Tomcat, put these properties into an external folder like /webapps/example, not /webapps/namewar.
Can I configure my Maven or do something to achieve that?
Thank you so much.
You can use maven-resources-plugin's copy-resources goal to copy a file from your source tree to some directory. You need to add something like the following to your pom.xml:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- you may want to choose another phase -->
<!-- see https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html#Lifecycle_Reference -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- outputDirectory can be absolute or relative to ${basedir} -->
<outputDirectory>/webapps/example</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory><!-- or whereever your application.properties reside -->
<includes>
<include>application.properties</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>
Is there any way to share resources between modules of a parent project in Maven? For example, I would like to specify one log4j.properties file for all the modules in a multi-module Maven project.
Generally, I use Eclipse IDE to create the parent project by choosing a general project and then convert it to a Maven project by specifying a packaging of pom. This creates a "clean" project structure without src and etc. folders. I wonder where such a shared resource should be put in this case.
EDIT1: I would like to put the common resources in the parent project.
I'd create one additional "base" module (project), packaging "jar", that contains the common resources in src/main/resources. Then I'd make the other modules depend on that project. Now they see the common resources on their classpaths.
Antoher possibility is to use a remote resource bundle. You would be able to configure it in the parent project. In this example I wanted to copy some files just for tests. If you use this you will need to create the bundle in another project.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
<version>1.5</version>
<configuration>
<resourceBundles>
<resourceBundle>es.sca:myBundle:1.0.0</resourceBundle>
</resourceBundles>
<attachToMain>false</attachToMain>
<attachToTest>true</attachToTest>
<appendedResourcesDirectory>${basedir}/src/test/resources</appendedResourcesDirectory>
</configuration>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
</execution>
</executions>
</plugin>
Another way, put in your project root pom:
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<!-- don't propagate to child poms -->
<!-- this will only execute in root pom -->
<inherited>false</inherited>
<configuration>
<descriptors>
<descriptor>assembly.xml</descriptor>
</descriptors>
<!-- don't add classifier -->
<appendAssemblyId>false</appendAssemblyId>
</configuration>
<executions>
<execution>
<phase>initialize</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
<plugins>
And example of assembly.xml
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
<id>resources</id>
<formats>
<format>jar</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<fileSets>
<fileSet>
<directory>${project.basedir}/resources/</directory>
<outputDirectory/>
<useDefaultExcludes>true</useDefaultExcludes>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
Assembly plugin will generate artifact and attach it to current reactor, so it will be installed and deployed.
No you can use it as standard dependency event in the same pom.
Important is to trigger assembly (proper phase) before another plugin which will use generated artifact.
Eg. You can have in your root pom, bellow configuration will be propagated to all your module:
<plugin>
<artifactId>some-maven-plugin</artifactId>
<executions>
<execution>
<phase>verify</phase>
<goals>
<goal>goal</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>your.project.groupid</groupId>
<artifactI>your.project.artifactId</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
</plugin>
You can see this method in project:
https://github.com/s4u/pgp-keys-map resources directory is shared by all module.
Yes, it seems as a possible solution. But I was interested whether it
is possible to specify these resources in the parent project (without
introducing additional module) since the parent project specifies all
the common dependencies and Maven configurations for the child
modules, I think that the parent project is the most suitable place
also for the common resources.
In case of packaging type pom , when goal package specified to manage your shared resources, just add next (check folders) into build section of pom file :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-config-files</id>
<phase>package</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/logconfig</outputDirectory>
<resources>
<resource>
<filtering>false</filtering>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
I think you can just add the resources and/or testResources elements to your pom.
E.g. to access an additional test resource directory add:
<testResources>
<testResource>
<directory>src/test/resources</directory>
</testResource>
<testResource>
<directory>../global/src/test/resources</directory>
</testResource>
</testResources>
see Maven - Override test resource folder
I managed it to work like this:
I create a project/assembly/test/resources/META-INF/persistence.xml file, and add this to my pom.xml:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-test-persistence-xml-resources</id>
<phase>process-test-sources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>src/</outputDirectory>
<resources>
<resource>
<directory>${project.parent.basedir}/assembly/</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
According to maven-war-plugin FAQ,
If you can't move the classes to another project, you can deploy the classes and resources included in your webapp as an "attached" artifact, with a classifier, by using the following configuration:
<project>
...
<artifactId>mywebapp</artifactId>
<version>1.0-SNAPSHOT</version>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<attachClasses>true</attachClasses>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
This will result in two artifacts being deployed: mywebapp-1.0-SNAPSHOT.war and mywebapp-1.0-SNAPSHOT-classes.jar.
Is there any way possible that I could get mywebapp-1.0-SNAPSHOT.jar instead of mywebapp-1.0-SNAPSHOT-classes.jar?
Update: :
I want both war as well as jar to be generated. Though I am able to do this by applying profiles as mentioned in Changing packaging based on active profile in pom. But I am curious to know about above question.
Short answer: no, you can't.
By looking at the maven-war-plugin sources, in WarMojo.java (line 292), you can see that you cannot meet your requirement by simply modifying the maven-war-plugin configuration:
protected static File getTargetFile( File basedir, String finalName, String classifier, String type )
{
if ( classifier == null )
{
classifier = "";
}
else if ( classifier.trim().length() > 0 && !classifier.startsWith( "-" ) )
{
classifier = "-" + classifier;
}
return new File( basedir, finalName + classifier + "." + type );
}
Since the classesClassifier parameter is "classes" by default, you have no chance to modify this behavior: classifier will never be null.
Either you rename the file after its generation, or you modify the source code of the maven-war-plugin, and use it as a custom plugin.
As a final consideration, it is not advisable to have a null classesClassifier: it could be misleading. I do not know your project requirement though.
Hope it helps.
The closest approach to what you want to do is to use <classesClassifier>
as
<project>
...
<artifactId>mywebapp</artifactId>
<version>1.0-SNAPSHOT</version>
...
<build>
<plugins>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<attachClasses>true</attachClasses>
<classesClassifier>someClassifier</classesClassifier>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
but this approach will always put the classifier as your_jar-classifier.jar and if you create and empty or spaced tag, it will default to -classes
On the other hand, by using archiveClasses instead of attachClasses you will find the JAR just as you want it inside war's WEB-INF\lib (without the classifier), but no WEB-INF\classes will be generated.
Try to configure your webapp's pom.xml using the following <build> section, to see if it fits your needs :
...
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>create-jar</id>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>attach-jar</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}.jar</file>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
...
This section asks Maven to explicitly create a jar, then it attaches the created jar to the build so that the install phase can copy the generated artifact into the local repository.
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<archiveClasses>true</archiveClasses>
</configuration>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>attach-jar</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.build.directory}/${project.build.finalName}/WEB-INF/lib/${project.build.finalName}.jar</file>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
Combining some of the ideas mentioned above seems to work for me. The <archiveClasses> (as explained here) causes the required JAR to be generated within the WAR file and the attach-artifact goal extracts that file as an artifact.
Maven's general philosophy is that one POM generates one artifact. That would mean the cleanest, most "Maveny" way to get the Jar out of your project is to separate your Java code and the Webapp items into two modules grouped together by a parent project.
So a potential project hierarchy could be:
mywebapp-parent/ -> Contains all dependency info, project version
mywebapp/ -> Creates Jar
mywebapp-web/ -> Depends on mywebapp, Creates War
I have a maven project which uses wsgen to generate XSD files from the compiled java classes.
The problem is that I want to add the generated files to the jar as resources. But since the resource phase runs before the process-classes phase, I can't add them.
Is there a way to tell maven to add additional resources that were generated at the process-classes phase?
I would suggest to define the output directory for the XSD files into target/classes (may be with a supplemental sub folder which will be packaged later during the package phase into the jar. This can be achieved by using the maven-resources-plugin.
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>3.0.2</version>
<executions>
<execution>
<id>copy-resources</id>
<phase>process-classes</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
<resources>
<resource>
<directory>${basedir}/target/xsd-out</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>
You need to take care that the resources plugin is positioned after the plugin which is used to call the wsgen part. You can also use the prepare-package phase instead to make sure the resources will be correctly packaged.