use maven shade plugin like assembly plugin - java

I have a pom file that builds a standalone application that leverages a variety of Spring modules, in particular it uses the integration-file module. Originally my pom file used the Maven Assembly plugin but the uber jar it created didn't run correctly. Further research seems to indicate that there is a bug in the assembly plugin that basically messes up the dependencies in the uber jar. The recommended workaround is the Shade plugin, which is working for me.
However, the assembly plugin is able to create a zip file that contains the uber jar and other resources (properties files, scripts, etc). You can then use that zip to unzip it and run your script which will call your jar and pass in the other items (as example). As far as I can tell the shade plugin does not do this additional feature.
I've tried combining the shade and assembly plugins using profiles but I can't figure out how to get it to use the shade plugin to build the uber jar and then afterwards, use the assembly plugin to build the zip with the other stuff.
Has anyone done anything similar? I just need to be able to create my uber jar and then zip up the uber jar with the scripts, xml and other items.
Is there a way to run the assembly plugin without binding it to a phase? If there were, I could run package and run the shade plugin and then afterwards run the assembly plugin independently? That would solve my issue if it were possible.

It's a bit late for this answer, but I have the same scenario as you ("package phase": 1. Build uber-jar with shade, 2. Pack it into assembly zip) and all I had to do is alter the order in which plugins are specified in pom.xml.
If shade is specified before assembly, it gets executed before, for the same phase.

It is a common practice to use a separate module in a multimodule project just for assembling the zip. There's also the appassembler-maven-plugin which might be interesting for you (I've never used it myself, though).
About running a plugin without a phase: that's always possible. Execute the full name as specified on the goal-page. In this case org.apache.maven.plugins:maven-assembly-plugin:2.4:single, or in short assembly:single.
Don't try o solve this with profiles, they aren't meant for that.

Related

JavaFX: Maven Plugin - Make the executable file reference to a maven repo instead of the lib folder

I'm looking for a way to create an executable jar file for my JavaFX application.
I'm currently using the zenjava maven plugin and I use the jfx:jar goal. Doing this, all the dependencies are generated on a folder called /lib.
The problem arises when one of the dependencies (a separate project handled by another group) is updated, I would need to rebuild my jar again.
Is it possible to just maybe refer to the dependencies using a pom? (not point to the lib) So I would only update the pom every time a dependency is updated?
Thanks in advance!
Short answer: nope, not possible
Long answer: the JavaFX-Maven-Plugin is usable for development (via mvn jfx:run) and deployment (via mvn jfx:jar or mvn jfx:native).
You are generating a potential deployable package, which already contains everything needed to execute on some targeted machine. You would have to encapsulate your javafx-application with a "pre-loader" which downloads all your required stuff to be executable.
What is the idea behind distributing an application which needs some internet-connection to gather all the required dependencies?
Disclaimer: I'm the maintainer of the javafx-maven-plugin.

How to use maven to generate code and package it without dependencies?

I have a project that generates some classes and resources that should then be packaged into a jar.
The class that does the generating has several dependencies. The generated classes have no dependencies.
My initial solution was to use the maven assembly plugin to only include the generated files. Unfortunately, the packaged pom includes all the dependencies required to do the generation. Consumers of this jar pull in a bunch of unnecessary dependencies.
I looked into the maven shade plugin. I compile once, run the generator class with mojo's exec plugin, the compile a final time. Then shade of course runs in the package phase. It creates a dependency-reduced-pom.xml without the excessive dependencies. So run mvn clean package and look in target/foo.jar. I expect the jar in the meta-inf folder to be the reduced dependency jar. But it's the full pom. I don't know how have the generated pom replace the one that is packaged.
Another poor solution I tried was using multiple profiles with their own dependency section. I run maven once with the generating profile, then again with the packaging profile. This works, but sucks because you have to run multiple maven commands. It's not jenkins friendly.
Am I going about this the wrong way? How should I go about arranging a project that generates some code and some text files that are then packaged in a maven friendly artifact?
1) One possibility is to make all your dependencies <optional>true</optional>.
The pom will still have the dependencies but the projects using your library won't try to download them.
2) Use plugin dependencies with the exec plugin.
That works well if the generator class is defined on another project.
Ideally you would call your generator using a plugin and avoid adding those dependencies to your project. That may not be worth doing depending on what your project is for and how reusable your generator has to be.
3) If you are using maven-shade-plugin the dependency-reduced-pom.xml is normally used. Check your .m2 repository to see the contents of the pom that is copied there when you do mvn install. It's likely that its contents will match the dependency-reduced-pom.xml

