Use maven to pack modules into an ear module - java

I have a project divided into modules/sub-projects.
Root
- module jar (used to contain ejb)
- module war (used to contain web app)
- module ear (used to pack the two aforementioned modules into one deployable unit)
Without using maven we should:
Build the jar and war projects separately and then
pack them in a ear.
I'm new to Maven but in my understanding Maven is used to manage this process
on behalf of the developer.
My project in term of maven is structured in the following way:
ROOT
parent-pom.xml
- jar-pom.xml
- war-pom.xml
- ear-pom.xml
My question is how do we tell maven to pack the jar and war module into a .ear
project, wich pom.xml should host this information ?
Edit:
The following is my project structure

Find the sample pom.xml under ear project to build ear
Add
<packaging>ear</packaging>
Add Dependencies
<dependencies>
<dependency>
<groupId><Your api Jar Group Id></groupId>
<artifactId><Your API artifact Id></artifactId>
<version>${project.parent.version}</version>
<type>ejb</type>
</dependency>
Add build plugin
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId
<configuration>
<version>6</version>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<modules>
<ejbModule>
<groupId><Your EJB Module Group Id></groupId>
<artifactId><Your EJB Module Artifact Id></artifactId>
</ejbModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>

Related

skip certain modules during deploy in multi-module maven java project on appengine w/ appengine-maven-plugin

I have a multi-module maven java project. In the parent pom:
<modules>
<module>core</module>
<module>batch-worker</module>
<module>be</module>
<module>scheduler</module>
<module>migrations</module>
</modules>
Both the migrations and core modules aren't services I wish to deploy but just common packages used throughout all services.
When i attempt a deploy with mvn appengine:deploy, I receive goal execution failures because the core and migrations modules do not define an app.yaml as they are not deployable services.
How do I skip these and omit them from the deploy?
You can define your services in the maven plugin.
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>2.2.0</version>
<configuration>
<services>
<!-- Default service-->
<service>${project.build.directory}/${project.name}-${project.version}</service>
<!-- other service-->
<service>${project.parent.basedir}/other_module/target/other_module_finalName-${project.version}</service>
</services>
</configuration>
</plugin>
However, in the documentation the services are take into account only for start/stop command and not for deploy. I don't know if it works.
Let me know.

Maven packaging for websphere

I am trying to build an EAR file - Which can be deployed in IBM websphere server.
This is an existing struts appliation, i am trying to mavenize it.
This project contains two folders
1. web
2. webEAR
web is actually for war file and webEAR folder for the EAR file, web contains all the code, and webEAR is a kind of a wrapper.
Steps I have already done are below
IDE - Eclipse
Java version - 1.7
Convereted both web and webEAR to Maven - (Configure to Maven)
edited the POM.XML like below
<modelVersion>4.0.0</modelVersion>
<groupId>com.comp.web</groupId>
<artifactId>web</artifactId>
<version>0.0.1</version>
<packaging>war</packaging>
<name>WEB</name>
<description>WEB</description>
added all relevant jar files - which are in lib folder as below (sample)
<dependency>
<groupId>jarfile</groupId>
<artifactId>com.ibm.jar</artifactId>
<version>1.0</version>
<scope>system</scope>
<systemPath>${basedir}/WebContent/WEBINF/lib/com.ibm.jarfile.jar</systemPat>
</dependency>
Now i dont have any errors in the eclipse, and I can run the application by right clicking the webEAR folder -> Run in Server, It works.
but I am not sure, how to create a EAR file , which has the war file, so that I can deploy in the WAS server dev environment.
Can someone show me a way I can do this. currently there is no POM.xml in the webEAR maven folder
P.S - I am not a Java developer. This is a first maven related project I am assigned to. I appreciate any help
Your module should have <packaging>ear</packaging>.
In the dependencies for this ear module ( Use a new module to build the ear ) include your war module as below.
<dependency>
<groupId>com.comp.webGroupId</groupId>
<artifactId>war-artifact</artifactId>
<version> war-version</version>
<type>war</type>
</dependency>
In the build plugins for this ear module include the maven-ear-plugin.
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<finalName>web</finalName>
<version>versionNumber</version>
<generatedDescriptorLocation>${basedir}/src/main/application/META-INF</generatedDescriptorLocation>
<modules>
<webModule>
<groupId>com.comp.webGroupId</groupId>
<artifactId>war-artifact</artifactId>
<uri>web.war</uri>
<bundleFileName>web.war</bundleFileName>
<contextRoot>/applicationName</contextRoot>
</webModule>
</modules>
</configuration>
</plugin>
Add any specific configuration values as required.

Best way to build twice the same webapp with different dependencies using maven

