Adding file to jar during maven build - java

I am trying to add a license file to all of my jars when executing a maven build. I have the license on each class file, but I am looking to add License.txt to each META-INF folder within each jar
My project has a master pom, which has half dozen modules, those modules then have modules of their own, and eventually get to a project that generates a /target/<.jar-file>. The build and the class level licenses are working, I am just looking to add a physical License.txt into the META-INF folder.
My file is stored (relative to the master POM) in /src/resources/src-license.txt. I really need the automated method to ensure that if/when the license changes, I dotn have to update 50 files, I can just update the one, which is then copied out to the other locations.
I have tried using
<build>
<sourceDirectory>src</sourceDirectory>
<resources>
<resource>
<directory>src/resources</directory>
<targetPath>/META-INF</targetPath>
<includes>
<include>src-license.txt</include>
</includes>
</resource>
</resources>
....
</build>
But that doesnt seem to do the trick. I have also tries some alternatives to the output path, such as ${project.build.outputDirectory}/META-INF, or */META_INF, also to no avail. Does anyone have some experience on how to accomplish this? Thanks
Also, I use the maven-license-plugin to ensure that each class file has the license info pasted into it, and that functions as intended. But again, that inside the class files, I am looking for an external .txt file in each <*.jar>/META-INF/

Using resources from parent relativePath is at least difficult (what if you have a complex directory structure?).
A simple and clean way can be to create a separate module containing your src-license.txt file. Then make it a dependency of your modules and unzip it (dependency:unpack-dependencies) # generate-resources phase, inside target/classes.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>unpack-license</id>
<phase>generate-resources</phase>
<goals><goal>unpack</goal></goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.acme</groupId>
<artifactId>com.acme.license</artifactId>
<version>${project.version}</version>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.outputDirectory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>

Related

java load a file from a folder but the project is a module

