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."
Related
I am trying to push my microservice to nexus and at the same time deploy to openshift.
my pom has got this:
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>exec</classifier>
</configuration>
</plugin>
This results in the creation of two jar files at the time of build.
my-service-exec.jar
my-service.jar
I took the advice from https://docs.spring.io/spring-boot/docs/1.4.1.RELEASE/maven-plugin/examples/repackage-classifier.html and added the exec classifier in my pom
After deploy and at pod startup I see this error message:
ERROR Neither $JAVA_MAIN_CLASS nor $JAVA_APP_JAR is set and 2 JARs found in /deployments (1 expected)
and the pod is not starting.
Any help in this regard is much appreciated.
By default, the repackage goal will replace the original artifact with the repackaged one. That is a sane behaviour for modules that represent an app, but if your module is used as a dependency of another module, you need to provide a classifier for the repackaged one.
The reason for that is that application classes are packaged in BOOT-INF/classes so that the dependent module cannot load a repackaged jar's classes.
spring docs
I need to set a active profiles to the jars while compile the maven spring boot project
Following are my two Approaches tried to activate the profiles.
First Approach - Not Activating the Profiles
mvn clean package -Dspring-boot.run.profiles=dev help:active-profiles
-s settings.xml
*
Above command not setting the active profiles while executing jars
java -jar package.jar
I have using maven plugin dependencies for activating the first approach
<build>
<finalName>${project.artifactId}</finalName>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring.boot.version}</version>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions> </plugin> </plugins></build>
Second Approach - Working as expected.
mvn clean package -Dspring.profiles.active=dev help:active-profiles -s
settings.xml
java -jar -Dspring.profiles.active=dev package.jar
I'm using multi-module parent pom structure for the project. Any one pls advise to work the first approach?
Maven is a build system. Its responsible for building your artifact.
Maven's profiles are basically a tool that allows to slightly change the build process depending on various factors (operating systems, version of java and so forth).
These are defined in maven's files (pom.xml)
Spring (and Spring boot of course) as opposed to maven is a runtime framework.
Spring profiles is something totally different - they allow to load different beans, resolve different configurations in runtime (read after you call java -jar app.jar) depending on profile definitions.
So don't be confused with the same name, its only an "accidental coincidence"
Now as for your question.
Maven builds the artifact and packages it for that use spring boot maven plugin. If you want to customize this building process - use maven profiles (and as a consequence help:effective-profiles can be sometimes handy).
When the artifact is built - you can run it. For that you can use spring profiles to define runtime in-variants:
- Addresses of databases
- Credentials
- Some subsystems of your product that won't be run locally
and so forth, this list really depends on the application itself.
There is an option to run the spring boot application right from maven and for that you can really use -Dspring.profiles.active=dev but if you don't run it (and you don't in any of suggested approaches, read about mvn spring-boot:run to understand what does it really mean to run a spring boot application during the build), then:
First approach:
mvn clean package -Dspring-boot.run.profiles=dev help:active-profiles
-s settings.xml
-Dspring-boot.run.profiles is irrelevant here - you do nothing with it (again you don't run the project during the build) so it does nothing
java -jar package.jar
Here you can really specify spring profiles with --spring.profiles.active=dev,whatever
The Second approach:
mvn clean package -Dspring.profiles.active=dev help:active-profiles -s
settings.xml
Again, -Dspring.profiles.active=dev is irrelevant, it does nothing.
java -jar -Dspring.profiles.active=dev package.jar
Here you do specify the list of active profiles (just like --spring.profiles.active, from spring boot's standpoint its the same) That's why the application works in runtime as expected
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.
I am having problems importing classes from a JAR library into my project. Please see the screenshot.
I have tried several things both in Eclipse and IntelliJ, both adding directly and adding through Maven. None of this helps, I still get a red underline.
In IntelliJ I tried:
Project Structure - Modules - Dependencies - Add jar.
Tried creating a lib folder, add it as a library and place the jar inside and then setup as dependency.
Adding through maven pom.xml with direct path to the jar.
In Eclipse I tried:
Java Build Path and adding it to my build path.
Maven - Update Project.
Here is my pom.xml to get the local jar.
<dependency>
<groupId>uk.co.pervasive_intelligence.simulator</groupId>
<artifactId>protocol</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>C:\Users\Vas-DELL\Desktop\simulator-1.2.2.jar</systemPath>
</dependency>
Strangely, I am able to see the jar and the classes inside the jar (screenshot). But still can not import them. Let me know please if there is anything else I can provide.
Create a lib/ dir in the root of your project folder. Put your Jar there. Add this to your pom.xml:
<dependency>
<groupId>uk.co.pervasive_intelligence.simulator</groupId>
<artifactId>protocol</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/lib/simulator-1.2.2.jar</systemPath>
</dependency>
Do not use \ as path separator (even though you're using windows)
Run mvn clean package from the command line
You could also try installing the dependecy manually in your local repo:
mvn install:install-file -Dfile=simulator-1.2.2.jar -DgroupId=uk.co.pervasive_intelligence.simulator -DartifactId=protocol -Dversion=1.0 -Dpackaging=jar
Then add this to your pom:
<dependency>
<groupId>uk.co.pervasive_intelligence.simulator</groupId>
<artifactId>protocol</artifactId>
<version>1.0</version>
</dependency>
EDIT:
The jar file does not have the structure of a standard java library. In order to use that jar as a library, the packages of your classes should exist as folders in the base (or root directory) of your jar file. For example:
/META-INF
/MANIFEST.MF
/uk
/co
/pervasive_intelligence
/simulator
/BaseComponent.class
/SimulatorApplication.class
/SimulatorException.class
....
Being a library jar file then the contents of the MANIFEST.MF can be as simple as
Manifest-Version: 1.0
Hope this helps
Class files in co.uk... package is inside BOOT-INF/classes packed inside simulator jar, and cannot be accessed directly because it not part of jar's default classpath (".").
To understand better about jar classpath please check What's the default classpath when not specifying classpath?
simulator jar need to be packaged with classpath entry to add BOOT-INF/classes/... in classpath to allow access to classes under BOOT-INF/classes.
For example to allow access to classes from package uk.co.pervasive_intelligence.simulator.Component with maven this can be done as
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Class-Path>BOOT-NF/classes/uk/co/pervasive_intelligence/simulator/Component</Class-Path>
</manifestEntries>
</archive>
</configuration>
</plugin>
If You Use SpringBoot and InteliJ Idea, when you have excute mvn clean package command, you should use packagename.jar.original in maven pom for The jar file have the structure of a standard java library.
/META-INF
/MANIFEST.MF
/uk
/co
/pervasive_intelligence
/simulator
/BaseComponent.class
/SimulatorApplication.class
/SimulatorException.class
....
This might be small question but I am not able to find answer to it. I wrote a library called Utilities and used java doc style comments. Using maven (m2e plugin in eclipse). I am using maven install option. I am getting a jar file and i am pushing the jar file to a central repository and reusing the same library in another project. I am able to use the lib and complete my project successfully but when I do ctrl click I am not able to see the library code from my project. I am also not able to see the arguments description when i hover my mouse on the methods.
I know that it is because My project is not finding sources and java doc .
So How can i generate sources , java doc for my library and attach them to my project using maven.
Thanks
See:
Cookbook: How to attach source and javadoc artifacts?
You need to use the maven sources plugin found at this link:
http://maven.apache.org/plugins/maven-source-plugin/usage.html
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<phase>verify</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
You must deploy sources and javadoc JARs along with library JAR. AFAIR you can either use:
$ mvn clean javadoc:jar source:jar deploy
or:
$ mvn clean deploy -DperformRelease=true
See also:
How to deploy Javadoc jar file?
Maven 2: Deploying Javadoc with your project
Maven 2: Deploying Project Sources
Attaching javadocs and sources to Maven install/deploy