How do you share Java Caching System (JCS) resource across multiple EJB - caching

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.).

Related

How to control module loading order in Liberty profile

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.

NoClassDefFoundError: in Web Sphere liberty Profile

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

WebSphere7 classloading Issues

I am just wondering, if the below is possible with Websphere or not?
I have an Enterprise application using Websphere 7 and with PARENT_LAST classloading mode. I am now trying to use a third party feature namely, gemfire in the application. My application with gemfire runs perfectly in PARENT_FIRST classloading mode. But, I can see some linkage errors occuring because of PARENT_LAST setting. Temperarly, I could solve them by removing the classes that are conflicting from gemfire jar(By this, I am actually asking those removed classes to be loaded from web app server). But, I am not sure if this will create some bigger issues as my appliaction grow to its fullest.
My question is : Suppose we have abc.jar in both web app server and also in gemfire.jar, with PARENT_LAST loading mode.Is it possible to solve the above class conflicts by not removing any class files from jars, instead tell the classloading mechanism to use the class loaded from web app server at a particular case and use the same class loaded from gemfire jar(meaning load from application) at another case?
Thanks
Yes, it is possible. We are using a similar setup. You should be very careful though and only use the exact same jars (or at least the same classes) in all the places you need to have them.

Websphere: Does parent_last affect other applications?

Does parent_last affect other applications ?
Is my application using parent_last affected by other applications?
The server is set to "Multiple Classloaders" (one for each application IIUC).
In my understanding, this would mean that all classes are loaded from the application, correct?
What happens if another application loads a class present in websphere extensions, and lateron my application uses that class. Will it be reloaded, or will the one from parent be used? (it might be incompatible to the classes in my application).
The websphere manual says:
"By specifying Classes loaded with local class loader first (parent last), your application can override classes contained in the parent class loader, but this action can potentially result in ClassCastException or LinkageErrors if you have mixed use of overridden classes and non-overridden classes."
But I do not understand this potential risk. Can somone please provide examples for this?
Classes loaded by application class loader cannot interfere in any way with those loaded by other applications since application classloaders are isolated from each other.
The quote that you provided warns about potential problems that might occur when libraries have transitive dependencies. For example, your application uses libraryA that depends on libraryB. LibraryA is some sort of "standard" library provided by application server, so you don't package it with the application. Then, if for some reason you need to have libraryB in the application and the version of it is different from the one expected by libraryA, you might have problems with incompatibility.

share common data in wars under ear

To reduce database hits, I've used static variables to store data from database.
At time of WAR deployment this data is stored in these variabes as it is not changing so frequently.
This scenario was working fine as the scope was with only single a WAR. Now I have another application where I need access to these varibles
But due to different application scope,I'm unable to access them in another application.
Also I'm having an EAR which encloses both above WAR and one JAR containing some common buisness logic of both WARs.
So under EAR is it possible to share these variables via JAR or using some different approach?
If any javaEE concept can help in this scenario, then please let me know about it also.
I'm using maven with Jboss7.1.1.Final for this
You should use Infinispan, the built-in caching mechanism of JBoss 7 https://docs.jboss.org/author/display/ISPN/Getting+Started+Guide+-+JBoss+AS+7. Caching data in static fields is generally frowned upon in Java EE.
However should you still want to cache your data in static fields you need to make sure the class with the cache was to be shared across all WARs. This means you have to create skinny WARs.
Looks like you need an Enterprise Caching Solutions. There are lots of choices on the market. They include but not limit to
Open Source framework
Memcached
EHCache
Infinispan (mentioned by Phillipe)
Commercial product
Oracle Coherence
GigaSpaces XAP
GemFire
For your second question, as long as your JAR is deployed in the EAR/lib folder, you should be fine.

Resources