Usage of the maven-shade plugin's AppenderTransformer - spring

Okay, I am running into the typical problem in which I need to create a uber jar, but my project dependencies has multiple spring.handlers and spring.schemas files. I have search around and figured out that my problem required me to use the maven-shade plugin, along with it's AppendingTransformer. The problem is that when I add the configuration and run the goal it does not merge the files; what's more, I can put a bogus classpath in for the appender or resource file and it does not complain, which lead me to believe that it is not even attempting to execute the transformer.
execute- mvn compile package shade:shade
<build>
<finalName>mongo-dictionary</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.7.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
</transformer>
<transformer
implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
<resource>META-INF/spring.schemas</resource>
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
</build>

I had my plugins configured as children of the pluginManagement element, once I got rid of the pluginManagement tag everything works as advertised.

where is this plugin configuration, can you ensure that it is in the right place - build -> plugins element of the project for which you are creating uber jar. I have the same configuration which works for me.
Also you don't need to execute shade:shade separately. Running mvn package will do that for you.

Related

How to package config.yml and resources in $project--0.0.1-SNAPSHOT.jar

I've a drop wizard project which has the following directory structure:
basedir
pom.xml
config.yml
src
main
resources
myresource.xml
The build portion of
<build>
<finalName>project-${version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>project-package.App</mainClass>
</transformer>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer">
</transformer>
</transformers>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
When I run my code from Eclipse, I use command as follows:
$mypackage.App server config.yml
It works fine and I can read the file under resources directory.
When I use mvn to build, in the snapshot jar created, it does not include config.yml and the path to "myresource.xml" is missing even though it is included in the snapshot.jar in the basedir. So, when I run it from my jar file, my code does not find it as resources.
How should I change the pom.xml to include config.yml and package the resource directory such a way that it is accessible as resource.
It is really strange that
this.getClass().getResource("myresource.xml")
does work in IDE but NOT when you run it from a jar.
this.getClass().getResourceAsStream("myresource.xml")
works both inside IDE and from jar.
That resolves the resources issue. However, I need an answer for how to package config.yml file. Should I supply separately in addition to the jar file?

How do I create an uber source jar with Maven?

Is there a well-known way to create an uber source jar? In other words, a jar of all the source code for a project and all its dependencies (or at least those that have a -sources.jar)?
I've looked into doing it with the maven-assembly-plugin, but using a dependencySet with includes of *.*.*.sources.* (or *.sources) doesn't work because those are not actually dependencies of the project, and I don't want to add them all.
You can use the maven-shade-plugin to create an uber jar. Just include the following within your <build> tag -
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.0.0</version>
<executions>
<execution>
<id>source-jar</id>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createSourcesJar>true</createSourcesJar>
<artifactSet>
<includes>
<include>...</include>
</includes>
</artifactSet>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
To modify the configuration, you can use Resource Transformers within org.apache.maven.plugins.shade.resource package.
And to define the contents of the jar, you can further use includes and excludes within the filters.
I found some information on working with sources in the maven-dependency-plugin.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>src-dependencies</id>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<phase>prepare-package</phase>
<configuration>
<classifier>sources</classifier>
<failOnMissingClassifierArtifact>false</failOnMissingClassifierArtifact>
<outputDirectory>${project.build.directory}/sources</outputDirectory>
<includeGroupIds>{your group prefix}</includeGroupIds>
<includes>**/*.java</includes>
<includeScope>runtime</includeScope>
</configuration>
</execution>
So if I do that, and then run a maven-assembly-plugin referencing the unpacked files, I can do it in two steps.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<execution>
<id>uber-source</id>
<goals>
<goal>single</goal>
</goals>
<phase>package</phase>
<configuration>
<descriptors>
<descriptor>ubersource.xml</descriptor>
</descriptors>
<outputDirectory>${deploy.internal.directory}</outputDirectory>
<finalName>${project.artifactId}</finalName>
</configuration>
</execution>
</executions>
</plugin>
with a file set in the assembly descriptor ubsersource.xml:
<fileSet>
<directory>${project.build.directory}/sources</directory>
<outputDirectory>.</outputDirectory>
</fileSet>
And then I get my uber source jar...
There is perhaps a subtle distinction in the way the maven-assembly-plugin and maven-dependency-plugin treats sources. If you reference classifier sources in a dependencySet of an assembly descriptor, it looks for sources that are actual dependencies in your pom -- not that useful. However, in maven-dependency-plugin, referencing sources classifier means that sources of your dependencies. Hence why this solution works.
I also wrapped this up in my own plugin using mojo-executor to make it single step, and single declaration in my pom, but that's optional
This is a lot more pom code, but I like it better than the maven-shade-plugin because it does just what I want, and nothing more.

Maven Shade and Clover won't work for mvn site

I have parent project and some child projects. Some of the child have dependency between each other. eg: parent - > child 1, parent -> child 2, child 1 -> child 2(Child1 is dependent on child 2)
Here is what I am doing in my poms:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
</plugin>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>3.1.10.1</version>
<configuration>
<jdk>${compile.source}</jdk>
<generateHtml>true</generateHtml>
<generatePdf>false</generatePdf>
<generateXml>true</generateXml>
</configuration>
<executions>
<execution>
<phase>pre-site</phase>
<goals>
<goal>instrument</goal>
</goals>
</execution>
</executions>
</plugin>
<reportPlugins>
<plugin>
<groupId>com.atlassian.maven.plugins</groupId>
<artifactId>maven-clover2-plugin</artifactId>
<version>3.1.10.1</version>
<configuration>
<jdk>${compile.source}</jdk>
<generateHtml>true</generateHtml>
<generatePdf>false</generatePdf>
<generateXml>true</generateXml>
</configuration>
</plugin>
</reportPlugins>
Child pom looks something like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
<exclude>META-INF/LICENSE</exclude>
<exclude>config.properties</exclude>
</excludes>
</filter>
</filters>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.cerner.pophealth.program.runtime.pipeline.Main</mainClass>
</transformer>
</transformers>
</configuration>
</plugin>
I am facing issue where mvm site-deploy would fail with following error:
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-shade-plugin:1.7.1:shade (default) on project foo: Error creating shaded jar: error in opening zip file /foo/bar/target/classes -> [Help 1]
mvn site-deploy is run from foo-parent level.
I have noticed even when site is run clover tries to create shaded jar within target/clover/ folder.
Any help is appreciated.
Used profile to enable/disable shaded plugin.
<profiles>
<profile>
<id>shade</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
The maven-clover2-plugin has two goals which can be used for source code instrumentation:
The clover2:instrument goal forks a parallel build life cycle in Maven in order to instrument sources. Which means that source roots (like src/main/java and src/test/java) as well as output folders (like target/classes) are being redirected to the target/clover directory. Such folder redirection may indeed in some cases cause trouble for other Maven plugins running.
The clover2:setup goal performs code instrumentation in Maven's default build life cycle. Which means that output folders remain unchanged (and instrumented classes are put into target/classes, for instance).
I suggest to try the clover2:setup instead goal of the clover2:instrument one. However, please keep in mind that calling the 'clover2:setup' together with 'mvn install' or 'mvn deploy' will cause that instrumented versions of your JARs will be installed. Unless this is a desired action,

Maven: JspC should use external JSP-files

We're using Maven 3 and I'm facing a project that has JSP-files and also uses "global" JSP-files stored in a different project. This works nicely when using maven-war-plugin and webResources. All JSP-files find their way into the WAR-file.
The new idea is to pre-compile all the JSPs. The obvious choice is to use jspc-maven-plugin. However, that doesn't include the external JSPs when it compiles the project-local JSPs.
Here's the snippet from the pom.xml:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
The error is
[ERROR] Failed to execute goal org.codehaus.mojo:jspc-maven-plugin:1.4.6:compile (jspc) on project internal.project: JSPC Error: file:C:/workspace/name.of.internal.project/src/main/webapp/WEB-INF/views/show.jsp(2,0) File "/WEB-INF/views/../jspGlobal/jsp-declaration.jspf" not found -> [Help 1]
The jspGlobal-directory would get copied with the <directory>../name.of.external.project/src/global/webapp</directory>-line above.
What's missing to include the external JSPs in JspC?
EDIT: Thanks to prunge's and Raghuram's input I looked deeper into sources and JavaDocs. I noticed that the mentioned sources requires a FileSet which does NOT allow a list of directories. And since sources is also not a list, I see no chance how I can specify more than one JSP-source directory. I even tried to copy the <plugin>-element, but that didn't help. My current situation is this:
<plugin>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-maven-plugin</artifactId>
<version>2.0-alpha-3</version>
<executions>
<execution>
<id>jspc</id>
<goals>
<goal>compile</goal>
</goals>
</execution>
</executions>
<configuration>
<sources>
<directory>${basedir}/../name.of.external.project/src/global/webapp</directory>
</sources>
<!-- the later mentioned <sources> gets picked
<sources>
<directory>${basedir}/src/main/webapp</directory>
</sources>
-->
<!-- 1.6 doesn't work!? Something lower than 1.5 seems to be the default -->
<source>1.5</source>
<target>1.5</target>
</configuration>
<dependencies>
<dependency>
<groupId>org.codehaus.mojo.jspc</groupId>
<artifactId>jspc-compiler-tomcat6</artifactId>
<version>2.0-alpha-3</version>
</dependency>
</dependencies>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.1</version>
<configuration>
<warName>${pom.groupId}.${pom.artifactId}-0.0.1-SNAPSHOT</warName>
<webXml>${basedir}/target/jspweb.xml</webXml>
<webResources>
<resource>
<directory>../name.of.external.project/src/global/webapp</directory>
</resource>
</webResources>
</configuration>
</plugin>
Now the external JSPs are compiled into the target-path of the current project. Now I need a way to compile the JSPs of the current project. How do I do this?
BTW, if I switch the <sources> to the line for the current project I get the same error as mentioned earlier.
Perhaps you could try with the latest version of jspc-maven-plugin, which is 2.0-alpha-3. Do note that the usage is a little different from the earlier version.
Looking at the source code of CompilationMojoSupport, I see a sources property of type FileSet. You might be able to configure this in the configuration of the plugin to add additional source directories. It looks like by default it uses ${project.basedir}/src/main/webapp regardless of the configuration of the WAR plugin.

Maven: how to get a war package with resources copied in WEB-INF?

when I create a war package with maven, files and directories under the directory "src/main/resources" are copied in /WEB-INF/classes instead of /WEB-INF. How can I get them copied in /WEB-INF?
thanks,
rand
UPDATE:
in my pom now I use this:
<plugin>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.3</version>
<executions>
<execution>
<id>copy-resources</id>
<!-- here the phase you need -->
<phase>war</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>myapp/target/WEB-INF</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
and I launch mvn with:
mvn -Dmaven.test.skip=true clean package resources:copy-resources
but I got:
[INFO] One or more required plugin parameters are invalid/missing for 'resources:copy-resources'
[0] Inside the definition for plugin 'maven-resources-plugin' specify the following:
<configuration>
...
<outputDirectory>VALUE</outputDirectory>
</configuration>.
[1] Inside the definition for plugin 'maven-resources-plugin' specify the following:
<configuration>
...
<resources>VALUE</resources>
</configuration>.
I'm using maven 2.2 and the snippet basically is the same of the documentation
any idea?
either configure the outputDirectory parameter of resources:resources plugin, or put your files under src/main/webapp/WEB-INF/ directory.
resource plugin
EDIT:
This configuration is working for me:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.4.2</version>
<executions>
<execution>
<id>default-copy-resources</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<overwrite>true</overwrite>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/WEB-INF/</outputDirectory>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
you can run a phase in the form somePhase or a goal somePlugin:someGoal. The phase invocations will invoke all plugins goals hooked on phases in interval [validate,phase] in order, so there's no need to explicitly call them.
Web resources are not the same as java resources, which should be placed in the classpath. Web resources are processed via the war plugin and should be placed into src\main\webapp\WEB-INF\. In this case, it will work automatically without any additional configuration in the pom.xml
This configuration is working add plugin pom.xml
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.3</version>
<configuration>
<webResources>
<!--copy resource file location-->
<resource>
<directory>${project.build.directory}/classes</directory>
</resource>
</webResources>
<!--location for add file-->
<webappDirectory>${project.build.directory}/${project.build.finalName}</webappDirectory>
</configuration>
</plugin>

Resources