One Spring Boot project, deploy to both JAR or WAR - spring

Is there a way to have a single Spring Boot project be packagable into both JAR and WAR without changing the pom.xml or the application source?
I've read Converting a Spring Boot JAR Application to a WAR, but it converts the project to WAR and it loses the ability to be packaged as JAR.
I don't expect mvn package to do both. What I want is something like mvn i-want-a-jar and it would package the project as JAR. Or I could run mvn i-want-a-war and it would package the project as WAR.
Is this possible?

I managed to do it by adding
<packaging>${packaging.type}</packaging>
to the POM file and then setting different profiles for JAR and WAR:
<profiles>
<profile>
<id>jar</id>
<properties>
<packaging.type>jar</packaging.type>
</properties>
</profile>
<profile>
<id>war</id>
<properties>
<packaging.type>war</packaging.type>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-tomcat</artifactId>
<scope>provided</scope>
</dependency>
</dependencies>
</profile>
</profiles>
Now mvn package -P war produces a WAR and mvn package -P jar produces a JAR.
Another option is to create separate modules for JAR and WAR, but I didn't go that route.

What's wrong with a WAR file that's executable? Isn't that what you really need?
P.S. like
java -jar name.war

We've recently had a similar requirement, where an existing Spring Boot based project that was originally packaged as an executable Jar needed to support Tomcat and WildFly deployments.
Due to some dependencies used in this project (for example WebJars), a simple switch to WAR package wasn't an option since some of those dependencies were required for WildFly (VFS support) but not for other deployment.
The solution was to restructure the project modules in a way that core module contained the actual project but without having Spring Boot’s plugin applied, while several package modules would depend on core module and configure deployment artifact specifics (Boot and other plugins, deployment specific dependencies etc.).
That way project build was able to generate multiple deployment artifacts (Boot's executable JAR, traditional WAR and WildFly specific WAR) in a single build run.
In case anyone finds this useful, the sample project to demonstrate the approach is available on Github. The project can be built by either Gradle or Maven.

Related

Intellij Spring maven install error "package does not exist"

Intellij version : Community 2019.2.3
Maven : 3.6.2
Spring : 2.2.0
I am trying to create a very simple Spring maven project with two sub-modules (one independent and another one dependent on independent one).
Root module - testmultimodule
Independent module - independent
Dependent module - dependent
testmultimodule pom.xml has all Spring related declaration and module definition
<modules>
<module>independent</module>
<module>dependant</module>
</modules>
Independent poom.xml is simplest and . only has parent maven declaration
<parent>
<artifactId>testmultimodule</artifactId>
<groupId>in.org.app</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
dependent module pom.xml has the dependency declaration as below to independent module
<dependencies>
<dependency>
<groupId>in.org.app</groupId>
<artifactId>independent</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
I have created a Test class under dependent module and using a User object from independent module. Initially, without the above dependency declaration, asa usual there was compilcation error.
As soon as I add the dependency and builld the project within Intellij IDE with the option "Build Prooject" option from "Build" menu, it successfully builds.
However, if I try to use Maven install option within Intellij right side window option. It always fails stating Error:(3,33) java: package in.org.app.independent.bo does not exist .
I am providing the GitHub URL for the test project , if you want to take a look and test by yourself.
GIT URL:
https://github.com/DhruboB/testmultimodule
I have tried all sort of tweaking found in internet so far e.g.
clearing Intellij Cache & restarting, mvn -U clean install, mvn scope verification, proxy etc.
Any further idea to resolve this? I need to solve this in the Community version of Intellij.
Your parent project includes the definition for the spring-boot-maven-plugin. This leads to each project defining this as a parent to be repacked to an executable JAR by this plugin. This repackaged JAR isn't useable as a dependency in another project.
Either you need to change the configuration of the spring-boot-maven-plugin for the project you want to use as a dependency. This is explained here in the Spring Boot Reference Guide. You now basically have 2 jars from this project, one plain and one executable.
If you don't need that project to be an executable JAR file then just move the spring-boot-maven-plugin to the project that needs to be. All other projects will no be basic JAR files again.
See also How to add a dependency to a Spring Boot Jar in another project?

How to deploy multi-module maven spring boot application on OpenShift

I have a multi-module spring-boot project that I want to deploy on Openshift, where I have installed Jenkins as well. Source code is hosted in Github.
Each module consists in a war, in order to have a microservices structure:
<modules>
<module>xyz-common</module>
<module>xyz-data-services</module> <!--a REST service to interact with mongodb-->
<module>xyz-batch-importer</module> <!--a service to import files into Mongo-->
<module>xyz-frontend</module>
</modules>
I found tutorial to deploy single spring-boot application, but I cannot figure out how this applies to a multi-module maven project.
If you want to work with multi-module maven project on openshift, then you have to tell openshift how to build them. You can achieve this task by defining build environment variables or writing custom build scripts which can be interpreted by Openshift.
For both method you can follow this tutorial:
If you want to work with first method, you can tell openshift to use additional maven commands while building process by defining "MAVEN_ARGS_APPEND" variable for build config.
So when the build operation starts on openshift, it will tell Maven that build the application with these additional parameters.
Define additional build environment variables that listed below to deploy war modules independently:
MAVEN_ARGS_APPEND: -pl modulename --also-make
ARTIFACT_DIR: modulename/target/
MODULE_DIR: modulename
In here "-pl" command provides to build "xyz-data-services" with its all dependencies. So if your "xyz-data-services" module has dependency to "xyz-common", then maven will build "xyz-common", create related artifacts for "xyz-data-services" ,package them together and deploy "xyz-data-services" as war on the pod.
In your case, suppose that you want to package "xyz-data-services" module and "xyz-front-end" module as war and deploy them.
Case 1:
If you want to make these modules self deployable, then you have to create two applications which will run on different pods.
First application will have these build environment variables:
MAVEN_ARGS_APPEND: -pl xyz-data-services --also-make
ARTIFACT_DIR: xyz-data-services/target/
MODULE_DIR: xyz-data-services
And the second one will have these guys:
MAVEN_ARGS_APPEND: -pl xyz-front-end --also-make
ARTIFACT_DIR: xyz-front-end/target/
MODULE_DIR: xyz-front-end
Case 2:
If you want to deploy these modules into same pod, then you can add an additional module to your project which packages both wars into single ear and define the variables for this ear.
So let this ear be "webapp", your parent pom will look like;
...
<modules>
<module>xyz-common</module>
<module>xyz-data-services</module>
<module>xyz-batch-importer</module>
<module>xyz-frontend</module>
<module>xyz-webapp</module>
</modules>
...
and the xyz-webapp pom will look like;
....
<artifactId>xyz-webapp-</artifactId>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xyz-common</artifactId>
<version>${project.version}</version>
<type>jar</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xyz-data-services</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>xyz-frontend</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
....
So your build environment variables will be;
MAVEN_ARGS_APPEND: -pl xyz-webapp --also-make
ARTIFACT_DIR: xyz-webapp/target/
MODULE_DIR: xyz-webapp
If you want to work with just single war and single pod then;
Case 3:
You can just package front-end application as war and declare dependencies to other modules which all packaged as ".jars"
You can go on with which case do you want. It's important here that it depends on your "microservices" implementation. Because the "microservice" term and the implementation is not explicitly defined and it can vary on the architecture or some business requirements, it's your decision that packaging front-end,api,backend together or manage them independently.

Maven EAR project for multiple application servers

I have a EAR project that I want automatize the building process using maven exclusively.
The EAR project has
Standard jar modules
Web modules
EJB modules
RAR modules
To be able to execute the product in Jboss 4.2.3 and WebSphere 7 the EJB and RAR descriptors must be configured in different way. Also we have one jar library for each app server.
What I want is to be able to build one EAR for each apps server using the same projects, and for that I need
Include a JAR module depending of the app server
Use the customized descriptor in the EJB/RAR modules depending of
the app server
Package all this customized modules in an EAR
Can this be done using the same set of project in maven?
Sure. Have a look at profiles in maven. They allow you to adjust various things (from the link) like:
<repositories>
<pluginRepositories>
<dependencies>
<plugins>
<properties> (not actually available in the main POM, but used behind the scenes)
<modules>
<reporting>
<dependencyManagement>
<distributionManagement>
a subset of the element, which consists of:
<defaultGoal>
<resources>
<testResources>
<finalName>
The best is to create separate modules like ear-websphere, or ear-jboss and make an appropriate pom file which contains the needed configuration for maven-ear-plugin.

How to auto-deploy EJB jar with TomEE maven plugin

I have a stateless EJB SOAP Web Service that is packaged in jar file.
Is it possible to setup auto-deploy with Tomee maven plugin when the app consists of only one EJB jar file?
For example, this site indicates that a web context defined in server.xml is required. My synch setup is same as the site suggests.
mvn compile
command does nothing but compile the sources as it normally does.
Is there a possibility to setup something like this with EJB jar or is a WAR package needed in any case?
Thanks.
UPDATE
In order to get the TomEE Maven plugin to work at all with jar files, I added the following in pom.xml configuration section
<apps>
<app>my.group:my-ejb-app:1.0:jar</app>
</apps>
We use the maven tomcat7 plugin to do exactly this. Here's the trick, because Apache TomEE is JEE6, you can deploy EJBs in wars.
So there are two ways to do what you want... One, skip the Jar packaging for your application and make your EJBs be WARs. If this doesn't sound appealing, the other way is to create a separate project that's a WAR, but pulls in your EJB jar as a dependency.
In either case, then you can then use the tomcat7 plugin to deploy your projects easily to Apache TomEE like this mvn tomcat7:deploy provided you fill out the server section of your pom correctly. Example:
<build>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<server>crabs</server>
<url>http://crabs/manager/text</url>
<path>/${project.artifactId}</path>
<update>true</update>
</configuration>
</plugin>
</plugins>
</build>
Make sure you have a user in tomcat-users.xml on the server that has the proper deployment permissions to manager-text. Also, put the server configuration into your ~/.m2/settings.xml:
...
<servers>
<server>
<id>crabs</id>
<username>deploy</username>
<password>your password</password>
</server>
...

Maven/Spring: How to add external jar to classpath without installing it as maven dependency?

The common ways of including external non-maven jar in the classpath of your Maven project is to either use "addjar-maven-plugin" (which I have not been able to get to compile maven with) or "mvn install:install-file" and then adding a dependency section for the external JAR. This approach essentially installs client JAR in your repo and makes it available in classpath for maven. But is there a better way to do this (or) are the options mentioned above the only ones available? I just want the external JAR to be added to classpath for component scanning by Spring but do not want the JAR itself to be added to my repo as it is client's JAR? I hope this is a valid case (if not, kindly explain)
Thanks,
Paddy
You can create lib folder under your project's src folder and reference this folder as maven repository.
<repository>
<id>local</id>
<url>file://${basedir}/src/lib</url>
</repository>
Then you should add dependency to your jar in your pom.xml
<dependency>
<groupId>com.company</groupId>
<artifactId>dependency</artifactId>
<version>1.0</version>
</dependency>
After that your should rename jar file and place it on following path src/lib/com/company/dependency/1.0/dependency-1.0.jar . This path depends on how you want to reference your jar.

Resources