Maven dependency project export - spring

I am using Spring in two 2 projects. First, I have a "web" project which depends on my second project that is a normal java project with maven nature enabled that I named "core".
So, in my "web" project I just add the reference of my "core" project:
<dependency>
<groupId>com.stackoverflow</groupId>
<artifactId>core</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>jar</type>
</dependency>
If I set the property "useProjectReferences" to false like here, everything works fine, But I am in developing phase, I don't wanna run maven install everytime I have a change in my "core" project.
I am running my projects in tomcat, so I can't package them in ear. All that I want is Maven export my "src/main/resources" source folder to Spring be able to find my coreContext.xml and bind my beans. What I have tried in my "core" pom.xml:
<build>
<resources>
<resource>
<directory>${basedir}src/main/resources</directory>
<targetPath>${basedir}WEB-INF/resources</targetPath>
</resource>
...
I tried to use shade-plugin but without success too. Any tip would be appreciated.

My suggestion would be to create a Multi Module Maven Project which contains both the core and web projects.

Related

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.

Multiple module Spring Boot app

We have a Spring Boot app (exposing REST services) with multiple modules and for dev purposes we're using the default Spring Boot build approach - Maven builds it as one executable war file, that has Tomcat embedded into it.
For productive deployment purposes this doesn't work. We already have web app servers setup and we need a regular, non-executable war, that can be deployed on those servers. I already figured out, how I can build it.
We also will have another, related web apps (war files) deployed on the same productive servers (e.g. - simulator of the app). Of course, they will use (some of) the same modules, so the question it raises is how to setup maven to build the war and the module jars outside of it, so the other apps (war files deployed on the same server) could have dependencies on them. I couldn't find a good explanation/example how to do that.
Any ideas, links, blogs?
This is really more of a Maven question than Spring Boot. When you have a multi-module project Maven still creates individual artifacts for each module so you can still reference them as dependencies elsewhere.
For example in my setup with Spring boot I have the parent project and the modules underneath it. Most of the modules are jar artifacts, some with dependencies on other modules in the project and of course some external dependencies as well. By using the parent we can standardize some of the versions used in the dependencies using placeholders in the parent. Since the artifacts are still built and published separately you can reference them in other projects, which is what I believe you are asking.
For example (just the main tags and not all of them):
Parent:
<groupId>com.somecompany</groupId>
<artifactId>project-parent</artifactId>
<packaging>pom</packaging>
<version>1.1.2-SNAPSHOT</version>
<modules>
<module>module1</module>
<module>module2</module>
</modules>
Module1:
<parent>
<groupId>com.somecompany</groupId>
<artifactId>project-parent</artifactId>
<version>1.1.2-SNAPSHOT</version>
</parent>
<groupId>com.somecompany.tools</groupId>
<artifactId>project-tools-core</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>jar</packaging>
Module2:
<parent>
<groupId>com.somecompany</groupId>
<artifactId>project-parent</artifactId>
<version>1.1.2-SNAPSHOT</version>
</parent>
<groupId>com.somecompany.apps</groupId>
<artifactId>project-webapp</artifactId>
<version>1.1.2-SNAPSHOT</version>
<packaging>war</packaging>
<!-- dependency on other module -->
<dependency>
<groupId>com.somecompany.tools</groupId>
<artifactId>project-tools-core</artifactId>
<version>${project.version}</version>
</dependency>
Some Other Project:
<groupId>com.somecompany.apps</groupId>
<artifactId>project-webapp-services</artifactId>
<version>1.3.0-SNAPSHOT</version>
<packaging>war</packaging>
<!-- dependency on other module which is published -->
<dependency>
<groupId>com.somecompany.tools</groupId>
<artifactId>project-tools-core</artifactId>
<version>1.1.1</version>
</dependency>
So in this case assuming you had published version 1.1.1 of your parent and its modules you can have another project refer to any of those published artifacts. Maybe it is the release and publishing step you are missing.

One Spring Boot project, deploy to both JAR or WAR

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.

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 can I share non-OSGi libraries between bundles in an OSGi container?

I came across this question when trying to share the Struts packages among multiple bundles inside an OSGi container. I wanted to avoid both duplicating dependencies inside the bundles and introducing a new dependency between them (by having one bundle export its internal dependencies for the other to share).
It turns out the answer is very easy if you happen to use Maven, and if you aren't, you can still use the Maven solution to learn how to create the same result with some other mechanism.
I found this approach useful multiple times during my project, so I'll post an example here.
An additional path for those not so keen on maven, unable to port, or perfectly happy with ant/ivy
I've found the that easiest way to accomplish the stated task is to turn the non-OSGi library into an OSGi library by letting the manifest export every package and add on some approriate symbolic names / versions. I've been able to do this VERY easily with bnd via ant tasks (or even direct command line invocation). There are also repositories which contain "osgi-ified" version of many popular libraries. Some libraries (joda-time) are already shipping with correct OSGi manifests.
Using Maven, it is very easy to create an OSGi bundle from any library. However, I think the same result can be created with other mechanisms, too. The Maven solution helped me understand how it works.
Creating the bundle is done by creating a project which has the library as a dependency and then packaging the project using the maven-bundle-plugin from the Apache Felix project and specifying the library packages with the Export-Package instruction. I used this to share Google Protocol Buffers between bundles inside an OSGi container:
<?xml version="1.0" encoding="UTF-8" ?>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.lib</groupId>
<artifactId>protobuf-dist</artifactId>
<version>2.1.0</version>
<name>Google Protocol Buffers OSGi Distribution</name>
<packaging>bundle</packaging>
<dependencies>
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
<version>2.1.0</version>
<scope>compile</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>com.google.protobuf</Export-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
</project>
If you want all transitive dependencies rolled into the bundle, too, use the bundleall goal of the plugin.
The plugin recognizes and honours existing OSGi manifests in the dependency.
You can also use the bundle plugin to just create the manifest and tell the jar packaging plugin (or the jar-with-dependencies builtin assembly) to use that manifest via the archive section. The plugin's page linked above shows how to do that.

Resources