Maven EJB packaging with dependent libraries - java

Im facing an issue how to correctly package my enterprise (EAR) application with simple WAR and EJB3 module for JBoss7 application server. The thing is, that EJB module is using XML-RPC library (from Apache) and Im still getting NoDefClassFound (classes from this xmlrpc lib) during deployment of EAR.
The thing is, that maven-ejb-plugin does not package dependencies within final EJB jar but maven-ear-plugin does package it at the root of EAR directory.
When EAR gets deployed, INSTALL is invoked on inner EJB module but it does not find xmlrpc lib class (it is not packaged with EJB jar but EAR and it does not have any entry in manifest).
EJB pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cz.ctu.fee.voxport.app_logic</groupId>
<artifactId>core</artifactId>
<version>1.0</version>
<packaging>ejb</packaging>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>6.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.xmlrpc</groupId>
<artifactId>xmlrpc-common</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.xmlrpc</groupId>
<artifactId>xmlrpc-client</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ejb-plugin</artifactId>
<version>2.3</version>
<configuration>
<ejbVersion>3.1</ejbVersion>
<archive>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Is there any way how to cleanly solve this using maven?

I managed to solve the problem. It seems that these libraries has to be packaged within /lib directory and not in root of EAR. Adding defaultLibBundleDir element solved the problem.
E.g.:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.6</version>
<configuration>
<defaultLibBundleDir>lib</defaultLibBundleDir>
...

Did you leave the <addClasspath>true</addClasspath> on the EJB config?
Well, you can leave it like this, but you'll get a heap of log entries (WARN) on server start complaining about the classpath entries.
I prefer to set it to false. <addClasspath>false</addClasspath>

Related

JAR under EAR(src/main/application/lib) are not part of ClassPath in Maven - [Resolved]

