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

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.

Related

Looking up OSGi services from outside the OSGi container

I have a set of bundles deployed in Karaf and exposing a number of OSGi services which I would like to be able to lookup and call remotely, from an application running on a (possibly) different machine and in a non-OSGi container. My initial though was to use JNDI lookup to get the services I want however I understand from an earlier stackoverflow post that this might not be supported (I say might since I haven't been able to find any information on whether anything has changed on the Aries JNDI implementation in the past year). In that case I guess my other options would be to use CXF to expose a JAX-WS or JAX-RS API for my services.
Is my understanding of the situation correct? Is JNDI lookup really not an option in my case? Are there any other alternatives I have not thought of?
A simple jndi lookup will not work. OSGi services are not suitable for remoting per se. So even if you can get the jndi object in some way you can not call it.
Possible solutions are manual cxf proxies and endpoints like you already found and Distributed OSGi. See CXF-DOSGi and Eclipse ECF. Both can offer transaparent service calls from one OSGi framework to another. DOSGi is ideal if you also use OSGi on the client side.
At least in case of CXF DOSGi it is also possible to use DOSGi on the server side and a normal CXF client on the client side. So you can keep the effort on the server side minimal.
See also this tutorial for CXF DOSGi
You need a Remote Services implementation. See https://en.wikipedia.org/w/index.php?title=OSGi_Specification_Implementations for a list.

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.

Glassfish 2.1 EJB 3.0 Exposing local EJB to other applications running in the same domain/jvm

I have an existing project that I am in need of configuring different. This needs to happen without major code changes. I am actually hoping I could somehow do this only with configuration. I have spent the past 2 to 3 days reading everything I can find on this issue. I understand the glassfish classloaders, and what is available to me.
I have a current sample project that has an EJB which defines a #Local interface.
The ejb is deployed inside an ejb-module as an ejb-module into the glassfish domain.
Now I am trying to find a way for another application which was deployed as an ear into the same domain, to be able to access that EJB via it's local interface.
I have read documentation that says this is not possible.
Then I have seen posts on here at StackOverflow, and other's on the web saying it is possible. But, I cannot find the actual solution.
With investigation, I have realised that the #Local EJB does not register itself onto jndi (atleast according to the logs), if I use the glassfish JNDI browser, I also do not see it visible. So it makes sense to me, that either it's not possible, or the deployment of the EJB project is at fault, and somehow I need to expose it.
#Remote is a possibility, if it can be by reference, and no performance overhead. But the preferred method allowing #Local EJB access is really the ultimate need.
Does anyone know what I would need to do to expose the #Local EJB to another application?
Or is this plainly not possible?
I am using Glassfish 2.1 With EJB 3.0
If Glassfish 2.1 can handle EJB 3.1 I would be willing to move to it if it provided this capability, but I doubt it's that easy.
Please assist.
Thank you.
I am adding a bounty. To complete the bounty, it would be required to run 2 ear applications in the same domain, where A.ear contains an #Local EJB that is used as well by the application in a B.ear.
The link #Peter gave you almost solves your problem. (link)
One trick which needs to be done to solve #Xavier's problem is to provide common.jar to both ears in the same version (loaded by the same class loader). If you do it, the class cast exception will not be thrown and you will be able to use the ejb with local interface.
To do it you need to put common.jar into glassfish/domains/domain1/lib folder (substitute domain1 with you domain name). This way this jar will be loaded by a Glassfish's shared class loader.
I made a quick test with Eclipse and Glassfish 3 with following structure:
package com.example;
JarShared
- #Local class Server
EarServer
- EjbServer
- #Stateless class ServerBean implements Server
EarClient
- EjbClient
- #Stateless #LocalBean class ClientBean
Lookup from ClientBean:
InitialContext ic = new InitialContext();
Server server = (Server) ic.
lookup("java:global/EarServer/EjbServer/ServerBean!com.example.Server");
I did not get ClassCastException and I could call sample method from ServerBean.
Important notes:
both EarServer and EarClient should not contain JarShared in lib folder, they should reuse the one which is in domains lib folder
remember to restart Glassfish after adding JarShared to it.
to make both ejb projects compile you must add JarShared to their build paths, but nothing more
If you have questions, post a comment.

passing objects between 2 applications in separate JVMs

I have a portlet application running on a portal server and an webapp running on application server. I want to make a call from the portlet application jsp to app application. I can make the call; no issues.. I can pass values in the request parameter; no issues.. I want to pass an object to the appserver application as well and I am not sure how to do this.
Try using Java RMI. After implementing couple of interfaces you can pass objects between JVM's quite easily. As Laird mentioned, that requires serialization, but it is often done implicitly by Java, so there's a good chance you won't have to worry about it.
Since your two applications are running on two separate application servers, and hence on two different Java Virtual Machines, the only way to pass an object from one to the other is by serializing the object in some fashion.
You may opt to use Java serialization, or you may choose to represent your object in terms of its state and then have a class--deployed separately to each application server somewhere--that knows how to build a new instance of your object out of that state.
Is your appserver a Websphere Application Server? Maybe Dynacache could be what you are looking for. A college told me a story from his current project, they need to access data from a Java EE app running on Websphere 7, Portal environment is 6.1.

How do you establish context and call an WebSphere EJB from the Sun JRE (not IBM)

Is there a way to call an EJB that is served through WebSphere (iiop://host:port/ejbName) from a vanilla JRE (like Sun). A lot of people have been telling me that this type of architecture relies in a homogenous environment. Thoughts?
Yes, this is possible. You have to create something called a thin client. It has limitations on JNDI lookups due to not being part of the container environment, so fully qualified names have to be used.
Just search for "thin client ibm ejb" on google. Unfortunately, I don't have the link to the appropriate libraries (for WAS 6) here, they are at work.
Although it’s possible, I wouldn’t recommend it because you’re asking for troubles using RMI-IIOP in a heterogeneous environment.
My approach would be to expose the EJB as a web service and consume at the client.

Resources