ClassCastException when call local ejb3 from different classloader on Websphere 7 - ejb-3.0

I have two ears, ear1 contains an ejb project and client, containing the interfaces (local). Ear2 contains a war that needs to call the ejb3 service. When I call the ejb service I am getting a classcastexception, I think because there are two classloaders involved here. Is there a clean way to achieve this?
I'm working in RAD75 and Websphere 7.0.0.7
Thank you

If both the ears run on the same server instance, you could set the Classloader Policy to "single" so that a single classloader is used.
But then again, if both the EARs run on the same server, then a better option would be to package the war within the EAR1. This way you do not have to change the Classloader Policy ( and hence other apps that may run on the same server will not be impacted)

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.

JavaEE: multi-module Maven project with Glassfish/Payara: ejb-jar.xml security roles not seen by EJB module

I am migrating a large JavaEE web app to a multi-module Maven form.
The roles declared for a specific EJB in the ejb-jar.xml are not being seen by that EJB when I run the multi-module web app.
The ejb-jar.xml is identical to the one I had in the single large web app (which worked fine), except for a change in the qualified name (packaging) of the EJB, which has been carefully matched in the new ejb-jar.xml.
The #Resource SessionContext ctx is working: it can see the Principal etc.
It just does not detect any of the roles from the ejb-jar.xml any more, so ctx.isCallerInRole(String) always fails.
I can use #DeclareRoles annotations in the EJB and it works (but that's not an acceptable solution, it's just for diagnosis).
The ejb-jar.xml in the EJB module is at:
.../src/main/resources/META-INF/ejb-jar.xml
Maven builds it to:
.../target/classes/META-INF/ejb-jar.xml
And it definitely makes it into the final target jar for the EJB module (I have even extracted it and checked).
The deployment is to the same Glassfish or Payara server as for the single large web app (where it worked fine).
I am not getting any relevant logged warnings of any kind during deployment.
Grateful for ideas about what else could be preventing the system from apparently catching the ejb-jar.xml on deployment of the multi-module web app project, or for suggestions on how to further diagnose the problem.
EDIT 2017-03-15: I found (after some sleep) that if I copy (or move) the ejb-jar.xml from the EJB module to .../src/main/webapp/WEB-INF/ of the web module it works as expected. But this is not quite a solution, as I want different web modules to be able to use the same EJB module, and also it means that the <security-role> and any <security-role-ref> and <role-link> are in one web module not the EJB module. I am also using the EJB module for REST services (independent of web role context) and want the same role concepts (so defined in the EJB module).

When to use a Local EJB Interface

As per Oracle docs here
Local Clients A local client has these characteristics.
It must run in the same application as the enterprise bean it
accesses.
It can be a web component or another enterprise bean.
To the local client, the location of the enterprise bean it accesses
is not transparent.
As for :It must run in the same application as the enterprise bean it
accesses.
When it says 'same application, it means the EJb client and the EJB bean must be part of the same jar file? Or same EAR file? If it is part of the same jar file, why even use an EJB in the first place? We can just import the EJB bean in the client and use it like a utility class.
It means the same EAR.
Regardless, the only reason to ever use EJB is because you want to delegate responsibility to the container (transactions, security, interceptors, resource injection, asynchronous methods, timers, etc.). There's nothing to stop you from implementing all the qualities of service yourself (e.g., Spring did it), but by using EJB, you don't have to worry about getting all the details right, and (in theory) you make it easier for many people to develop an application because they share a common understanding.

tomcat: guvnor & webservice load order

I have guvnor deployed on tomcat 7. Now need to deploy a wrapper webservice around the BRMS. The webservice is a spring-ws and uses #Autowired kbase dependency injection. kbase is configured in spring-context XML as (not literal):
<drools:resource id="xxx" source="http://localhost:8080/guvnor/.../<package>/LATEST
Now the problem is tomcat first loads the webservice which fails to initialize as the guvnor URL is not up yet.
I can work around this by first starting only guvnor along with tomcat startup and then copy the WS war to the webapps folder. This works but is painful to do everytime.
What is the best approach?
I have seen this thread, but not sure if it will work in this context: Is there a way to enforce a deployment order in tomcat6?
Tried the following ways to address this:
Tomcat brings up both services on starup. The initialization of webservice fails but bring up the webservice manually through tomcate admin interface.
Use a script to do the same as above to bring up the webservice after a delay.
Change the drools package initialization to load through drools API instead of through config files along with a retry logic.
All of these work, but retaining the last option in the production code.

Different EARs using common services. Should I use remote calls, or package them as local?

I have multiple EJB3 ears deployed on jboss server. One of them is an application containing common services exposed as remote. Now all other ears use those services via remote and it seems to be realy painful for performance.
What can i do to overcome this? Can I make those services #Local and package this jar to every single application to allow them to be used via #Local not #Remote?
According to the JavaEE tutorial, the client of a #Local bean "must run in the same JVM as the enterprise bean it accesses."
So you should have no problem using local calls between different deployed applications on the same server.
Are you sure this is the cause of your performance problems, though?
I agree with you, you cannot inject an ejb session bean from another ear and in the same jvm using local interface.
if you have two ear you must use the remote interface, and using:
#EJB(lookup ="JNDI_BEAN_NAME")
I disagree. See this thread as it provides an excellent description of why you shouldn't: http://www.coderanch.com/t/79249/Websphere/Local-EJB-calls-separate-ear
The only way, normally, to make local calls between ears is to make cross-classloader calls. Not pretty.
You can get around this by having a single classloader per server (versus scoped by ear). Also a bad idea for security/isolation reasons.
You should use remote calls between ears. Some Java EE implementations optimize these calls to be more efficient when calling within the same jvm.

Resources