We have 12 ear files in our SOA layer, we deploy these EARs individually to JBoss. Increasingly we are having trouble managing the dependencies, and the deployment of all these EAR files.
Each EAR is:
built using Maven, and the maven-ear-plugin
contains a webModule for RESTful access like payment-rs/payment
has an API like payment-api-1.1.9.jar, which is often a dependency to other EARs
uses maven version numbers like payment-service-1.1.9.ear
Ideally, we could have a single EAR (or some other format) that we could version and certify together. I've tried adding modules to the parent pom, but that just facilitates building all the individual EAR at the same time.
Is there a way to somehow combine these EAR files?
If the answer is no, any ideas on if we are "doing it wrong" with our architecture? Should we combine the projects? Solve the API dependency issues some other way?
To me it sounds like you should go for single ear with multiple web modules. See the official docs: http://maven.apache.org/plugins/maven-ear-plugin/modules.html
As you would still use SOA the web services could communicate between each other via whatever interface defined, just deployment could be simplified dramatically.
Your project pom.xmls could look like this:
WebModuleA with pom.xml like:
<groupId>???</groupId>
<artifactId>webModuleA</artifactId>
<version>???</version>
<type>war</type>
<dependencies>
<dependency>
<groupId>???</groupId>
<artifactId>payment-service</artifactId>
<version>1.1.9</version>
<type>jar</type>
</dependency>
...
webModuleB with pom.xml like:
<groupId>???</groupId>
<artifactId>webModuleB</artifactId>
<version>???</version>
<type>war</type>
<dependencies>
<dependency>
<groupId>???</groupId>
<artifactId>payment-service</artifactId>
<version>1.1.9</version>
<type>jar</type>
</dependency>
...
payment-service with pom.xml like:
<groupId>???</groupId>
<artifactId>payment-service</artifactId>
<version>1.1.9</version>
<type>jar</type>
...
and finally, the earModule that would contain all the web modules:
<groupId>???</groupId>
<artifactId>earModule</artifactId>
<version>???</version>
<type>ear</type>
<dependencies>
<dependency>
<groupId>???</groupId>
<artifactId>webModuleA</artifactId>
<version>???</version>
<type>war</type>
</dependency>
<dependency>
<groupId>???</groupId>
<artifactId>webModuleB</artifactId>
<version>???</version>
<type>war</type>
</dependency>
...
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.8</version>
<configuration>
<modules>
<webModule>
<groupId>???</groupId>
<artifactId>webModuleA</artifactId>
</webModule>
<webModule>
<groupId>???</groupId>
<artifactId>webModuleA</artifactId>
</webModule>
...
</modules>
</configuration>
</plugin>
That should be basically it.
Moreover, if you want to prevent having payment-service packaged in the each war webModuleX (to reduce the size of the final ear archive), make sure to go for so called "skinny wars": http://maven.apache.org/plugins/maven-ear-plugin/examples/skinny-wars.html
Feel free to ask in detail, if some of the suggestions is unclear or inaccurate.
Related
I need to modify and deploy some liferay modules that I didn't write. The original developer is not with the company anymore and there's almost no documentation on the code. The project is structured differently to the liferay projects I'm familiar with, so I'm struggling with the deployment.
It's a maven project with a number of modules, and when I build it generates multiple jar files. When I copy one of those jar files to my local deployment folder Liferay prints something like:
13:07:23,201 INFO [com.liferay.portal.kernel.deploy.auto.AutoDeployScanner][ModuleAutoDeployListener:70] Module for /Users/ali/LIFERAY/liferay-portal-6.2-ee-sp14/deploy/com.monator.ehp.routes.servicemix.moci-1.6.1.jar copied successfully. Deployment will start in a few seconds.
... and then nothing. If I check the liferay/data/osgi/modules/ directory I do see the jar file is present there, however when I test the behaviour I do not see my changes reflected, even after restarting the tomcat server.
We're running Liferay 6.2 ee sp14 with tomcat and postgres. I believe the modules in question are osgi modules, but I don't think that changes the deployment method?
EDIT: This is the main project pom file, running "mvn install" in the same directory does not create a war file, but does create multiple individual jar files in the various child module folders:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.monator.tools</groupId>
<artifactId>monator-parent</artifactId>
<version>0.7.0</version>
</parent>
<groupId>com.monator.clients.moh</groupId>
<artifactId>camel-routes</artifactId>
<version>1.6.1</version>
<packaging>pom</packaging>
<name>Camel Route Project Parent</name>
<scm>
<url>https://bitbucket.org/monator/ehealth-portal-camel-routes.git</url>
<connection>scm:git:ssh://git#bitbucket.org/monator/ehealth-portal-camel-routes.git</connection>
<developerConnection>scm:git:ssh://git#bitbucket.org/monator/ehealth-portal-camel-routes.git</developerConnection>
</scm>
<modules>
<module>servicemix.routes.parent</module>
<module>liferay.routes.parent</module>
</modules>
<properties>
<camel.version>2.13.2</camel.version>
<osgi.export.package></osgi.export.package>
<osgi.import.package>*</osgi.import.package>
<osgi.bundle.symbolic.name>${project.groupId}.${project.artifactId}</osgi.bundle.symbolic.name>
</properties>
<build>
<finalName>${osgi.bundle.symbolic.name}-${project.version}</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
<configuration>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.4.0</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Bundle-SymbolicName>${osgi.bundle.symbolic.name}</Bundle-SymbolicName>
<Export-Package>${osgi.export.package}</Export-Package>
<Import-Package>${osgi.import.package}</Import-Package>
</instructions>
</configuration>
</plugin>
</plugins>
</build>
<!-- Dependencies only declared for IDE support -->
<dependencies>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-core</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-blueprint</artifactId>
<version>${camel.version}</version>
</dependency>
<dependency>
<groupId>org.apache.aries.blueprint</groupId>
<artifactId>org.apache.aries.blueprint.cm</artifactId>
<version>1.0.5</version>
</dependency>
<dependency>
<groupId>org.apache.activemq</groupId>
<artifactId>activemq-osgi</artifactId>
<version>5.10.0</version>
<!-- Since we're using Maven 3, this is necessary. -->
<exclusions>
<exclusion>
<groupId>com.sun.jdmk</groupId>
<artifactId>jmxtools</artifactId>
</exclusion>
<exclusion>
<groupId>com.sun.jmx</groupId>
<artifactId>jmxri</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
</project>```
Liferay 6.x can deploy war files, not jars!
Maybe your maven projects builds many jars for then build a war file?
Better if you post the pom.xml and the internet crew try to understand the mistery..
EDIT:
This project build osgi jars for Apache Camel to create some custom routes! https://camel.apache.org/ , there are not Liferay modules!
(Maybe Liferay plays as Camel consumer/producer?)
This is My Folder structure -
![Project explorer][1]
--project>
--src
--main
--java
--resource
--target
pom.xml
This is My Pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>com.mkyong</groupId>
<artifactId>spring-security-loginform-xml</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>SpringSecurity Custom Login Form XML</name>
<url>http://www.mkyong.com/tutorials/spring-security-tutorials/</url>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<id>mkyong</id>
<name>Yong Mook Kim</name>
<email>mkyong2002#gmail.com</email>
</developer>
</developers>
<properties>
<jdk.version>1.6</jdk.version>
<spring.version>3.2.8.RELEASE</spring.version>
<spring.security.version>3.2.3.RELEASE</spring.security.version>
<jstl.version>1.2</jstl.version>
</properties>
<dependencies>
<!-- Spring 3 dependencies -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>${spring.version}</version>
</dependency>
<dependency>
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
<version>1.1.1</version>
</dependency>
<!-- Spring Security -->
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-web</artifactId>
<version>${spring.security.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId>
<version>${spring.security.version}</version>
</dependency>
<!-- jstl for jsp page -->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>${jstl.version}</version>
</dependency>
</dependencies>
<build>
<finalName>SpringSecurityHelloWorld</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>${jdk.version}</source>
<target>${jdk.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-eclipse-plugin</artifactId>
<version>2.9</version>
<configuration>
<downloadSources>true</downloadSources>
<downloadJavadocs>false</downloadJavadocs>
<wtpversion>2.0</wtpversion>
</configuration>
</plugin>
</plugins>
<sourceDirectory>${basedir}/src</sourceDirectory>
</build>
</project>
While i am going to modify the code in java file or the controller those are not effecting while I am running the project. I think Maven is not compiling the Java code.
Is the folder structure is correct ?
Where the class files are generated in the project ?
Can any one suggest with explanation.
Based on your question and the comments below it I try to give you a answer:
is the folder structure correct?
Yes ist is. It follows the Maven standard directory structure described here: http://maven.apache.org/guides/introduction/introduction-to-the-standard-directory-layout.html
It however misses a webapp-folder (see next point) which will not make your build fail but end in a war not containing a WEB-INF folder - hence it is not a standard webbapplication as defined by the Java EE standard (http://docs.oracle.com/javaee/6/tutorial/doc/bnadx.html).
Where are the class files generated in the project?
After maven runned the phase compile (mvn compile) of the default lifecycle (http://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html) the compiled class files will be placed under /target/classes.
If you continue to the phase package (mvn package) maven will build a war (jar is the default packaging type which was overwritten in your pom) containing your classes as well as your resources which is placed under /target
Note: If you are building a webapplication you place your website's content such as a deployment descriptor (web.xml) or HTML/JSP/JSF pages etc. under a folder src/main/webapp (the WEB-INF folder should be under src/main/webapp/WEB-INF).
Regarding the comments disscussion
If you expect to see changes in Java files on the fly Maven will not support you out of the box. Maven is a build tool - e.g. if you change something in your project you will request maven to build the project again to have the changes ready in a deployable form (e.g. you have a war file in your /target folder which you can then deploy).
If you want to see changes on the fly you should try a websearch for topics such as Hotdeployment, JRebel, embedded jetty since there are quite a few options available to archive this.
One general approach to have hotdeployment "out of the box" is to point the exploded directory of a hotdeploy-supported (web)(application) server to the exploded directory of your maven build. Right on the same level as you will find your spring-login-security-xml.war the is a folder spring-login-security-xml which contains the unpacked webapplication. This will however not spare you to have a build per change.
This is the first issue that popped up for me when my class files were not being generated. My fix does not apply to this question, but I'm mentioning it here in case it helps someone else.
I had a quick copy and paste setup with a single top level pom.xml. In it I had set
<packaging>pom</packaging>
which caused the java files to be ignored. The fix was to remove the packaging tag, letting it default to jar.
I got a simple maven project and yet frustratingly fail for hours to get it right. The project contains 1 parent module, and 2 submodules (one for ear-packaging, the other for an ejb). Building works successfully, but the ear-packing just doesn't work as expected:
<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>at.betrieb.projekt</groupId>
<artifactId>extended</artifactId>
<version>1.0</version>
</parent>
<artifactId>extended-ear</artifactId>
<packaging>ear</packaging>
<dependencies>
<dependency>
<groupId>at.betrieb.projekt</groupId>
<artifactId>extended-ejb</artifactId>
<version>1.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.7</version>
<configuration>
<version>6</version>
<generateApplicationXml>false</generateApplicationXml>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<jarModule>
<groupId>at.betrieb.projekt</groupId>
<artifactId>extended-ejb</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
</configuration>
</plugin>
</plugins>
</build>
</project>
Now when I look into the packaged folder I see this structure:
|-lib
extended-ejb-1.0.jar
activation-1.1.jar
javaee-api-7.0.jar
javax.mail-1.5.0.jar
|-META-INF
application.xml
What I expected however was this structure:
|-extended-ejb-1.0.jar
|-lib
activation-1.1.jar
javaee-api-7.0.jar
javax.mail-1.5.0.jar
|-META-INF
application.xml
So basically I wanted the ejb outside of the other libraries. These other 3 libraries come from the ejb-module which requires the javaee-api dependency for annotations. Unfortunately it also collects transitive the javax.mail.jar, activation.jar.
Now I really don't know why the structure just doesn't work as expected, by all means I tried to follow this guide step by step.
Ok, after I checked out a project from various maven archetypes I found the error... the minimal error... it's always a minimal error costing huge amounts of time...
In the dependencies section of the ear file, where I define my ejb as dependency, just add this:
<type>ejb</type>
so it's:
<dependency>
<groupId>at.betrieb.projekt</groupId>
<artifactId>extended-ejb</artifactId>
<version>1.0</version>
<type>ejb</type>
</dependency>
Afterwards it works correctly. Obviously it is wrong on the IBM page and on many other pages. Besides I found out the following section is also outdated, and can be completely removed from the ear-plugin section:
<jarModule>
<groupId>at.betrieb.projekt</groupId>
<artifactId>extended-ejb</artifactId>
<bundleDir>/</bundleDir>
</jarModule>
I have some dependencies in my webapp that I've marked as provided because I expect them to be provided by an appserver (maybe a production environment provides these dependencies at the specified versions). How do I simulate that when I'm running tests or in development on my localhost using for example the tomcat7-maven-plugin goals like run?
I can't see any way to do it without manually copying jars around. I can see how to use the test classpath - is there something wrong with what I'm trying to do?
OK, I've found a way of getting this to work - it's reasonable but there's a duplication of dependency information and a magic profile... I feel that the tomcat7-maven-plugin should provide a means of making provided dependencies available in the container when running.
Add a profile that is activated when the tomcat plugin runs, and add the dependencies that have provided scope with compile scope to that profile, eg.
... in project pom ...
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-provided-artifact</artifactId>
<version>1.2.3</version>
<scope>provided</scope>
</dependency>
</dependencies>
...
<profiles>
<profile>
<!-- profile activated as cli param when tomcat7 plugin runs -->
<id>tomcat</id>
<dependencies>
<dependency>
<groupId>com.mycompany</groupId>
<artifactId>my-provided-artifact</artifactId>
<version>1.2.3</version>
<scope>compile</scope>
</dependency>
</dependencies>
</profile>
</profiles>
I use, for example, this:
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<version>2.0</version>
<configuration>
<path>/myApp</path>
</configuration>
<dependencies>
<dependency>
<groupId>com.oracle</groupId>
<artifactId>ojdbc6</artifactId>
<version>11.2.0.3</version>
</dependency>
</dependencies>
</plugin>
and then also include the dependency again later with provided.
We are using maven to build an EAR that contains WAR, the JARS are duplicated on both EAR's root and WAR's lib folder, I read about the skinny jars to remove the jars from the WAR but I don't want this as I want to keep the WAR as stand alone unit,
IS there a way to do it the other way around and remove the JARs from the EAR's root folder ?
attached is the EAR POM
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.6</version>
<configuration>
<modules>
<webModule>
<groupId>com.csv.xyz</groupId>
<artifactId>web</artifactId>
</webModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.csv.xyz</groupId>
<artifactId>web</artifactId>
<version>0.0.1-SNAPSHOT</version>
<type>war</type>
<scope>compile</scope>
</dependency>
</dependencies>
The "maven-skinny-war" solution isn't any drawback in your case. Also have a look at this question and my answer: How to make maven place all jars common to wars inside the same EAR to EAR root?
With this solution you will first get WARs packaged with their own dependencies and second, an EAR module with skinny WARs. So everything is deployable on its own and nothing is duplicated.
I don't think this would be a good idea because of the class loader architecture. If a JAR is part of a WAR, it's defined by the web app class loader, which may result in multiple instances. If it's part of an EAR, it's defined by the enterprise app class loader, which is a different class loader.
To remove a dependency from the EAR lib folder, declare the dependencies as provided in the EAR pom, for example to remove commons-lang:
<dependencies>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
<scope>provided</scope>
</dependency>
</dependencies>
Just make sure if you have EJB modules that they don't require the dependency! Also webModules do not contribute to the EAR's root lib folder, do you have more dependencies in you ear pom?