I am wondering about the steps required with Maven to implement custom packaging and bind it to the 'package' phase.
Basically what I need is to invoke standard maven-war-plugin and create ZIP archive of a specific structure that will contain created WAR file. While I know how to do these tasks separately, I do not quite understand how to tie them together.
I assume a sequence like this:
At some phase maven-war-plugin is invoked. It automatically handles WAR-specific stuff and creates the WAR file
During 'package' phase maven-assembly-plugin is invoked. It creates ZIP archive of the required structure.
What would be the most straightforward and proper way to define these tasks in POM file and bind them to the build life cycle?
We generally just run the assembly during the package phase, using the standard assembly config:
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>attached</goal>
</goals>
</execution>
</executions>
if that is not working for you for some reason, an easy solution is to split the war and the zip into 2 submodules. generate the war in the first sub-module, then create a second sub-module of type "pom" which runs the assembly plugin.
Can you try invoking the maven-assembly-plugin during the 'install' phase?
You can change the phase of each task.
1) Create the War file during the prepare-package phase
<phase>prepare-package</phase>
2) Create the zip file during the package phase
<phase>package</phase>
Related
I noticed maven plugins has goals and they are bound to different phases. But it seems some goals will only be executed after we explicitly config them in side execution tag. For example, maven-jar-plugin has two goals jar and test-jar. If you don't config test-jar goal explicitly inside execution tag then it will not be executed. It will only be triggered with below config where test-jar is explicitly config inside execution tag
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.1.0</version>
<executions>
<execution>
<phase>test-compile</phase>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
But for goal jar whether you config it with execution tag or not, it will always be triggered. In this case, I wonder to trigger a goal of a plugin should we config it inside execution tag or not? I didn't see official doc has any clarification on this either. Thanks.
The jar goal is by default bound to the default life cycle (jar) so it's triggered automatically.
All plugins which are bound by the default life cycle (for example maven-compiler-plugin etc) will run automatically during a build.
Any other goals which are not bound will not run automatically and have to be bound manually if needed.
All goals like the jar goal of the maven-jar-plugin should never being bound manally... because they are already bound to the life cycle.
Furthermore you should always check the documentation of the appropriate plugin (here the maven-jar-plugin) and check the goal page for the text: Binds by default to the lifecycle phase: package.
This means you can omit the <phase>..</phase> part of your configuration because the plugin knows the life cycle phase when it should start.
I am using Maven to build my project. It was working fine up until I put in a parent pom. Now, the project still builds but the output is 2 jar files instead of one. One of them ends in a -boot.jar, and seems to be the correct jar file, because it has all the dependencies baked in and is over 60mb. The other file has the correct name (projectId-version.jar) but is less than 1mb, and this is the one that gets picked up by the pipeline process, and it fails deployment.
I need mvn to build just one jar with all the dependencies baked in.
I am using Spring boot 1.5.19 (the parent pom has this dependency). Any ideas?
Please see the documentation of the spring boot maven plugin usage and docuemtation.
https://docs.spring.io/spring-boot/docs/2.1.4.RELEASE/maven-plugin/repackage-mojo.html
https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html
Specifically the repackage goal. The parent POM you are using must be configured to set the new artifact to add the boot.jar via the classifier configuration.
Classifier to add to the repackaged archive. If not given, the main artifact will be replaced by the repackaged archive. If given, the classifier will also be used to determine the source archive to repackage: if an artifact with that classifier already exists, it will be used as source and replaced. If no such artifact exists, the main artifact will be used as source and the repackaged archive will be attached as a supplemental artifact with that classifier. Attaching the artifact allows to deploy it alongside to the original one,
You could define the configuration settings for the maven plugin and override whatever is defined in the parent.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
<configuration>
<classifier></classifier>
</configuration>
</plugin>
I am a newbie to Java/Maven. I have a standard maven project structure, and I've written some helper classes that I want to use in some testing scripts, and those classes are in the src/test/java. After I do mvn clean install, I can see that those classes are in target/test-classes, but in my script although I use the absolute path to the target directory in my CLASSPATH, I am seeing a Could not find or load main class ....
For instance, I have src/test/java/validation/CrossValidator.java, and in my script I am using java -cp $CLASSPATH validation.CrossValidator ..., where CLASSPATH is the absolute path to target directory.
Anyone can guide me to accomplish this? I know that I can simply move those classes to src/java/main, but I don't want those classes to be part of the library jar, since they're not used at runtime.
Thanks in Advance.
You can add a secondary execution of the maven-jar-plugin that builds a test jar from your project:
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>test-jar</goal>
</goals>
</execution>
</executions>
</plugin>
This will create a jar with a classifier of test-jar that contains all of your test classes.
More details can be found at Create test JAR.
I have a POM-based Java project. It contains a number of servlets for deployment in a WAR. However, in addition to this, I also have classes that launch the application as a standalone using embedded servlet and database environments (for a turnkey development environment). Additionally, there is also a command-line client for the application.
I would like to have the ability to build the project into both the WAR and two separate executable JARS (one server, one client). I'm not concerned about the JARs/WAR containing some unnecessary code or deps- I just want all 3 to work.
What's the "correct" way to do this with Maven?
Multiple projects is the way to do this. Put the common code in the first project along with the standalone support. Then make a second with war packaging that depends on the first.
You could use assembly plugin to do this. Assembly plugin can package zip or tar.gz archive for you. It's a perfect distribution format for standalone applications. When you configure assembly plugin you could link it to package phase, so application will be packaged in two formats: war and zip.
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.2.1</version>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>assembly</goal>
</goals>
</execution>
</executions>
</plugin>
I'm currently migrating our build process to Maven from Ant. Our application is deployed to many different customers, each with a unique set of dependencies and and configuration. I can implement different profiles to model these and build the required wars from them. However this is a process that happens at compile time.
Each release is tagged under SVN as well as uploaded to our internal Nexus repository. I want to be able to take a defined release and reconstruct it based a profile. Is there a way to do something like this? Is there something other than profiles I should be using?
"declare several execution for the war plugin to produce several artifacts (and install/deploy them)" This sounds like this might be the way forward. How would I go about doing this?
This goes a bit against a Maven golden rule (the one main artifact per module rule) but can be done. The One artifact with multiple configurations in Maven blog post describes one way to implement this approach:
I decided to put all the environment
specific configuration in a special
source tree, with the following
structure:
+-src/
+-env/
+-dev/
+-test/
+-prod/
Then I configured the maven-war-plugin
to have three different executions
(the default plus two extra), one for
each environment, producing three
different war files: beer-1.0-dev.war,
beer-1.0-test.war and
beer-1.0-prod.war. Each of these
configurations used the standard
output files from the project and then
copied the content from the
corresponding src/env/ directory on
to the output files, enabling an
override file to be placed in the
corresponding src/env/ directory. It
also supported copying a full tree
structure into the output directory.
Thus if you for instance wanted to
replace the web.xml in test you
simply created the following
directory:
src/env/test/WEB-INF/
and placed your test specific
web.xml in this directory and if you
wanted to override a db.property
file placed in the classpath root
directory for the test environment you
created the following directory:
src/env/test/WEB-INF/classes
and placed your test specific
db.property file in this directory.
I kept the src/main directory
configured for development
environment. The reason for this was
to be able to use the
maven-jetty-plugin without any extra
configuration. Configuration
Below you find the maven-war-plugin
configuration that I used to
accomplish this:
<plugin>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<classifier>prod</classifier>
<webappDirectory>${project.build.directory}/${project.build.finalName}-prod</webappDirectory>
<webResources>
<resource>
<directory>src/env/prod</directory>
</resource>
</webResources>
</configuration>
<executions>
<execution>
<id>package-test</id>
<phase>package</phase>
<configuration>
<classifier>test</classifier>
<webappDirectory>${project.build.directory}/${project.build.finalName}-test</webappDirectory>
<webResources>
<resource>
<directory>src/env/test</directory>
</resource>
</webResources>
</configuration>
<goals>
<goal>war</goal>
</goals>
</execution>
<execution>
<id>package-dev</id>
<phase>package</phase>
<configuration>
<classifier>dev</classifier>
<webappDirectory>${project.build.directory}/${project.build.finalName}-dev</webappDirectory>
<webResources>
<resource>
<directory>src/env/dev</directory>
</resource>
</webResources>
</configuration>
<goals>
<goal>war</goal>
</goals>
</execution>
</executions>
</plugin>
(...) I can define each customer project with profiles but I don't know if there's a way to release them to a repository.
You have several options:
use profiles and run the build several times (create artifacts with a classifier and install/deploy them)
declare several execution for the war plugin to produce several artifacts (and install/deploy them)
use different modules (and maybe war overlays to merge a common part with a specific one)
Or at least a way in Maven to automatically build an artifact with a specified profile from say an SVN tag.
Well, this is doable. But without more details about a particular problem, it's hard to be more precise.
I would take a look at your architecture and see if there is a way to split up your project into multiple projects. One would be the main code base. The other projects would depend on the JAR file produced by the main project and add in their own configuration, dependencies, etc to produce your final artifact.
This would let you version customer specific code independently of each other as well as keeping common code in one place and separate from customer specific stuff.
Have you taken a look at the Maven Assembly plugin?
This plugin allows you to customize how your distribution is assembled - i.e. what format (.tar.gz, .zip, etc), directory structure, etc. I think you should be able to bind several instances of the plugin to the package phase to assemble multiple variations of your output (i.e. the packaging for customer 1, customer2, etc, separately).
The deploy plugin should then automatically handle deploying each of your assembled packages in the target directory to the repository.
I ended up doing something slightly different. We're not storing the releases in our internal repository. Instead we're building using Hudson and a multi-configuration project (one configuration/profile for each customer). This way when a release is made the Hudson job is run to build different wars for all customers. They are then stored on the Hudson server instead of Nexus. Builds for specific versions and customers can also be built at any time from the releases in Nexus. – samblake Mar 16 '11 at 12:32