Taken by example the jhipster-sample-app how can I manage multiple profiles, given that the same application will be installed in several machines having different configurations?
Since the deployment will be made using the apache tomcat, and it could be running one or more jhipster based apps, I would like to avoid using
-Dspring.profiles.active=MY_PROFILE
in the JAVA_OPTS variable.
Also it could happen to run the same application with different profiles on the same tomcat instance.
Taking profiles for the configuration of an application to support different environments like dev, test, prod is a bad idea.
Let us assume you have defined to make it simple three profiles like dev,test,prod. So now you build for dev environment like this:
mvn -Pdev clean package
Ok now you can take your artifact and deploy it. Next time you need for test environment you have to go like this:
mvn -Ptest clean package
You can take your artifact and deploy it. But what happens if you like to create for two environments or for three?
mvn -Pdev,test,prod clean package
This will usually fail, cause it's really tricky (and in same areas impossible) to handle different profiles to produce three different artifacts. So the best practice is to remove profiles and let your build produce just by:
mvn clean package
all the packages you need one for dev, one for test and one for prod.
One solution is to create a project structure like this:
.
|-- pom.xml
`-- src
|-- main
| |-- java
| |-- resources
| |-- environment
| | |-- test
| | | `-- database.properties
| | |-- qa
| | | `-- database.properties
| | `-- production
| | `-- database.properties
| `-- webapp
The different folders and property files are place holders just to show the path.
Next you need an assembly-descriptor one for each environment like this:
<assembly xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
<id>test</id>
<formats>
<format>war</format>
</formats>
<includeBaseDirectory>false</includeBaseDirectory>
<dependencySets>
<dependencySet>
<unpack>true</unpack>
<useProjectArtifact>true</useProjectArtifact>
</dependencySet>
</dependencySets>
<fileSets>
<fileSet>
<outputDirectory>WEB-INF</outputDirectory>
<directory>${basedir}/src/main/environment/test/</directory>
<includes>
<include>**</include>
</includes>
</fileSet>
</fileSets>
</assembly>
And finally you need to configure the maven-assembly-plugin like this:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>test</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/test.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>qa</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/qa.xml</descriptor>
</descriptors>
</configuration>
</execution>
<execution>
<id>production</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>${project.basedir}/src/main/assembly/production.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
In the end this will produce the following artifacts: artifact-VERSION-dev.war, artifact-VERSION-test.war and artifact-VERSION-prod.war with a single call of Maven. If you take a deeper look into that blog article the above can made much more elegant.
Related
I have a jar project that uses some .jar libs to run. In old days we use Eclipse to build the jar, but now my company is migrating to Maven. I didn't know how hard is to create an independent jar file that contains its dependencies (or some of them) inside itself like before xD.
I've read that there's an "assembly" maven plugin that "unpack" the dependencies and put them inside the independent jar, but my company has its own maven repository and they don't have that plugin. So, I'm using the "dependency-plugin" to achieve that.
The problem is that I can't get my independent jar to run.
I have this in my pom:
...
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<classpathPrefix>.</classpathPrefix>
<mainClass>jar.App</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.1.2</version>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
</execution>
</executions>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.example.jar2</groupId>
<artifactId>jar2</artifactId>
<version>1.0-SNAPSHOT</version>
<type>jar</type>
<overWrite>false</overWrite>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</artifactItem>
</artifactItems>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
<overWriteReleases>false</overWriteReleases>
<overWriteSnapshots>true</overWriteSnapshots>
</configuration>
</plugin>
<plugin>
Actually, the content of the pom.xml is not important because I get what I wanted: my jar with a structure like this:
jar1.jar
|
- com/something/my-classes.class
|
- META-INF
| |
| - MANIFEST
| - maven
| |
| - A lot of maven stuffs
|
- jar2-1.0-SNAPSHOT.jar
And my MANIFEST file has these entries:
Class-Path: ./jar2-1.0-SNAPSHOT.jar
Main-Class: jar.App
I thought it was enough to have my jar dependencies copied inside my independent jar and indicate the Class-Path in my MANIFEST to tell to java "hey! here are my dependencies!", but, when I try to run the jar with:
java -jar my-jar.jar
I get:
Exception in thread "main" java.lang.NoClassDefFoundError: jar2/Operations
In the line where I'm trying to use the classes of my dependencies.
Why is that? What I need to get an independent jar with Maven (without using the assambly plugin)? I supposed I'm missing something to indicate to Java where my dependencies are, but I'm not sure... Or maybe I need an extra class that "loads" every class that I'm using?
Thanks a lot!
I have an issue concerning the target directory of aggregated javadocs.
What I have is:
A maven project containing several modules. It looks a bit like the one used as example here
Project
|-- directory_to_contain_docs/
|-- pom.xml
|-- Module1
| `-- pom.xml
|-- Module2
| `-- pom.xml
`-- Module3
`-- pom.xml
I can't get it done to make javadoc generate the documentation in the directory named "directory_to_contain_docs".
This is what I tried:
I call the generation with "mvn javadoc:aggregate". And this is a part of the pom.xml:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<!-- Default configuration for all reports -->
<failOnError>false</failOnError>
<destDir>${basedir}/directory_to_contain_docs</destDir>
<!-- as there are lots of incorrectly documented sources -->
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
<executions>
<execution>
<id>aggregate</id>
<goals>
<goal>aggregate</goal>
</goals>
<phase>site</phase>
<configuration>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
The javadoc is always generated in {project}/target/site/apidocs, the generation creates the complete path given in destDir beneath that directory. I am looking for a way to have the whole docs somewhere else.
Is there a chance to achieve that?
Thanks,
Ishiido
Don't know why I did not see it... The missing link is
configuration/reportOutputDirectory.
It specifies the directory where the documentation is generated. It may be specified further by destDir.
Basically, I want to generate a jar file named <project.name>.jar in addition to default jar file(which in my case is something like <project.name> + <project.version>.jar). NOTICE : This <project.name>.jar is all the same to default jar but the name.
And this additional jar should have a manifest file like below which is the manifest file of default generated jar
anifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: XXX
Start-Class: com.XXXX.XXX.Application
Spring-Boot-Version: 1.3.1.RELEASE
Created-By: Apache Maven
Build-Jdk: 1.8.0_74
Main-Class: org.springframework.boot.loader.JarLauncher
I am adding additional block in my as follows
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
....
<execution>
<id>copy-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<finalName>${project.name}</finalName>
</configuration>
</execution>
<execution>
</plugin>
But in my case, the manifest file generated in my addition jar don't have following impart fields:
Start-Class
Main-Class
...
So it couldn't be deployed.
I know the requirement sounds weird, but the question is clear, how to make maven generate a jar which having a correct and complete manifest file for deployment?
//The complete plugin part
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<goals><goal>test-jar</goal></goals>
</execution>
<execution>
<id>copy-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<finalName>${project.artifactId}</finalName>
</configuration>
</execution>
<execution>
<id>dto-jar</id>
<goals><goal>jar</goal></goals>
<phase>package</phase>
<configuration>
<finalName>${project.artifactId}-dto</finalName>
<includes>
<include>**/dto/*</include>
<include>**/dto</include>
<include>**/exceptions/*</include>
<include>**/exceptions</include>
<include>**/utils/*</include>
<include>**/utils</include>
</includes>
</configuration>
</execution>
</executions>
</plugin>
Concerning your maven-jar-plugin section:
You are having three executions: one for the test-jar goal, two for the jar goal
one of them re-using the default execution id (default-jar) to specify the finalName entry, but not specifying any manifest configuration. According to this configuration, your manifest file should also be empty then, not coherent with the description provided by your question then.
the additional jar goal execution has a further configuration with customizated option, nothing wrong here, except that you except to have a properly filled manifest file as part of it, while (again) there is no configuration for it.
A possible explanation would be that your pom also provides a pluginManagement section, with further configuration for the maven-jar-plugin, or a parent pom at its top which would then specify a further configuration for the same.
To double check this, you could run
mvn help:effective-pom -Doutput=eff-pom.xml
And check the content of the generated eff-pom.xml file. That would be the single source of truth for your case.
Looking at your manifest entry:
Spring-Boot-Version: 1.3.1.RELEASE
Main-Class: org.springframework.boot.loader.JarLauncher
It makes quite clear that you are working on a Spring Boot project, normally having a Spring Boot parent pom which already configures the required manifest file. However, it makes use of a fat-jar (jar with dependencies or uber jar), not built via the maven-jar-plugin but via the maven-assembly-plugin.
As an example:
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.4</version>
<configuration>
<descriptors>
<descriptor>src/main/assembly/jar-with-dependencies.xml</descriptor>
</descriptors>
<archive>
<manifest>
<mainClass>org.springframework.boot.loader.JarLauncher</mainClass>
</manifest>
<manifestEntries>
<Start-Class>org.springframework.boot.load.it.jar.EmbeddedJarStarter</Start-Class>
</manifestEntries>
</archive>
</configuration>
<executions>
<execution>
<id>jar-with-dependencies</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
Hence you should not look at the Jar Plugin solution, but rather add a further Assembly Plugin execution for the same.
Just quick share of some other aspects of this problem. actually pom file should never be in charge of deployment business(even though It could, but very likely bring into more issues in the future). This part should be fully managed by bamboo deploy script. That is what I eventually did.
A mavenized version of an old project of mine creates two Jar files, one for command line and one for GUI use. As it currently stands, it deploys only the primary artifact to the local repository. The jars are created by having two executions for maven-jar-plugin, and both get created in the target directory. What happens is the GUI file overwrites the primary one, with the wrong name:
[INFO] Installing /Users/gmcgath/DevProjects/git/jhove/target/jhove-GUI-1.12.0-SNAPSHOT.jar to /Users/gmcgath/.m2/repository/edu/harvard/hul/ois/jhove/1.12.0-SNAPSHOT/jhove-1.12.0-SNAPSHOT.jar
I'm trying to use the build-helper plugin to get the GUI jar deployed to the repository, using the following:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>attach-artifacts</id>
<phase>package</phase>
<goals>
<goal>attach-artifact</goal>
</goals>
<configuration>
<artifacts>
<artifact>
<file>${project.artifactId}-GUI-${project.version}</file>
<type>jar</type>
<classifier>gui</classifier>
</artifact>
</artifacts>
</configuration>
</execution>
</executions>
</plugin>
Maven runs to completion without any errors, but doesn't copy the jar properly. The log tells me it's trying to copy the GUI jar from the project-level directory instead of the target to the correct destination. The GUI file is still overwriting the primary jar.
[INFO] Installing /Users/gmcgath/DevProjects/git/jhove/jhove-GUI-1.12.0-SNAPSHOT to /Users/gmcgath/.m2/repository/edu/harvard/hul/ois/jhove/1.12.0-SNAPSHOT/jhove-1.12.0-SNAPSHOT-gui.jar
(The "harvard" part is historical. Keeping this open-source project was part of my severance package. :)
So I'm doing something basically wrong. How can I fix this? Should I be using the assembly plugin instead, even though it looks more complicated?
Update: Partially fixed. The file element in the artifact needs to be
<file>${project.build.directory}/${project.artifactId}-GUI-${project.version}.jar</file>
I'm still looking for the fix to get the primary artifact copied correctly.
OK, here's my fix. The first part, as indicated above, was to get the directory and extension right in the build-helper artifact. It should have been
<file>${project.build.directory}/${project.artifactId}-GUI-${project.version}.jar</file>
The other issue was in a part of the pom.xml that I didn't post. The two executions lacked a classifier element, and so looked like this:
<executions>
<execution>
<!-- console app - don't change id, will cause build problems -->
<id>default-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<classifier>cmd</classifier>
<archive>
<manifest>
<mainClass>Jhove</mainClass>
</manifest>
</archive>
</configuration>
</execution>
<execution>
<id>gui-app-jar</id>
<phase>package</phase>
<goals><goal>jar</goal></goals>
<configuration>
<classifier>gui</classifier>
<archive>
<manifest>
<mainClass>JhoveView</mainClass>
</manifest>
</archive>
<finalName>${project.artifactId}-GUI-${project.version}</finalName>
</configuration>
</execution>
</executions>
Everything looks OK now.
We are building a jar file from external(to the project) classes.
That works fine but we have not been able to figure out how to also include the external source files. I have tried using the "< includes >" tag but only end up with a manifest file in the final jar when used. I have looked at using the maven-resources-plugin but either I used it wrong or it doesn't work in my case. Here is a copy of our of code:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<!-- <phase>generate-resources</phase> -->
<phase>clean</phase>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<classesDirectory>${itendant.path}/web/rocket/WEB-INF/classes</classesDirectory>
<finalName>${itendant.jar.name}</finalName>
<outputDirectory>${itendant.jar.path}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
Sources? Do you mean external dependencies? These should also be managed with maven, using mvn deploy:deploy-file as described on http://maven.apache.org/plugins/maven-deploy-plugin/usage.html , and imported in your pom.xml.
If you really mean external resources, then a proper resources declaration would be:
<project>
...
<build>
...
<resources>
<resource>
<directory> [your folder here] </directory>
</resource>
</resources>
...
</build>
...
</project>
You can have multiple tags if you have multiple resource directories, of course. Also note that building anything during clean is questionable, as clean is not run every build - package would be a better option.