I have a maven project with a webapp for which I need two versions, each one having its own set of dependencies. The intent is to support two different (and conflicting) versions of a storage client. The webapp code, configuration file and anything but certain libraries is the same in both cases. The right client is loaded at runtime : I just need to drop the right jar (and its dependencies) in the lib folder of the webapp.
If I deploy the dependencies manually, I lose the opportunity to check for version conflicts (which I do when I build a maven project with all its dependencies correctly set).
I do not want to deploy the webapp(s) on the maven repository since it is not a library and it only makes a big archive (mainly because of the embedded dependencies) that consumes space for nothing. Thus, to build the final wars, I cannot add a dependency on the webapp project.
I do not want to duplicate the common webapp class files and configuration files in two different modules. It would make future evolutions more difficult because of the necessary synchronization between the two modules each time one file is updated.
Any suggestion on how to solve this ?
Note that the best solution should allow to build both wars at once.
Use Maven profiles.
http://maven.apache.org/guides/introduction/introduction-to-profiles.html
You can put certain dependencies into certain profiles and activate/deactivate them through the command line with the -P parameter.
I guess defining two profiles in your pom might do the trick :
<project [...]>
[...]
<profiles>
<profile>
<id>storage1</id>
<dependencies>
<dependency>
<groupId>my.group.storage</groupId>
<artifactId>thisOne</artifactId>
<version>13</version>
</dependency>
</dependencies>
</profile>
<profile>
<id>storage2</id>
<dependencies>
<dependency>
<groupId>my.group.storage</groupId>
<artifactId>thisOtherOne</artifactId>
<version>37</version>
</dependency>
</dependencies>
</profile>
</profiles>
[...]
</project>
Call one or the other with mvn -P storage1 or mvn -P storage2. You can also make one active by default, use activation triggers based on other properties, etc.
Here's their introduction article.
In the end, I did not use profiles. There was an issue building both webapp versions at once.
Instead I used war overlays https://maven.apache.org/plugins/maven-war-plugin/overlays.html.
First, I created a skinny war version of the webapp. The skinny war does not include libraries nor META-INF files. Only resources like configuration files. The webapp classes are packaged in a jar (using the attachedClasses configuration option of the maven-war-plugin). I do not mind having this war deployed since it is very lightweigth. Here is the configuration of the maven-war-plugin :
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<outputFileNameMapping>#{groupId}#.#{artifactId}#-#{version}##{dashClassifier?}#.#{extension}#</outputFileNameMapping>
<attachClasses>true</attachClasses>
<archive>
<addMavenDescriptor>false</addMavenDescriptor>
</archive>
<packagingExcludes>WEB-INF/classes/**/*,WEB-INF/lib/*</packagingExcludes>
</configuration>
</plugin>
Then, I created 2 additional modules, one for each flavour of the webapp. In the dependencies, I set :
- the webapp as a dependency of type war
- the jar of the webapp classes
- the storage client library
That way, maven checks for dependency conflicts in all the libraries. The webapp classes are imported through the dependency. The overlay war is used to build the final war. No duplicate code between the 2 flavours of the webapp. Only the client dependency changes between the 2 pom files. Here is an excerpt of one of them :
<dependencies>
<dependency>
<groupId>com.storage</groupId>
<artifactId>client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.group.id</groupId>
<artifactId>webapp</artifactId>
<version>${project.version}</version>
<classifier>classes</classifier>
<type>jar</type>
</dependency>
<dependency>
<groupId>com.group.id</groupId>
<artifactId>webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-install-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-deploy-plugin</artifactId>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

Maven Tomcat7 run a dependency war

I have a question regarding maven and its tomcat7 plugin :)
I have the following maven projects:
plugin1: plain java project packaged as jar
plugin2: plain java project packaged as jar
webapp: standalone webapp project packaged as jar
those three project are properly build in maven and the outcome works fine:
I can use the jars from plugin1/plugin2
I can deploy the webapp war file to a web container
I can run tomcat7:run to start the webapp
Now, I need to provide different packaging of the webapp containing specific plugin setup.
i.e. I want to generate a war file with webapp + plugin1 and another one with webapp + pugin2
To achieve this, I have created 2 additionnal maven projects that declare dependancies on the webapp project + the appropriate plugin projects and are packaged as wars.
The generated war files have the expected content, and can be deployed to a tomcat, but when I try to use the maven tomcat plugin (tomcat7:run again), it simply doesnt start anything.
Though this is not blocking for me (my main point was to generate the war files), I have the feeling that I missed something.
the pom.xml for those aggregate projects looks like this (note that there is absolutly no code in those projects, these were just created for packaging with specific dependancies convenience).
<groupId>my.project</groupId>
<artifactId>live1</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>war</packaging>
<name>MyWebapp</name>
<properties>
<failOnMissingWebXml>false</failOnMissingWebXml>
</properties>
<dependencies>
<dependency>
<groupId>my.project</groupId>
<artifactId>plugin1</artifactId>
<version>${project.version}</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>my.project</groupId>
<artifactId>webapp</artifactId>
<version>${project.version}</version>
<type>war</type>
<scope>runtime</scope>
</dependency>
</dependencies>
<build>
<finalName>MyWebapp</finalName>
<plugins>
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<url>http://localhost:8080/manager</url>
<server>localhost</server>
<path>/${project.build.finalName}</path>
</configuration>
</plugin>
</plugins>
</build>
Thanks !
note: long time lurker, first time asker here, if some information is missing tell me :)
Depending on the structure of your project it may not be suficient to just add a dependency of type war. You may need also to configure <overlays> as described here maven-war-plugin.
It looks like your final war does not provide the full web configuration that you expect. With overlays you can configure how the resources from the dependency will be packed into your final web app.
There must be some difference in the way that your external tomcat starts the app compared to the tomcat7 plugin. May be you can try -X option :
mvn -X tomcat7:run
This should log out some details, of what the embedded tomcat is configuring..

Packaging WSDL clients in JARs with Maven and cxf-codegen-plugin

I've got a maven project that will consume a number of webservices. The application will be packaged as a WAR. So far the clients' code has been generated with cxf-codegen-plugin, in the generate-sources phase. By default, generated sources are placed into target/generated-sources/cxf, and after compile, they are compiled and mixed up with the application classes in target/classes. Both the generated and application classes can share the first level packages.
I'd like each of the clients to be packaged in its own JAR inside WEB-INF/lib in the WAR file. I found out about -clientjar, but it only generates the .jar files and places them into target/generated-sources/cxf, and the JARs also end up in target/classes along with the compiled classes, which is pointless.
I suppose the compile plugin at some point is compiling the generated sources into target/classes, and possibly another phase is also moving the JARs there. Would it be possible to have Maven avoid compiling those generated sources (or even have cxf-codegen-plugin generate no sources at all, only the JARs), and compile the application classes against the JARs generated by CXF?
I know it would be possible to achieve this by defining a multimodule project with a jar packaging module for each webservice, but I'd like to avoid this option. There can be a large number of webservices and it would not be suitable to maintain an independent module for each one. With -clientjar I'm already forced to define a <wsdlOption> for each WSDL in order to provide the JAR name for each WSDL (it's not possible to let cxf-codegen-plugin just scan src/main/resources/wsdl or <wsdlRoot>).
Of course the client JARs could be generated outside Maven and installed to a local repository, and be defined as dependencies in the project, but I'd like to know if it's possible to do this in a single Maven build.
With assemblies I'd probably sort out how to place the JAR files generated by -clientjar into WEB-INF/lib but there would still be an issue with the generated classes inside the WAR.
I don't have a deep knowledge of the Maven build lifecycle and its possibilities, any suggestions or pointers are very much welcome.
This is the approach I took. It isn't exactly what I wanted, there's still lots of manual work to do with every WSDL file and is far from the solution I had in mind (having Maven automatically create individual JAR artifacts for every wsdl in the project and using them as dependency).
Specifically, for each WSDL, this approach needs :
Creating a directory containing the WSDL file and a pom.xml containing a distinct artifact name
Adding that directory to the top-level aggregator POM.
Adding a dependency to the WS client JAR artifact in the webapp's POM.
I ended up creating an aggregator (multimodule) Maven project, having one module for each WebService Client, that will produce a JAR artifact with the generated WS client classes (following Maven's convention of one artifact per POM).
For convenience, the plugin that will take care of the WebService client classes generation is defined only once in the main pom.xml, and this POM is the parent of the WS client generation POMs. It is important to note the difference between aggregator and parent POMs. Both concepts are used together in this approach.
There's also a module for the main webapp. Its pom.xml specifies dependencies for each of the WS client JAR artifacts.
This is the outline of the project's directory tree:
| pom.xml
+-- WSClient1
| | WebService1.wsdl
| | pom.xml
+-- WSClientN
| | WebServiceN.wsdl
| | pom.xml
\---MyWebapp
| src
| pom.xml
The aggregator POM:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.myproject</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Aggregator POM</name>
<properties>
<!-- CXF version used for cxf-codegen-plugin -->
<cxf.version>2.7.10</cxf.version>
</properties>
<modules>
<!-- WS Client Modules -->
<module>WSClient1</module>
<module>WSClientN</module>
<!-- WAR Module -->
<module>MyWebapp</module>
</modules>
<!-- Project configuration every child POM will inherit -->
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<!-- WSDL files will be at each project's root level -->
<wsdlRoot>.</wsdlRoot>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Each one of the WS client POMs is extremely simple, just an artifact name and specify the parent:
<?xml version="1.0" encoding="UTF-8"?>
<project xsi...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example.myproject</groupId>
<artifactId>wsclient1</artifactId>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>WebService1 client</name>
<parent>
<groupId>com.example.myproject</groupId>
<artifactId>parent</artifactId>
<version>1.0.0</version>
</parent>
</project>
The webapp's POM doesn't need to be a child of the parent POM because it won't be using the cxf-codegen-plugin, and includes <dependency>s for each one of the WS client artifacts:
<dependency>
<groupId>com.example.myproject</groupId>
<artifactId>wsclient1</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>com.example.myproject</groupId>
<artifactId>wsclientN</artifactId>
<version>1.0.0</version>
</dependency>

Categories

Resources