Package a maven project via Windows command line - java

I want to release a server, built using Maven. The idea is that there is a batch file than can run the server and a batch file that can compile the server (any updated code, but stops leaching by not compiling certain changes).
Creating a deploy-able jar file in Maven is annoying as it is on its own using an IDE:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>
// Main class
</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
To then execute mvn package. But, the potential user who has downloaded the server, may not have MVN installed. Is there any way to package a maven project in the windows command line? (CMD) I have tried:
jar cvf MainClass.jar * // First attempt
jar cfe myJar.jar MainClass *.class // Second attempt
However, each of these will not work because it contains multiple packages therefor my structure looks like
- Folder A
- a.class
- b.class
- Folder B
- c.class
- d.class
etc..

Maven is frequently installed by java developpers, but there is a workaround if you don't have maven:
You can use the Spring boot maven wrapper, you don't need Spring boot dependencies, it's only 2 script and a directory with a jar that can be copied/pasted in your project : mvnw and mvnw.cmd and .mvn/*
Find an example of source here:
https://github.com/spring-guides/gs-spring-boot/blob/master/complete/mvnw
https://github.com/spring-guides/gs-spring-boot/blob/master/complete/mvnw.cmd
https://github.com/spring-guides/gs-spring-boot/tree/master/complete/.mvn/wrapper
It works just like the graddle wrapper:
It download a maven runtime from the tiny jar
It launch it.
CLI usage:
$ ./mvnw clean install
PS: The inconvenience of this method is that you rely on having the network for the download (with proxy well configured if needed) and every project you build will need the wrapper.

Related

Working directory not set correctly for multi module Java maven project

I have following multi module project structure:
ProjectName
+--Config
+--Pom.xml
+--Api
+--src\Main\Java\SomeRunnerClass.java
+--Pom.xml
+--Tests
+--src\Test\Java\TestsRunner.java
+--Pom.xml
When i run:
mvn compile -pl Api exec:java -Dexec.mainClass=SomeRunnerClass
Working directory is correctly seen as \ProjectName and i can use files from Config directory
But when i run
mvn compile test
Which runns TestsRunner (cucumber runner) the working directory is seen as \ProjectName\Tests so i can't see \ProjectName\Config directory and all tests artefacts are saved to Tests instead of ProjectName directory
Is there a way to change working directory when running maven tests?
I have achieved this by adding workingDirectory to maven-surfire configuration in child pom file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<workingDirectory>${project.basedir}/../</workingDirectory>
...

Difference between spring-boot:repackage and mvn package

After reading Spring documentation and some other articles on web, I am still confused what is the difference between Spring Boot Maven plugin's spring-boot:repackage and a regular mvn package.
I've thought that mvn package creates a jar with all dependencies included, so what is really the reason to use the plugin by Spring?
The maven package goal and the spring-boot:repackage goal are different in nature. The spring-boot repackage goal is mainly intended to make a JAR or WAR executable from the command line itself using java -jar *.jar while the maven package goal take the compiled code and package it in its distributable format, such as a JAR.It is the spring-boot repackage goal that repackages the JAR produced by maven to specify the main class and make it executable using an embedded container.
Maven Package
The first, and most common way, to set the packaging for your project via the equally named POM element . Some of the
valid packaging values are jar, war, ear and pom. If no packaging
value has been specified, it will default to jar.
When a package is defined,each packaging contains a list of goals to bind to a particular phase ,the jar packaging will bind the
following goals to build phases of the default lifecycle :
process-resources,compile,process-test-resources,test-compile,test,package,install,deploy.
Spring-boot:repackage
Plugin to be included is :
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>2.1.4.RELEASE</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The configuration repackages a jar or war that is built during the package phase of the Maven lifecycle.
So,Once spring-boot-maven-plugin has been included in your pom.xml, it automatically tries to rewrite archives to make them executable by using the spring-boot:repackage goal. You should configure your project to build a jar or war (as appropriate) by using the usual packaging element.
Reference : https://docs.spring.io/spring-boot/docs/current/reference/html/build-tool-plugins-maven-plugin.html
Spring repackage a jar or war that is built during the package phase of the Maven lifecycle. The following example shows both the repackaged jar, as well as the original jar, in the target directory:
$ mvn package
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
If you don’t include the configuration, you can run the plugin on its own (but only if the package goal is used as well). For example:
$ mvn package spring-boot:repackage
$ ls target/*.jar
target/myproject-1.0.0.jar target/myproject-1.0.0.jar.original
See more details from spring website using the link
mvn package creates a jar or war.
The spring boot plugin takes that jar or war and repackages them to make them executable from the command line (i.e. no app server needed).
From the plugin docs:
"Repackages existing JAR and WAR archives so that they can be executed from the command line using java -jar."

Automatically install a project in the local repository?

I'm trying to work around a maven bug MDEP-187 ( https://issues.apache.org/jira/browse/MDEP-187 ) by not using workspace resolution.
This forces me to do a mvn install for all my dependencies, I'm doing this by creating a launch configuration in eclipse with goal install.
The problem is that i have to create a launch config for every project in my multiproject workspace, in addition to install i have to manually call every launch config and run it. Which just doesn't work.
Is it possible to automatically install a project in the local repository? (whenever i update my code)
If you don't need to run dependency:copy in Eclipse, you can use following work-around:
Add a profile to your pom.xml, something like this:
<profiles>
<profile>
<id>copy</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.10</version>
<executions>
[...]
</executions>
</plugin>
</plugins>
<build>
<profile>
</profiles>
Enable workspace resolution in Eclipse.
Then Eclipse will not use dependency:copy, but you can use dependency:copy with command line: mvn install -P copy.
I did go with #khmarbaise solution:
But than you need to can handle the whole thing via
maven-assembly-plugin which can create archives / folders with all the
dependencies. Apart from that a swing ui must be started somehow which
will need some kind of shell script / batch file which you can create
by using appassembler-maven-plugin...And it sounds like you need to go
for a multi module project in maven..cause you might have parts like
core, ui, etc. which are needed to be combined in the end.
#khmarbaise i was in the understanding that the assembly-plugin didn't
support putting dependencies in a lib/ folder (just putting everything
in 1 big jar), but after a little bit of trying i just go myself a zip
with a runnable jar and my dependencies in a lib/ folder. Tomorrow i'm
going to read a bit more about the assembly-plugin. I'm happy ;-

Is it possible to build a java project only once using eclipse and share?

Is it possible to actually build a maven project containing java code to be built once and the binaries can be shared?
Problem: The project I am trying to build would take me about 3-4 hours and requires high internet bandwidth. I am trying to check the possibility of re using this built project among several other machines.
I have worked with c++ projects involving makefiles earlier and this was pretty simpler. I am new to Java / eclipse and would need help to figure out if this is something really possible.
PS:
I did try to find existing solutions; they were not straight forward or they say that this can't be done.
Build once and share it offline
In Maven, you can build your project only once and get a JAR file fully packed with all dependencies. So that, you can share this JAR to other machines off-line.
Below are the steps to make it.
First update your pom.xml with the below setting
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.thanga.MyTest[REPLACE WITH YOUR MAIN CLASS]</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
Package your project with the goal package assembly:single as shown below
In console,
mvn package assembly:single
In eclipse,
Run this and you can get the two JAR files. One of them MyFullPack-0.0.1-SNAPSHOT-jar-with-dependencies.jar has the full
dependencies loaded.
You can open the JAR to see the dependencies are packed as shown below.
You can share this JAR to other machines off-line without any more build
Is it possible to actually build a maven project containing java code to be built once and the binaries can be shared?
Yes, that's the whole point of Maven, you build the project once, thus generating an artifact (your jar/war ...) which is stored in your local maven repository.
The following command build the project and save it in the local repo :
mvn clean install
However, if you do this, you only have the artifact on your local repo.
A good practise is to create a repository and store your artifacts over there :
https://maven.apache.org/repository-management.html
The use of the following command would store the snapshot dependency on the repository :
mvn clean deploy
You can then reuse your components through multiples computer by specifying the dependencies in your new project's pom.xml file.
You might want to give a look at this guide :
http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html
You would obviously need to configure the repository and your maven project in order to use a setup of this kind.
First things first. Is your project a web application (war) or an enterprise application (ear) or just a stand alone Jar?
you can use the packaging tag in POM.xml to package your application to a JAR,WAR,EAR
Examples:
<packaging>war</packaging>
<packaging>ear</packaging>
<packaging>jar</packaging>
Then run mvn clean install
In project/src/target you should see the jar,war or ear generated which you can use to deploy on your machine or any other machine.
OR
you can also find that in .m2 folder once you have run install.
If you use maven, a mvn install will install your binary into your ${home}/.m2 folder. Those binary will be available for all other maven job that will run on the same machine.
If you need to share your binary between multiple machine, you can deploy your jars to a repository, like nexus or artifactory.
You can just take the jar file of your target folder and copy it to the other machines, otherwise you could use some share repository like nexus oder artifactory to share your built binary. Maven is capable of automatically deploying artifacts into those repositories

How do I package and run a simple command-line application with dependencies using maven?

I am brand new to both java and to maven, so this is likely very simple.
If I follow the maven2 hello world instructions here:
http://maven.apache.org/guides/getting-started/maven-in-five-minutes.html
everything works OK. If I then alter pom.xml to bring in a dependency from a remote repository, the files for this dependency get stored in ~/.m2/repository/new-dependency/.
Using the syntax in the hello world instructions to run the application requires that I add the absolute path to the dependency to my classpath (either by setting the environment variable or via the command line switch):
java -cp target/my-app-1.0-SNAPSHOT.jar:/.../.m2/.../new-dependency.jar com.mycompany.app.App
This will obviously get unwieldy quickly :)
I suspect that this is not the usual way of running a java program and that I just need to read more about .jar files, but while I am doing so I would appreciate any tips on how to do this properly.
I am not using an IDE, btw. vim from the command line.
Thanks!
Mike.
You can use maven itself to run it, I believe it sets the classpath for you.
mvn compile
will compile it
then you run:
mvn exec:java -Dexec.mainClass="com.mycompany.app.App"
which will execute it.
You can see http://www.vineetmanohar.com/2009/11/3-ways-to-run-java-main-from-maven/ for some more info on ways to run (including passing command-line args to the thing you want to run)
You can make a jar executable by adding the Main-Class attribute to its manifest file. In Maven this is done by the archiver plugin. To add the Main-Class attribute, add this to your pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<mainClass>com.mycompany.app.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
You can now run your jar with the command: java -jar myjar.jar or by double clicking on it (not available in all platforms).
If you want it simple for you and others, then you can generate a jar with all dependencies in it, using the maven-assembly-plugin. Example is here: http://maven.apache.org/plugins/maven-assembly-plugin/usage.html, section Execution: Building an Assembly
You can use the maven-shade-plugin which will create an executable uber war with all dependencies.
OR
Use the appassembler-plugin which creates a script that imports all dependencies and lets you execute a main class from the command line.

Categories