Running a Maven project with many dependencies

I'm hacking on a Maven-based project with a lot of dependencies; the project is normally meant to be developed in Eclipse but I need to work on it from the command line.
How to build+execute the project in a sane way? Something like mvn run, but of course Maven is not meant for running Java projects (for some reason).
The problem is specifying all the dependencies on java's commandline, I don't even know how to autogenerate that. I can currently deal with it using the assembly:single maven plugin (using the jar-with-dependencies descriptor) which will package the dependencies to a single .jar for me.
However, there really is a lot of dependencies and the assembly phase can take about two minutes, greatly disrupting my hack-test cycles so I'm looking for other ways to run the project with minimum build overhead - any recommendations, please?
Note: One possibility is running it in Eclipse once and capturing the java commandline. However, that's just a one-time hack, not a general solution in case I change pom.xml later or come to another project from the suite without Eclipse access anymore.
Have a look at the maven exec plugin
mvn exec:java -Dexec.mainClass="com.example.Main"
if you do this frequently, you can of course configure it via plugin configuration.
Regarding finding out project dependencies - you can use maven dependency plugin
http://maven.apache.org/plugins/maven-dependency-plugin/list-mojo.html
If you want to put them into file it'd be smth like
mvn dependency:list > dependencies.txt
See this question: How can I create an executable JAR with dependencies using Maven?. You can use the dependency-plugin to generate all dependencies in a separate directory before the package phase and then include that in the classpath of the manifest.
I see three solution to this:
onejar-maven-plugin - faster than assemlby with jar-with-dependencies descriptor
With onejar-maven-plugin, you'll (...) get a nice clean super jar with the dependency jars inside.
Spring Boot Maven Plugin - but this is dedicated to Spring projects
Maven Assembly Plugin with custom descriptor. This custom descriptor should grab all dependencies into lib folder, maven-jar-plugin should set Class-Path in Manifest.fm according to this new location. After this you can simply execute your program or zip your jar with lib folder as distribution.
After this is possible to run your program on your computer or any other with one command:
java -jar myjar.jar

How can I retrieve the classpath string from my Eclipse project that uses Maven?