I have a maven project parent project that contains 5 modules.
the public static main is located in the first module.
the first module calls the fifth module. the fifth module loads a file from a folder. the hiracicy of all everything together are:
module1
module2
module5
config(this folder)
plugings.xml (this file)
in the fifth modules, i want to load the plugins.xml, i do here:
String configPath = System.getProperty("moquette.path", null);
File filePluginsConfiguration = new File(configPath,
"config/plugins.conf");
if (!filePluginsConfiguration.exists()) {
LOG.warn(String
.format("parsing not existing file %s, so fallback on default plugin configurations!",
filePluginsConfiguration.getAbsolutePath()));
i know know it is no correct, because moquette.path is points to a diffirent folder. but i don't know how can i point it to my plugins.xml file
could you help please
You can do it by copying the module5 config folder into your classpath.
In Maven, you can use maven-resources-plugin to do it:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>copy-resources</id>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target/extra-resources</outputDirectory>
<resources>
<resource>
<directory>module5/config</directory>
<filtering>false</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
In some cases, a file in the classpath is more useful and modular than a file 'in the file system'.
Place the file in `src/main/resources/some/package/plugins.conf', then use the Guava resources class to access it (there is a more verbose straight JRE alternative).
URL url = Resources.getResource("/some/package/plugins.conf");
String text = Resources.toString(url, Charsets.UTF_8);
Or get a stream or a reader with other methods of the Resources class. In any case, the file can 'live' in module (a) and be consumed in module (b).

maven copy a particular dependency jar to a specific directory in the .war file

I am trying out a Simple Java Web Start project based on the Oracle Tutorial. I am using maven to package it as a webapp and deploy it to application server. The full source code is available here
https://github.com/KiranMohan/dynamic-tree-javaws-sample-project
The maven project structure is like
parent
|--lib
|--webapp
The webapp module is a maven war module. It is required to package lib.jar at the root of webapp.war. NOT under WEB-INF/lib.
How to achieve this in maven?
I found that the right way to do this is to use the maven-dependency-plugin.
Since "lib.jar" is not used in the compile phase of "webapp" module, it is only a package time dependency. Using maven-dependency-plugin, I can copy lib.jar to any required directory during the prepare-package phase. The maven-war package would then include the lib.jar in the .war package.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>prepare-package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>[ group id ]</groupId>
<artifactId>[artifact id]</artifactId>
<version>[ version ]</version>
<outputDirectory>${project.build.directory}/${project.artifactId}</outputDirectory>
</artifactItem>
</artifactItems>
<!-- other configurations here -->
</configuration>
</execution>
</executions>
</plugin>
Update:
There is a webstart-maven-plugin that does a better job of packaging javaws applications. See my sample project
https://github.com/KiranMohan/dynamic-tree-javaws-sample-project
for details
Well how i said in the comments for sake of readability here is a part of the answer:
Since Maven will always store the dependencies of a web project under its WEB-INF/lib folder by default i (i am no Maven expert ...) would try to place my lib.jar inside the /target folder of the project before the phase package is executed.
NOTE: I havent tried it out so you will have to adjust the paths - expecially the output path so your lib.jar is placed properly to be packed into the root of the war (e.g. if you open your war there will be a lib.jar next to folders such as WEB-INF).
<!--
lets assume the root of my project would be under C:/devjba/projectX this equals the maven
variable ${project.basedir}.
from there the output-directory would be located under C:/devjba/projectX/target which equals the
maven variable ${project.build.directory}. This is the location a .war would be placed in after
the build
lets assume the required jar lib.jar is located under C:/devjba/projectX/misc which would equal to
the expression: ${project.basedir}/misc
-->
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>foo</id>
<!-- may adjust to another phase before package but make sure your plugin is bound to a phase
because otherwise it wont be invoked during build! Now its bound to the first phase of the
default lifecycle for packaging type war -->
<phase>process-resources</phase>
<goals>
<!-- use the copy-resources goal of this plugin - it will copy resources :) -->
<goal>copy-resources</goal>
</goals>
<configuration>
<!-- this points to /target of the current project, you may adjust it to wherever it must be placed to be packed into the root of the war (just try&error) -->
<outputDirectory>${project.build.directory}</outputDirectory>
<resources>
<resource>
<!-- this points to a folder /misc under the project root where we expect the lib.jar -->
<directory>${project.basedir}/misc</directory>
<!-- unless you specify what to include anything of the above directory will be included -->
<includes>
<include>lib.jar</include>
</includes>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
As i said i have no experience in signing JARs at all but there is a plugin called maven-jarsigner-plugin which i guess will do the job (i would sign it, then move it, then package the war) with a manual - i recomend you try to configure it according to my "example configuration of the maven-resource-plugin and post a new question directly containing your two plugin configurations. Dont forget to link to this question in that case. And also leave this question open so someone with a better approach may correct my way).

Maven web resources question

I have a Maven web project and I have some CSS and Javascript files under the src\main\webapp\ folder. I constantly make changes to those files and would like to see my changes quickly. If I run maven install, it takes ages due to project dependencies. Sometimes all I want to change is one line of code in my CSS file and do not want to recompile everything else. I have a maven plugin that publishes my output war file to my JBoss instance. Ideally, I would like to run a maven execution script that will quickly copy my web resources to the output folder and reploy the changed war file without recompiling everything else.
I tried invoking the generate-resources goal but that doesn't seem to look in the src\main\webapp directory as it is expecting my resources to be under the src\main\resources folder. What am I missing here?
Thanks
If you want to add more resources to be copied during the generate-resources plugin, you can change the resources folders used by your build. The project.build.resources property controls which folders are searched for resources. You could add:
<project>
...
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
<resource>
<directory>src/main/webApp</directory>
<includes>
<include>*.css</include>
<include>*.js</include>
You would then run mvn resources to copy the files.
This approach is that these files will always be copied during the resources phase of any build. You can get around this by using the copy-resources goal instead of resources. In this case you would use the following configuration:
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.5</version>
<executions>
<execution>
<id>copy-web-resources</id>
<!-- here the phase you need -->
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/webApp</outputDirectory>
<resources>
<resource>
<directory>src/main/webApp</directory>
<includes>
<include>*.css</include>
<include>*.js</include>
You could then run mvn resources:copy-resources to copy the files.
I think you could accomplish this by using the war:war goal. This should generate a war file in the output folder for you without re-compiling the source.

Having Maven2 copy resources to the build directory, but NOT bundle them in the JAR

I've started a new Maven project in NetBeans, accepting all the defaults. The POM, with all the JAR dependencies stripped out, is cut-n-pasted at the bottom of this question.
The application reads in various properties files (e.g. logging and config). It also reads in external resources such as fonts, images, and sounds. I do NOT want all these resources to be bundled up into the JAR file. Instead, I plan to deploy them in subdirectories beneath the directory where the JAR is deployed.
A simplified view of the project's directory structure looks like this:
-src
|---main
|---java
|---com.mypackage, etc
|---resources
|---conf
|---fonts
|---images
|---sounds
+target
What I would like to have after a clean build would look like this:
+src
-target
|---myproject-1.0.0.jar (compiled contents of "src/main/java" ONLY)
|---conf
|---fonts
|---images
|---sounds
However, when I do a "clean-and-build" or an "exec" through NetBeans (or the command-line for that matter)... what I'm actually getting looks like this:
+src
-target
|---classes
|---("src/main/java" and "src/main/resources" slammed together)
|---myproject-1.0.0.jar (the "classes" subdirectory JAR'ed up)
Can someone point me in the right direction for getting that first result rather than the second? I apologize if this is a silly question (I'm a Maven rookie), or if I overlooked a previously-asked duplicate. However, from the searching I've done on Stack Overflow... it looks like all the duplicate questions try to go the other way! (i.e. get resources into a JAR rather than keep them out)
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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>steveperkins</groupId>
<artifactId>myproject</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>My Project</name>
<url>http://maven.apache.org</url>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.4</source>
<target>1.4</target>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
...
Although the proposed solutions would work they basically work around the maven conventions. A better alternative would be to filter out the resources so they are not included in the jar but still available as resources while working in the IDE. In the pom it should look like this:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<excludes>
<exclude>/conf/**</exclude>
<exclude>/fonts/**</exclude>
<exclude>/images/**</exclude>
<exclude>/sounds/**</exclude>
</excludes>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
This would effectively exclude them from the jar without any workarounds.
Here is the doc page for the jar plugin.
Though the above will answer your question may I suggest some additional possibility that could help you in your endeavour. As a second step, to still make these resources available you could package your project using the assembly plugin. this would allow you to create a zip file and place all the files, resources and jar, in an appropriate location so that when the zip is unpacked everything just falls into place.
If this project is part of a larger work you can still use the assembly plugin for each where you would have this situation and in the main project you could extract and reassemble them in a larger zip including all the necessary artifacts.
Lastly I suggest you leave the directory structure under target as-is. If you customize it it would be preferable to do it through the Maven variables so that the changes percolate to the other plugins. If you manually remove and rename stuff once Maven has gone through you may run into problems later. Normally the Maven jar plugin should be able to just get it right if you configure it the way you want so you have no needs to worry about what comes under target. Personally I use Eclipse and the pusign is pretty good at getting the IDE and Maven config in sync. For NetBeans I would suspect this would also be the case. If not the best approach would be to configure your project in NetBeans to use target/classes as a target folder for built artifacts and target/test-classes for stuff built from src/test/java.
Personally, I would not use the default location of resources but an "extra" location and configure the resources plugin to copy them where you want from there:
<project>
...
<build>
<plugins>
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>validate</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${basedir}/target</outputDirectory>
<resources>
<resource>
<directory>src/non-packaged-resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
...
</build>
...
</project>
If you insist with using the default location (src/main/resources), I think you'll have to configure some exclusions (see below) to avoid resources getting copied by default and then use the same approach as above.
Another option would be to use the AntRun maven plugin and Ant to move files but this is not really the maven way so I won't detail it.
Resources
Copy Resources
Including and excluding files and directories
You can sonfigure a special execution of resources:copy-resources goal.
Eugene is on the right track but there's a better way to make this work.
It should look something like this:
<build>
<outputDirectory>target/${artifactId}-${version}</outputDirectory>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3.1</version>
<configuration>
<classesDirectory>${project.build.outputDirectory}</classesDirectory>
<outputDirector>target</outputDirectory>
</configuration>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources/conf</directory>
<targetPath>../conf</targetPath>
</resource>
<resource>
<directory>src/main/resources/ANOTHER_PATH</directory>
<targetPath>../ANOTHER_PATH</targetPath>
</resource>
</resources>
</build>
You won't be able to get rid of the 'classes' directory, but you'll be able to give it a different name that shouldn't interfere with NetBeans.
You can find more about the <outputDirectory> element here.
You can find more about the jar plugin here.
You can find more about the <resource> element here.
As a side note, you may want to consider running Maven under a 1.6 JDK and fork the maven-compiler-plugin to use your 1.4 JDK for compiling. You can find out more about this here. That should give you a boost to your compile time. You can also tell surefire when running test cases to use the 1.4 JDK for execution as well.

How to change the default output from a Maven 2 / Cobertura instrument goal?

when i instrument my classes using Maven 2 using the command
mvn cobertura:instrument
The output (the instrumented classes) are put in \target\generated-classes. Is there a way to change the output location to \target\classes?
I checked the instrumentation tasks of the cobertura-maven plugin but this does not give me a solution sofar.
You have not said why you want to overwrite the default location, but I assume it is so that you can use the instrumented classes from another project, or perhaps include them in a web archive or something similar.
I added the following to my pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<id>instrumented-classes</id>
<goals>
<goal>jar</goal>
</goals>
<phase>package</phase>
<configuration>
<classifier>instrumented</classifier>
<classesDirectory>${project.build.directory}/generated-classes/cobertura</classesDirectory>
</configuration>
</execution>
</executions>
</plugin>
This makes maven generate an additional jar file called projectname-instrumented.jar
It is then possible to depend on this jar file from any other pom (including for example a web module) using
<depends>
<group>mygroup</group>
<project>projectname</project>
<version>1</version>
<classifier>instrumented</classifier>
</depends>
I did not test this 100% but have used similar mechanisms in the past
As far as I understand, the instrumented classes are only needed by cobertura for report generation. If you create them in target/classes, they will overwrite the original class files.
If you need the instrumented files in a jar as a result, you can configure the maven-jar-plugin to pick up the files from the target/generated-classes directory instead of or in addition to the files from the standard ${build.project.outputDirectory}.
Edit
Have a look at the maven-jar-plugin description. To only use target/generated-classes, the following addition to your POM should work - try it and modify it to your needs:
<project>
...
<build>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.3</version> <!-- replace with correct version nbr! -->
<configuration>
<includes>
<include>${project.build.directory}/generated-classes/**/*.class</include>
</includes>
<excludes>
<exclude>${project.build.directory}/classes/**/*.class</include>
</excludes>
</configuration>
</plugin>
...
</plugins>
</build>
...
</project>
${project.build.directory} points to your target folder, ${project.build.ouputDirectory} to target/classes. I do not know if you can simply set ${project.build.ouputDirectory} to a new value - have a look at the this chapter of the maven book, maybe you find some hints
Edit 2
Alternativly or additionally you can use maven to copy the files from target/generated-classes to target/classes after coberture:instrument has finished. This question has one answer with an example POM (fragment), you just have to identify the correct phase (process-resources is definitely too early for your case)
Did you try "mvn cobertura:instrument install"? It will generate a jar file including all the cobertura version classes.
If you want to change back original version, just run the command without "cobertura:instrument".
I just implemented the solution proposed by Andreas_D, modified my pom and uses the maven-resources-plugin. So on some stage of my build the Cobertura generated files are copied to the /target/classes directory.
You can configure it using <classesDirectory>[Your DIR]</classesDirectory>
In cobertura-maven-plugin version 2.4 this is still not supported. I've just created an improvement ticket, patch is attached to the ticket.

Categories

Resources