I am working on converting a J2EE application to Maven where the EAR project will contain a WAR module. I have followed the below URL to convert the project and it does work with some minor changes:
https://www.ibm.com/docs/en/wasdtfe?topic=projects-converting-existing-maven
In the current project, there are some libraries under the EAR folder which I cannot move to the local maven repository. The reason is old legacy code which expects these library names to be intact (myCommon.jar and no version to be added like myCommon-1.0.jar).
As a workaround, I placed these libs under EAR->src->main->application->lib folder. There is no build failure observed but the major problem is with the ClassPath for these EAR lib files as shown below:
[err] java.lang.ClassNotFoundException: com.myClass.classFromWAR
[err] at java.lang.Class.forNameImpl(Native Method)
[err] at java.lang.Class.forName(Class.java:332)
E.g. myCommon.jar contains code like the below:
public void EARLibFunc( string classNameFromWAR){
.........
//E.g. classNameFromWAR = "com.myClass.classFromWAR";
final Class warClass = Class.forName( classNameFromWAR );
.........
}
Calling above function from the java files inside WAR module reports ClassNotFoundException: EARLibFunc("com.myClass.classFromWAR");
The directory structure looks like the below:
WARProject
-src
----com
--------myClass
------------classFromWAR.java
EARProject
-src
----main
--------application
------------lib
----------------myCommon.jar
The jar files from EAR/src/main/application don't seem to be part of the ClassPath.
Can you please suggest the best practice to handle such an issue? What should be the correct layout of the EAR libraries to make it part of the ClassPath? Please be informed that the code from the EAR libraries cannot be changed (legacy code dependency issue).
For reference here are my pom settings:
WARProject pom.xml:
.......
.......
<groupId>MyApp</groupId>
<artifactId>MyApp</artifactId>
<version>3.5</version>
<packaging>war</packaging>
<description>MyApp Maven</description>
........
<build>
<resources>
<resource>
<directory>Java Source</directory>
<excludes>
<exclude>**/*.java</exclude>
</excludes>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.0.0</version>
<configuration>
<warSourceDirectory>Web Content</warSourceDirectory>
</configuration>
</plugin>
</plugins>
</build>
......
EAR Project pom.xml (contains WAR module as dependency):
.....
<groupId>EARProject_EAR</groupId>
<artifactId>EARProject_EAR</artifactId>
<version>3.5</version>
<packaging>ear</packaging>
<description>My Project EAR</description>
<build>
<plugins>
<plugin>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10</version>
<configuration>
<version>7</version>
<skinnyWars>true</skinnyWars>
<defaultLibBundleDir>lib</defaultLibBundleDir>
<archive>
<manifest>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<addClasspath>true</addClasspath>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>MyApp</groupId>
<artifactId>MyApp</artifactId>
<version>3.5</version>
<type>war</type>
</dependency>
</dependencies>
......
SOLUTION:
The crash reported for the CLASSPATH is resolved. Since I am moving an old legacy application to Maven, there were some old references to be cleaned-up. Below changes were required:
There were duplicate classpath references in the eclipse Project
(Project -> Properties -> Java Build Path). Even though I had
dependencies mentioned in the pom.xml of the WAR file, the project
properties were also having its references. This may or may not be
the real reason.
Reverted earlier workaround solution. Removed libraries from
EAR->src-main->application->lib and added those as dependency in the
WAR pom.xml reference. Though it has re-created other legacy issue
but I believe this will adhere to the best practices.
I think, it should be possible this way:
Install the jar in your local maven repository.
Configure the maven-ear-plugin to include third party libraries as shown here.
Add <bundleFileName>myCommon.jar</bundleFileName> to jarModule in order to give your JAR file the desired name within the EAR.
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>3.2.0</version>
<configuration>
[...]
<modules>
<jarModule>
<groupId>artifactGroupId</groupId>
<artifactId>artifactId</artifactId>
<includeInApplicationXml>true</includeInApplicationXml>
<bundleFileName>myCommon.jar</bundleFileName>
</jarModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
More information can be found at the usage page of the plugin.

How can I remove maven dependency jar in Eclipse

I'm really new to Maven and just converted my app-engine project to a Maven project.
I've added dependencies in the pom.xml file in order to get rid of the errors.
but now I get in my code
The method getPart(String) is undefined for the type HttpServletRequest
So after doing a bit of research on Stack Overflow it appears I need to have a single and updated package of servlet-api to make that work properly.
Apparently I may have a conflict with an older version that is in my Maven dependencies but I never added it in the pom.xml and now I'm stuck with this jar not knowing why it is imported and how I can delete it.
Here is my pom.xml:
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>my-project</groupId>
<artifactId>my-project</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>war</packaging>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-war-plugin</artifactId>
<version>3.2.1</version>
<configuration>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<filtering>true</filtering>
<targetPath>WEB-INF</targetPath>
</resource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>com.google.cloud.tools</groupId>
<artifactId>appengine-maven-plugin</artifactId>
<version>1.3.1</version>
<configuration>
<deploy.promote>true</deploy.promote>
<deploy.stopPreviousVersion>true</deploy.stopPreviousVersion>
</configuration>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>com.mailjet</groupId>
<artifactId>mailjet-client</artifactId>
<version>4.2.1</version>
</dependency>
<dependency>
<groupId>com.google.appengine.tools</groupId>
<artifactId>appengine-gcs-client</artifactId>
<version>0.8</version>
</dependency>
</dependencies>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
</project>
and here are images of what I get in Maven dependencies in my build path.
my guess is that the error comes from having a 2.5 version of the servlet-api.
So any help is greatly appreciated, I saw something about the exclusion
tag but don't even know where to put it as it doesn't look like anything in the pom.xml is asking for this jar.
You'd better open in Eclipse your pom.xml file and switch to the "dependency hierarchy" tab. Look for the undesired library (type in "serlvet" in the filter) and add exclusion on it through the context menu. This will modify your pom.xml file.
Delete project from workspace and don't check Delete project content on disk. Delete the jar from .m2 folder as well. Import the project using eclipse. Open the pom file and click on dependency Hierarchy. Select the the jar you want to delete. Right click and click on Exclude Maven Artifact. Next time you run the proejct it will not download the jar.

ClassNotFoundException with Classpath for WAR in EAR with shared libs?

I've got an EAR which contains a WAR and an EJB (jar). The EJB and the WAR share some libraries, so I wanted to produce a skinnyWar using maven-ear-plugin.
I have my ear pom configured with the shared libs as dependencies, and have the <skinnyWars> option set to true.
I see my EAR is properly built; the common libs are extracted from my WAR and placed in the EAR.
My problem, when I launch my EAR on Websphere 8.5, is that the WAR is unable to find classes which remain in the WAR/WEB-INF/lib folder.
I have checked the MANIFEST.MF in the war/META-INF/ and see that all the libs are listed (both those in the war/web-inf/lib folder as well as the common libs), however I keep getting ClassNotFoundException whenever I try to access classes from within the WEB-INF/lib/xxx.jar.
(snippets from the pom.xml)
<dependencies>
<dependency>
<groupId>com.webinfo</groupId>
<artifactId>WebInfoWebApp</artifactId>
<version>${project.version}</version>
<type>war</type>
</dependency>
<dependency>
<groupId>com.webinfo</groupId>
<artifactId>WebInfoEJB</artifactId>
<version>${project.version}</version>
<type>ejb</type>
</dependency>
<!-- In order to make skinnyWars, need to list all the common dependencies of the EAR here -->
<!-- Use the ejb pom to list all the ejb dependencies here automatically -->
<dependency>
<groupId>com.webinfo</groupId>
<artifactId>WebInfoEJB</artifactId>
<version>${project.version}</version>
<type>pom</type>
</dependency>
</dependencies>
<build>
<plugins>
<!-- EAR plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<version>2.10</version>
<configuration>
<defaultLibBundleDir>/</defaultLibBundleDir>
<skinnyWars>true</skinnyWars>
<archive>
<manifestFile>META-INF/MANIFEST.MF</manifestFile>
<manifest>
<addClasspath>true</addClasspath>
</manifest>
</archive>
<modules>
<webModule>
<groupId>com.webinfo</groupId>
<artifactId>WebInfoWebApp</artifactId>
<bundleFileName>WebInfoWeb.war</bundleFileName>
</webModule>
<ejbModule>
<groupId>com.webinfo</groupId>
<artifactId>WebInfoEJB</artifactId>
<bundleFileName>WebInfoEJB.jar</bundleFileName>
</ejbModule>
</modules>
</configuration>
</plugin>
</plugins>
</build>
EAR manifest.mf:
Class-Path: WebInfoWeb.war WebInfoEJB.jar core_business-5.1.0.jar core
_common-5.1.0.jar core-5.1.0.jar ICS_SSEClient-3.5.15.jar com.ibm.uti
l.ini-1.0.jar ICS_SecuredUserContext-3.5.15.jar ICS_SecuredUserContex
tClient-3.5.15.jar ICS_ManageClient-3.5.15.jar ICS_ConfigurationClien
t-3.5.15.jar ICS_Common-3.5.15.jar
WAR manifest.mf:
Class-Path: WebInfoJava-3.9.0-SNAPSHOT.jar com.ibm.util.ini-1.0.jar ow
asp-esapi-full-java-1.4.jar regexp-1.2.jar com.ibm.regex.REUtil-1.3.0
.jar ojdbc6-11.2.0.3.0.jar AdobeFDF-1.0.jar core_business-5.1.0.jar c
ore_common-5.1.0.jar core-5.1.0.jar ICS_SSEClient-3.5.15.jar ICS_Secu
redUserContext-3.5.15.jar ICS_SecuredUserContextClient-3.5.15.jar ICS
_ManageClient-3.5.15.jar ICS_ConfigurationClient-3.5.15.jar ICS_Commo
n-3.5.15.jar
Exception:
java.lang.ClassNotFoundException: com.calculator.sendmail.SendMailCommunicationBusinessFactory
But SendMailCommunicationBusinessFactory is located in WebInfoJava-3.9.0-SNAPSHOT.jar which is in the war/WEB-INF/lib folder.
Am I doing something incorrect in the way the classpath is setup/configured?

Datanucleus JDO in maven assembly jar

I used the maven assembly package to create a single monolithic jar. Included is the datanucleus package, but I am getting errors because I did not maintain the OSGI structure (plugins.xml & META-INF/META-INF.MD). The answers on stackoverflow([question]: Datanucleus, JDO and executable jar - how to do it?) do not provide answers on how to create the single deployable jar.
Does anyone know what maven directives I can use to ensure OSGI structure?
So, the problem is that packing everything into a monolithic jar is that the OSGI structures get overritten by the OSGI structure of other jars. The benefit of the monolithic jar was to have a single file to push to the server but not necessary (since I was using capistrano to push to the server)
Instead, it's easier to just copy the jars into the final build directory. Heroku's Java setup has a perfect example of this:
https://devcenter.heroku.com/articles/java
<?xml version="1.0" encoding="UTF-8"?>
<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>
<groupId>com.example</groupId>
<version>1.0-SNAPSHOT</version>
<artifactId>helloworld</artifactId>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-servlet</artifactId>
<version>7.6.0.v20120127</version>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>servlet-api</artifactId>
<version>2.5</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.4</version>
<executions>
<execution>
<id>copy-dependencies</id>
<phase>package</phase>
<goals><goal>copy-dependencies</goal></goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

How to add build ear file containing only dependency jars in pom

I would like to create an ear containing only dependency jar files using maven.
<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">
<dependencies>
<dependency>
<groupId>groupId</groupId>
<artifactId>artifactId</artifactId>
</dependency>
......
......
......
</dependencies>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-ear-plugin</artifactId>
<configuration>
<modules>
<jarModule>
<groupId>groupId</groupId>
<artifactId>artifcatId</artifactId>
<includeInApplicationXml>true</includeInApplicationXml>
</jarModule>
</modules>
...............
...............
</configuration>
</plugin>
</plugins>
</project>
Maven created application.xml automatically which has entries for these jars but still, when deploying, I am getting message in console - "No modules found in ear."
Could you help me out what am I missing here.
An EAR file should contain WARs, RARs, SARs, and EJB JARs. Anything else, including basic library JARs, are unimportant as far as the EAR is concerned and and EAR with just those kind of files is useless as far as a Java EE Application Server is concerned.

Categories