How can I retrieve the classpath string from my Eclipse project that uses Maven? In eclipse , I have more than 100 .jar files imported via Maven and refrences as a library called "Maven Dependencies". How can I retrieve the "effective" classpath in the form of a string in my project?
The .classpath file does not reveal this.
You can try to use the java development toolkit (JDT) in Eclipse. The class JavaCore in the org.eclipse.jdt.core plugin can take a reference to your java project (an IProject) and return an IJavaProject which adds the behavior of knowing stuff about the classpath. Maven provides a classpath container that should also collaborate with the IJavaProject to answer back the actual source folders and jars on the classpath. Can't provide with any more info off the top of my head, but I think this approach is your only hope.
Unless you write an eclipse plugin that extends the maven plugin. Documentation is sketchy at best, but in theory you can write an extension that is asked to tweak the contents of the maven container in your project's class path. If at that time you were to cache information about the container contents off to your plugin's state folder, you'd be able to reference it when the user wants you to invoke your script. This extension would be invoked whenever maven is asked to update project configuration or dependencies.
I understand that you want to execute that script yourself and you have Maven installed. I guess the easiest way to run your application in this case is to use the Maven Exec Plugin:
http://mojo.codehaus.org/exec-maven-plugin/
(I'm usually using the exec:exec goal to run the application in its own process.)
Edit:
Otherwise have a look at the Maven Dependency Plugin to prepare the classpath if you don't want to use the Maven Exec Plugin:
http://maven.apache.org/plugins/maven-dependency-plugin/

What is "pom" packaging in maven?

I was given a maven project to compile and get deployed on a tomcat server. I have never used maven before today, but I have been googling quite a bit. It seems like the top level pom.xml files in this project have the packaging type set as pom.
What am I supposed to do after mvn install to get this application deployed? I was expecting to be able to find a war file somewhere or something, but I guess I am looking in the wrong place or missing a step.
pom is basically a container of submodules, each submodule is represented by a subdirectory in the same directory as pom.xml with pom packaging.
Somewhere, nested within the project structure you will find artifacts (modules) with war packaging. Maven generally builds everything into /target subdirectories of each module. So after mvn install look into target subdirectory in a module with war packaging.
Of course:
$ find . -iname "*.war"
works equally well ;-).
pom packaging is simply a specification that states the primary artifact is not a war or jar, but the pom.xml itself.
Often it is used in conjunction with "modules" which are typically contained in sub-directories of the project in question; however, it may also be used in certain scenarios where no primary binary was meant to be built, all the other important artifacts have been declared as secondary artifacts
Think of a "documentation" project, the primary artifact might be a PDF, but it's already built, and the work to declare it as a secondary artifact might be desired over the configuration to tell maven how to build a PDF that doesn't need compiled.
Packaging of pom is used in projects that aggregate other projects, and in projects whose only useful output is an attached artifact from some plugin. In your case, I'd guess that your top-level pom includes <modules>...</modules> to aggregate other directories, and the actual output is the result of one of the other (probably sub-) directories. It will, if coded sensibly for this purpose, have a packaging of war.
To simply answer your question when you do a mvn:install, maven will create a packaged artifact based on (packaging attribute in pom.xml), After you run your maven install you can find the file with .package extension
In target directory of the project workspace
Also where your maven 2 local repository is search for (.m2/respository) on your box, Your artifact is listed in .m2 repository under (groupId/artifactId/artifactId-version.packaging) directory
If you look under the directory you will find packaged extension file and also pom extension (pom extension is basically the pom.xml used to generate this package)
If your maven project is multi-module each module will two files as described above except for the top level project that will only have a pom
Packaging an artifact as POM means that it has a very simple lifecycle
package -> install -> deploy
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
This is useful if you are deploying a pom.xml file or a project that doesn't fit with the other packaging types.
We use pom packaging for many of our projects and bind extra phases and goals as appropriate.
For example some of our applications use:
prepare-package -> test -> package -> install -> deploy
When you mvn install the application it should add it to your locally .m2 repository. To publish elsewhere you will need to set up correct distribution management information. You may also need to use the maven builder helper plugin, if artifacts aren't automatically attached to by Maven.
I suggest to see the classic example at: http://maven.apache.org/guides/getting-started/index.html#How_do_I_build_more_than_one_project_at_once
Here my-webapp is web project, which depends on the code at my-app project. So to bundle two projects in one, we have top level pom.xml which mentions which are the projects (modules as per maven terminology) to be bundled finally. Such top level pom.xml can use pom packaging.
my-webapp can have war packaging and can have dependency on my-app. my-app can have jar packaging.
“pom” packaging is nothing but the container, which contains other packages/modules like jar, war, and ear.
if you perform any operation on outer package/container like mvn clean compile install. then inner packages/modules also get clean compile install.
no need to perform a separate operation for each package/module.
Real life use case
At a Java-heavy company we had a python project that needed to go into a Nexus artifact repository. Python doesn't really have binaries, so simply just wanted to .tar or .zip the python files and push. The repo already had maven integration, so we used <packaging>pom</packaging> designator with the maven assembly plugin to package the python project as a .zip and upload it.
The steps are outlined in this SO post
https://maven.apache.org/pom.html
The packaging type required to be pom for parent and aggregation (multi-module) projects. These types define the goals bound to a set of lifecycle stages. For example, if packaging is jar, then the package phase will execute the jar:jar goal. If the packaging is pom, the goal executed will be site:attach-descriptor
POM(Project Object Model) is nothing but the automation script for building the project,we can write the automation script in XML,
the building script files are named diffrenetly in different Automation tools
like we call build.xml in ANT,pom.xml in MAVEN
MAVEN can packages jars,wars, ears and POM which new thing to all of us
if you want check WHAT IS POM.XML

Categories

Resources