Maven shade plugin adding dependency-reduced-pom.xml to base directory - java

The maven shade plugin is creating a file called dependency-reduced-pom.xml and also artifactname-shaded.jar and placing them in the base directory.
Is this a bug? Should be in the target directory. Any workaround?

You can avoid having it created by setting createDependencyReducedPom to false.
e.g.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>${maven-shade-plugin.version}</version>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
</configuration>
....
....
</plugin>
See more detail from apache

Based on bmargulies' answer and his comment on Xv.'s answer, I decided to configure the dependency-reduced POM to be output to target/, which is already ignored in my VCS.
To do that, I just added the dependencyReducedPomLocation element to the configuration element of the plugin, i.e.
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
(...)
</configuration>

See https://issues.apache.org/jira/browse/MSHADE-121, and also https://issues.apache.org/jira/browse/MSHADE-124.
There is an option to move the d-r-p to elsewhere, but you may not like the consequences.
You are wrong about the -shaded jar, it always ends up in target/ unless you move it elsewhere.

You could use an old version of the plugin. Version 1.7 of the maven-shade-plugin writes to /target.
Since version 1.7.1, dependency-reduced pom.xml is written to basedir. See the issue MSHADE-124 for some reasons why it was done and what the consequences are. If you try setting dependencyReducedPomLocation, you will likely run into problems generating the site - open issue MSHADE-145.

the documentation on http://maven.apache.org/plugins/maven-shade-plugin/shade-mojo.html is incorrect when it says:
createDependencyReducedPom boolean - Flag whether to generate a
simplified POM for the shaded artifact. If set to true, dependencies
that have been included into the uber JAR will be removed from the
section of the generated POM. The reduced POM will be
named dependency-reduced-pom.xml and is stored into the same directory
as the shaded artifact. Unless you also specify
dependencyReducedPomLocation, the plugin will create a temporary file
named dependency-reduced-pom.xml in the project basedir. Default value
is: true.
the dependency-reduced-pom.xml is not stored in the same directory as the shaded artifact (target directory) ... it is in fact generated in the base directory, not target

To ignore the file you can add it to the ignore directive for your DVCS. For git, a .gitignore file is created with contents:
dependency-reduced-pom.xml
You can also add it to maven-clean-plugin configuration so it's blown away during the clean lifecycle phase: (Below assumes defaults, such as version, are defined in the POMs pluginManagement section.)
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<configuration>
<filesets>
<fileset>
<directory>.</directory>
<includes>
<include>**/dependency-reduced-pom.xml</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
Note that the above configuration is additive to the non-customized clean default.

Related

Maven delete resources after testing

I recently read you can have a logback.xml and a logback-test.xml in your classpath, where the test file has higher priority.
Logback tries to find a file called logback-test.xml in the classpath.
If no such file is found, logback tries to find a file called logback.groovy in the classpath.
If no such file is found, it checks for the file logback.xml in the classpath..
Source
So I thought it would be a great idea letting logging happen in the console while testing and log to a file after buildung with maven (without having to change the output manually).
I found the maven-resources-plugin, which can <exclude> some resources. I specified test files (like logback-test.xml) like this in the plugin:
pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>test/**</exclude>
<exclude>*test*</exclude>
</excludes>
</resource>
</resources>
</configuration>
</plugin>
Which works great, but has one problem. I definitely need access to the *test* files (yes, also logback-test.xml, so I cannot just exclude only it instead of the wildcard *test*) and the test/** directory during tests. I only want to exclude/delete them after testing is complete. With this configuration the excluded resources are never copied, but I want them to the copied first (to make them accessible by tests) and then (after tests run successfully), delete them.
How can I achieve this? I've been lookung for a "maven delete plugin" but couldn't find any.
Things are much simpler.
Maven separate sources/resources for the packaged application and sources/resources for the execution tests.
Simply move logback-test.xml in the src/test/resources folder.
And place logback.xml in src/main/resources.
In this way, logback-test.xml will be available during the tests of your build.
And as the file is located in src/test/resources, it will never be included it in your application.
While the packaged application will contain and use only logback.xml as defined in src/main/resources.
I found my own solution.
Delete the maven-resource-plugin. Instead, based on your packaging, use maven-jar-plugin or maven-war-plugin which is responsible for building the jar or war file (and runs later, after the tests).
jar
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<excludes>
<exclude>test/**</exclude>
<exclude>*test*</exclude>
</excludes>
</configuration>
</plugin>
war
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<packagingExcludes>${webdir}/test/**,${webdir}/*test*</packagingExcludes>
</configuration>
</plugin>
where webdir is the path to your classpath root from the built war file. You can add it to your <properties> tag (directly under the <project> tag). In my case it is WEB-INF/classes.
pom.xml
<properties>
<webdir>WEB-INF/classes</webdir>
</properties>

Copy a file during maven build phase

My situation is:
I have a Maven project, I have my java classes in /app/src/main/java, my resources in /app/src/main/resources and my webapp files in /app/src/main/webapp
I have a javascript file in /common/script.js
Now what I want is to include (copy) the javascript file to the war file during the build phase of maven. To be precise, I want the script.js to land in /js/ directory of the war archive, just as it was placed in /app/src/main/webapp/js before starting the build.
I need this to share one version of resource files among many web-apps.
Kind regards,
Q.
You could do something like this, as documented here.
<project>
...
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1.1</version>
<configuration>
<webResources>
<resource>
<!-- this is relative to the pom.xml directory -->
<directory>../common</directory>
<targetPath>/js</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
You can use the mojo copy-resources to copy resources which are not in the default maven layout or not declared in the build/resources element.
Check
"maven-resources-plugin"
You can use maven-resources plugin to copy a file to the desired location. Before or after a war has been built

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.

How do I add an extra source directory that will be used by the maven-jxr-plugin?

I'm using the build-helper-maven-plugin to add it to my build, but I'd
like to see the XREF source for this extra source directory as well.
FYI:
maven-jxr-plugin - The JXR plugin produces a cross-reference of the project's sources. The generated reports make it easier for the user to reference or find specific lines of code. It is also handy when used with the PMD plugin for referencing errors found in the code.
build-helper-maven-plugin - This plugin contains various small independent goals to assist with Maven build lifecycle.
You can tell JXR what files to index using a file pattern, following Ant guidelines. For example, to include all java files in src/main/java and all source in src/main/java2, the following configuration in your file should work:
<project>
...
<reporting>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
<configuration>
...
<includes>
<include>src/main/java/**/*.java</include>
<include>src/main/java2/**/*.java</include>
<includes>
...
</configuration>
</plugin>
</plugins>
...
</reporting>
...
</project>
The problem I was having was related to the order of the plugins in the pom.xml.
When I moved the jxr plugin to the top of the plugin list everything started working.
Crazy stuff.

Categories

Resources