I have deployed the one ear inside the dropins folder and one of the war file from the ear is referencing the jar which i kept outside folder (Shared->config->lib->global). External jars which i kept global folder is again referring few jar which resides in the ear and this time i am getting "java.lang.NoClassDefFoundError"
Can you please suggest how to give reference .
server.xml
<webApplication contextRoot="/xyz" id="zyx" location="xyz.ear" name="xyz" type="ear">
<classloader commonLibraryRef="global,filterjars"></classloader>
</webApplication>
Common shared libraries cannot load classes from application binaries. When using common libraries, you can think of them as a one-way connection.
The application's classloader can delegate to common shared libraries, but not the other way around.
Common libraries are implemented as their own classloader so they must contain all dependencies.
On the other hand, private libraries have their classpaths appended to the application classloader's classpath - so they could load classes provided by the application, but this is not a good practice. For example, if a private library depends on ClassA that application1 provides, it will work just fine for application1, but might break in application2 that might not provide ClassA (or might provide an incompatible version of it).
If you have classes in your shared libraries that depend on classes in your application, I would either recommend putting all of those classes in the shared library - or putting all of the shared library classes in the application (or WAR, etc.). I personally prefer the latter - self-contained applications are much more portable and less likely to run into classloader/dependency issues (i.e. app1 needs version X of some dependency, but app2 needs need version X+5...).
Hope this helps,
Andy
Related
I have an ear file with a web module and a ejb module(just used for message driven beans). The ejb module has dependency on web module and it's classes. I would need to load the web module first and then ejb module. But the liberty always loading the ejb module first causing com.ibm.ws.container.service.state.StateChangeException: java.lang.NoClassDefFoundError:
How to control the order of modules loading within the same ear file? On traditional webshpere there is an option called 'Starting weight'. Whichever module has lowest value takes precedence and loads it first. so the application works good on tradition Websphere. However, this property seems missing on Liberty. I already looked at this. It only talks about deploying the multiple war files and their order.
If your EJB module depends on Web, that is bad design. It should be the other way around.
If you have such situation , proper way would be to extract shared classes in to a common jar file, let say mycommon.jar and then put that into ear\lib folder. In this way they will be visible by both modules ejb and web.
If your EJB module depends on the javax web api (e.g. servletRequest) that is even worse, and you should redesign such classes to POJO DTOs.
As a last resort you could try what is described here and add <initialize-in-order>true</initialize-in-order> in your application.xml.
FRowe's solution will not work, as classes are not shared between the applications, so changing load order of apps will not help. Each Java™ EE application has its own class loader in a running Liberty server.
Consider using the ability to control app start order as described here: https://www.openliberty.io/blog/2020/06/05/graphql-open-liberty-20006.html?_ga=2.4728563.17466047.1620833568-1423690488.1614284842&cm_mc_uid=99965752544816136653536&cm_mc_sid_50200000=61078141620909829332#ORDER
You'll have to deploy the war module as an app instead of packaging it within the ear, but you should be able to achieve the proper ordering.
I have multimodule maven application. Inside the main directory where parent pom resides I have some modules. I am in the process of adding another one on the same level as the other modules. The application is packages as EAR and deployed into Websphere, this EAR is configured to use shared library which basically is a directory containing jars. In this shared library Apache Crimson resides which is used by some of the modules. I am adding the new module based on Spring Framework 4.0.0.RELEASE. The whole project is a legacy and uses Java 6 and Hibernate 2.1 :( . The problem is that this Crimson make my new module crashing during deployment:
BeanDefinitionStoreException: Parser configuration exception parsing
XML from ServletContext resource [/WEB-INF/spring/root-context.xml];
nested exception is javax.xml.parsers.ParserConfigurationException:
Unable to validate using XSD: Your JAXP provider
[org.apache.crimson.jaxp.DocumentBuilderFactoryImpl#706b4db8] does not
support XML Schema. Are you running on Java 1.4 with Apache Crimson?
Upgrade to Apache Xerces (or Java 1.5) for full XSD support.
So I added to my new module this:
`<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.6.2</version>
</dependency`
But application still takes crimson.jar from the shared library. I tried to exclude this crimson.jar from parent pom but still it is taken from shared library.
Crimson is required by some other modules being packaged as jars hence the crimson is present ar EAR/lib level.
Another try was to change classloader order to take jars from the new module first and then go upward in the hierarchy (my new war module then parent ear). But this gave me some other exception.
The question is - how being in WAR module inside EAR module not take the jar from the ear level (it was also included in EAR/lib) and take from the WAR level only?
If parent-last class loading in the WAR doesn't work (perhaps due to something else in the WAR that can't be safely run with that delegation pattern), then I'd recommend an isolated shared library associated with the WAR. In the WAS administrative console, create a shared library with a class path containing the parser jar(s) you need, select the "use an isolated class loader for this shared library" option, then associated that shared library with the web module that needs it.
Isolated shared libraries utilize parent-last class loading, but only for the jars in the library rather than for the entire EAR or WAR. Because of that, you can target it to only the jars that you really NEED to use that type of delegation. The isolated library should allow you to use Xerces in the WAR while still using Crimson in the EAR.
The size of my EAR file has reached around 100 MB after adding many exetrnal jars.
Environment : Java Spring/Websphere application server/Maven
Please share the tips to reduce the size of an EAR file.
Seems the exteral jars contribute most to the large size. Is it possible to follow an approach like below, if so how to do that?
Do the maven build with compile scope for large jars
Keep the large sized jars in app server lib, with this will the app take these jars at runtime from appserver?
Thanks
Smitha
You should really review your jars, especially poorly done Maven builds add a lot of unnecessary jars to the application (like jta, servlet, jee-api, etc..), so make sure you don't have them. Sometimes jars are duplicated in every web module you have in the EAR.
Second WebSphere is Java EE 6 server, so it provides lots of common features like JAX-WS, JAX-RS, JPA, etc..., so you should consider using them, before throwing all that as third party libraries in your application.
If you want to use shared library approach, do not put the jars in the server lib folder or server classpath. This is not recommended.
Create Shared library via Environment > Shared libraries see here and assign them to the application.
To reduce the War size you can consider
Static Content :Keep the Static content like images etc out of the war file and refer them via application using references to location.
Shared Libs : if majority of the size is contributed by Shared Libs you can separate that out of war. to do that you can place the war libraries in one of the following locations
a) In Server Lib folder, Not Recommended since different apps might use diff versions.
b) In Server App Lib Folder
b) In a shared folder and including that folder into class path .
c) Use exploded war deployment deploying only changes.
I'm hitting the same problem described in here, but I don't know my websphere version at the time
More questions
1) does Removing commons-logging-1.1.jar fix it?
2) what if I really need to put commons-logging-1.1.jar in my application? How can I fix this?
Theres a fix pack of ibm for this.
https://www-304.ibm.com/support/docview.wss?uid=swg21502693
This happens because the class org.apache.commons.logging.impl.Jdk14Logger is loaded by a different classloader than the one that loaded the Log interface.
According to IBM's documentation, whenever you use a third-party library that WebSphere itself uses for its own internal purposes, you must:
Set your EAR's classloader policy to PARENT_LAST; and
Ensure that your EAR is self-sufficient. That is, that your third-party libraries (and their dependencies) are bundled within the EAR.
In your case:
Set your EAR's classloader policy to PARENT_LAST
Include commons-logging-1.1.jar within your EAR (you can place it in the "EAR Library" directory, usually EAR/lib).
I am using JCS to store the ldap search results which should be shared by multiple EJB. I have created a singleton class to initialize JCS only once but due to EJB's classloader, it's been initialized multiple times with its own copy. so search resources are not shared.
How are you guys resolving issue where you need to share the cache across multiple beans?
I am looking for cache within JVM. (Not the remote e.g memcached etc.).
Glassfish is used as an application server.
I haven't been able to test it yet, but I think that one of the techniques explained in the "Circumventing Class Loader Isolation" chapter of the Application Development Guide for the version of Glassfish you are using may solve you problem.
Short version, at least valid for versions 2-3-4 : use the Common Classloader (what exactly this common classloader does and its relation to the other classloaders is explained in the same manual). There are several ways to do this:
copy the jar to domain-dir/lib
or copy the jar to as-install/lib
or run asadmin add-library --type common /path/to/your.jar (will only work in version 4 iirc)
There are several questions here on SO that are related to "Circumventing Class Loader Isolation" (just use that search term), look there for examples and more discussion.
Simply put, the singleton will likely "live" where your caching implementation class lives, as that's the classloader in the hierarchy that "owns" the class.
So, if each EJB is separately deployed, with their own copy of the cache lib jar, they'll each get their own copy.
If your beans are deployed in a composite EAR, sharing a single instance of the lib jar, then that cache will be shared across the beans in the EAR.
If you remove the lib from the deployment completely, and put it outside the container ($DOMAIN/lib/ext for example), then that cache will be shared by EVERYTHING in the domain (EJBs, EARs, WARs, etc.).