I've used the maven-ear-plugin with the maven-war-plugin and maven-ejb-plugin to successfully deploy and run an application packaged as EAR to Jboss AS7.
.
|-- META-INF
| |-- application.xml
| |-- MANIFEST.MF
| `-- maven
| `-- com.patrac
| `-- Patrac-ear
| |-- pom.properties
| `-- pom.xml
|-- Patrac-ejb-1.0-SNAPSHOT.jar
`-- Patrac-web-1.0-SNAPSHOT.war
In the application source code directories, the poms are located as follows:
.
|
|-- Patrac-ear
| `-- pom.xml
|-- Patrac-ejb
| `-- pom.xml
|-- Patrac-web
| `-- pom.xml
`-- pom.xml
I can't figure out how to stop a few annoying warning messages when I deploy the application:
12:32:03,958 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-components-ui-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,970 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-components-api-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,984 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-core-api-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
12:32:03,989 WARN [org.jboss.as.server.deployment] (MSC service thread 1-2) Class Path entry richfaces-core-impl-4.0.0.Final.jar in "/content/Patrac.ear/Patrac-web-1.0-SNAPSHOT.war" does not point to a valid jar for a Class-Path reference.
Patrac-web-1.0-SNAPSHOT.war!META-INF/MANIFEST.MF looks like this:
Manifest-Version: 1.0
Built-By: pgarner
Build-Jdk: 1.7.0_02
Class-Path: Patrac-ejb-1.0-SNAPSHOT.jar richfaces-components-ui-4.0.0.
Final.jar richfaces-components-api-4.0.0.Final.jar richfaces-core-api
-4.0.0.Final.jar richfaces-core-impl-4.0.0.Final.jar cssparser-0.9.5.
jar sac-1.3.jar guava-r08.jar
Created-By: Apache Maven
Archiver-Version: Plexus Archiver
The ejb class-path entry needs to be present for the EJB module, for portability, and the richfaces, cssparser and guava class-path entries should NOT be in the WAR's manifest.
The problem is that my WAR depends on all of the JARs, some of which live in WEB-INF/lib (RichFaces), and one JAR, Patrac-ejb-1.0-SNAPSHOT.jar, that lives in the root directory of the EAR. Each dependency needs to be entered in Patrac-web/pom.xml but NOT each of the dependencies should appear in the manifest.
Maven puts the JARs in the correct places, but it puts Class-Path entries for ALL of the JARs into the manifest. It should not do this. It should ONLY put an entry in for Patrac-ejb-1.0-SNAPSHOT.jar.
<!--
According to Java EE 6 spec, the application is portable if
Patrac-web.war's META-INF/MANIFEST.MF contains a Class-Path entry
for Patrac-ejb-1.0-SNAPSHOT.jar.
<optional>true</optional> is the flag that maven-war-plugin uses
to put the entry in MANIFEST.MF without copying Patrac-ejb-1.0-SNAPSHOT.jar
into WEB-INF/lib. This is what I want.
<scope>provided</scope> would cause maven-war-plugin to NEITHER
put the entry in MANIFEST.MF nor copy Patrac-ejb.jar into WEB-INF/lib,
which would not be good.
No tag at all would cause maven-war-plugin to BOTH put the entry in
MANIFEST.MF and copy Patrac-ejb.jar into WEB-INF/lib, which would
also not be good.
-->
<dependency>
<groupId>com.patrac</groupId>
<artifactId>Patrac-ejb</artifactId>
<type>ejb</type>
<optional>true</optional>
</dependency>
<!--
These two dependencies are used to copy
the other JAR files into WEB-INF/lib and there
should not be any class-path entries for such
JARs in MANIFEST.MF, in order to avoid the
error messages.
-->
<dependency>
<groupId>org.richfaces.ui</groupId>
<artifactId>richfaces-components-ui</artifactId>
</dependency>
<dependency>
<groupId>org.richfaces.core</groupId>
<artifactId>richfaces-core-impl</artifactId>
</dependency>
I'm using the most recent maven-war-plugin version, 2.2. How do I tell the maven-war-plugin to put the "non-ejb" JARs into WEB-INF/lib while not putting class-path entries in MANIFEST.MF?
Any advice or pointers you have are greatly appreciated.
References:
Maven War Plugin
Maven Ear Plugin
The Maven archiver, used by the Maven WAR plugin, provides a means to generate Class-Path entries in the WAR's manifest but unfortunately the archiver takes an all-or-nothing approach. Once you pass addClassPath=true to the archive configuration, the archiver puts Class-Path entries for all of the WAR's required- and optional dependencies into the manifest.
However, some entries simply do not belong in there. Class-Path entries are used to denote "Download Extensions," or references to JARs external to the WAR. JARs located in WEB-INF/lib should not, therefore, have Class-Path entries in the WAR's manifest. Maven's War plugin breaks this rule when you set addClassPath=true in the archiver.
Moreover, when you pass addClassPath=true to Maven's archiver, it gives all of the Class-Path entries the same directory prefix -- no matter where the dependencies are located within the EAR. This causes problems when optional- and required dependencies are located in separate locations such as the EAR root directory, EAR lib and WAR WEB-INF/lib.
Naturally, when one deploys an EAR whose WAR manifest contains the above errors JBoss throws warnings if the WAR class loader can ultimately find a dependency (JARs located in WEB-INF/lib) or errors if the class path prefix is wrong (e.g. on an EJB JAR or a dependency in the EAR lib directory).
Therefore, if your WAR, like mine, depends on an EJB module, located at the root of the EAR, and any number of dependencies that are located inWEB-INF/lib, Maven archiver will generate Class-Path entries for all of the dependencies and they will all have the same prefix regardless of their location within the EAR.
Not good.
The problem would be ameliorated somewhat if the archiver would provide a means to exclude Class-Path entries of the JARs located in WEB-INF. But it does not.
Here's a summary of the outcome for each dependency setting when one uses addClassPath=true:
Setting Generate Copy JAR into
Class-Path WEB-INF/lib
Entry
1. <scope>provided</scope> NO NO
2. <optional>true</optional> YES NO
3. (no option -- default) YES YES
4. ????? NO YES
What is needed is coverage for situation #4, above: do not create a Class-Path entry and, yes, do copy the JAR into WEB-INF/lib. Maven archiver should implement this behavior by default.
The best solution I can think of is to use brute force and turn off the Maven archiver's automatic Class-Path entry generation. Instead, I explicitly create a Class-Path entry for the EJB module in the WAR's manifest using the archiver's manifestEntries option. The way to do this is to remove the following from Patrac-web/pom.xml:
<manifest>
<addClasspath>true</addClasspath>
</manifest>
and replace it with this:
<manifestEntries>
<Class-Path>Patrac-ejb-${project.version}.jar</Class-Path>
</manifestEntries>
Using this configuration only one Class-Path entry, for the EJB module, is created explicitly.
For those JARs with need to be excluded from MANIFEST and from WEB-INF/lib you need to mark them as <scope>provided</scope>. That means JAR files will be provided by the container (and that is EAR in your case).
For other options check WAR manifest guide.
The ejb class-path entry needs to be present for the EJB module …
The class-path only needs to be present for EJBs modules (in the root of the EAR) who reference other EJB modules (in the root of the same EAR)
read specifically about skinny wars
http://maven.apache.org/plugins/maven-war-plugin/examples/skinny-wars.html
Related
Currently I have a problem during migrating a Java Enterprise project form old WAS-8 to Liberty Profile 17. In my case the environment cannto find a bunch of css/js files in the richfaces jar. Loading a page in the browser, WLP17 writes warnings like this into the logfile:
[WARNING ] SRVE0190E: File not found: /org.richfaces.resources/javax.faces.resource/org.richfaces.staticResource/4.5.17.Final/PackedCompressed/org.richfaces/jquery.js
I build the project using maven and I defined the richfaces dependency in the parent pom like this:
<dependency>
<groupId>org.richfaces</groupId>
<artifactId>richfaces</artifactId>
<version>4.5.17.Final</version>
</dependency>
Then, I have several EJB and WAR projects that are packed together into an EAR file. The WAR projects using richfaces contain a richfaces dependency with scope provided:
<dependency>
<groupId>org.richfaces</groupId>
<artifactId>richfaces</artifactId>
<scope>provided</scope>
</dependency>
Finally, the EAR pom has the dependency on richfaces to ensure that the library is included in the EAR file. For any reason the liberty is not able to find resources located in the richfaces jar.
I inspected the created EAR file, it contains the richfaces libraries. Then, I inspected the richfaces libraries, the also contain the files that are not found.
Is there any more configuration I have to do?
Jar libraries which are expected to serve static files from META-INF/resources/ should be bundled in the web application WAR. Section 4.6 from the Servlet 3.0 spec is relevant:
The getResource and getResourceAsStream methods take a String with a
leading “/” as an argument that gives the path of the resource
relative to the root of the context or relative to the
META-INF/resources directory of a JAR file inside the web
application’s WEB-INF/lib directory...
#wtlucy's comment did solve my problem. Thank you.
I have put the richfaces libraries into the WAR files that need these libraries.
I have fat-jar spring boot application in jar A.jar
in this fat-jar I have folder lib with two jar files (dependencies)
let's say B.jar and D.jar in each of these jar file (B and D) we have application.properties (resource) which is loaded automatically during initialization of application.
Unfortunately application.propertiesfrom D.jar is loaded before application.properties from B.jar
How to load application.properties from B.jar instead of application.properties from D.jar ?
Depends on location on classpath always first application.properties will be loaded. Order of jar files on classpath in my case (maven pom.xml) depends on order of registering dependencies in pom.xml
If I use
<dependencies>
<dependency>
//B.jar
</dependency>
<dependency>
//D.jar
</dependency>
</dependencies>
then application.properties from B.jar will be loaded.
The war dependency mentioned in jar project just to get copied from copy-dependency plugin/assembly plugin to use for some custom packaging. But plugin skip the war dependency , Is this plugin behaviour?
or need something else?
<dependency>
<groupId>com.external.modules</groupId>
<artifactId>war-jboss</artifactId>
<version>1.0.0-SNAPSHOT</version>
<type>war</type>
</dependency>
Maven assembly plugin works on include and exclude. You would not be including your war file correctly. Check if you are using the correct regular expressions to include the war file in assembly plugin.
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.
I have a Maven project that is packaged as jar.
And I also have a Maven project that is packaged as war. This war project has a tld file and some xhtml files (the tag libs). The structure of the war project is (basically):
pom.xml
src
main
java
...
webapp
WEB-INF
my-facelets.taglib.xml
facelets
aTag.xhtml
anotherTag.xhtml
META-INF
my-facelets.taglib.tld
And then appeared a requirement to remove those xml, xhtml and tld files from the war project and package them into the jar project. So my first try was add in the jar project's POM:
<resources>
<resource>
<directory>src/main/tld</directory>
<targetPath>META-INF</targetPath>
</resource>
<resource>
<directory>src/main/taglib</directory>
<targetPath>WEB-INF</targetPath>
</resource>
</resources>
And put the files, of course, into src/main/tld (the ones I wanted to export into META-INF) and src/main/taglib (the ones I wanted to export into WEB-INF). And the jar was created as I wish:
myjar
com
my
classes
WEB-INF
META-INF
my-facelets.taglib.tld
WEB-INF
...
And then I added this new jar to my first war project, as a maven dependency.
The problem is that those .tld, .xhtml, .xml files that are inside the jar's META-INF, WEB-INF (the jar is inside war's WEB-INF/lib) are not recognized. Apparently they should be directly into the war structure, unless some other configuration is performed. This is a must-have requirement, because multiple war projects will use the features (classes and taglibs) of the jar project.
The practice these days is to put the TLD files into the tag library JAR and let the class loader find them. Download the Apache JSTL JARs and see how they do it. I'd recommend following that convention. It'll simplify your app too, because you won't have to declare the TLD in your web.xml file: just put the JAR in your CLASSPATH and make sure that the URI in your .jsp matches that in the TLD.
#duffymo - Your solution totally works. Adding graphic to your description.
Create a maven project that generates JAR. keep the structure like this below
src -- main
|-- java
| `-- net
| `-- madhur
| `-- helloTag.java
`-- resources
`-- META-INF
`-- tags
`-- customTags.tld
To your customTags.tld file add uri something like this
<uri>http://www.xyzabc.com/taglibs/customTags</uri>
Accessing tags in you WAR file
War should have following structure
META-INF/
META-INF/MANIFEST.MF
WEB-INF/
WEB-INF/classes/
WEB-INF/lib/
WEB-INF/lib/{tagLibrary}.jar
WEB-INF/web.xml
WEB-INF/customTags.tld
web.xml
<jsp-config>
<taglib>
<taglib-uri>www.xyzabc.com/taglibs/customTags</taglib-uri>
<taglib-location>/WEB-INF/customTags.tld</taglib-location>
</taglib>
</jsp-config>
Using tag in FTL or JSP file
Ftl:
<#assign ct = JspTaglibs["www.xyzabc.com/taglibs/customTags"]>