I have a stateless session bean and a standalone-java-program acting as a client. The bean method executes just fine when the interface is marked #Remote. However,when I mark that interface with #Local instead of #Remote, I get the following Exception.
[java] javax.naming.NamingException: Could not dereference object [Root exception is java.lang.RuntimeException: Could not find InvokerLocator URL at JNDIaddress "chapter1/HelloUserBean/local"; looking up local Proxy from Remote JVM?]
But I expected even the latter to work, since it is the same computer that the code executes in.
Seeing this behavior, I am assuming that, the Application-Server and the Standalone-Java-Program use different JVM instances and not a single JVM instance and so this client can access only through a remote interface.
Is that assumption correct ?
Thanks !
Yes, it is correct.
#Local interfaces are to be used only within the same application-server. The application server starts one JVM instance, and your standalone client starts another.
Related
I'm trying to work with a stateful EJB Bean in an application which is deployed on a websphere server. For other customers we deploy on wildfly and I don't have any issues there. On Websphere however, the first lookup works fine as well. But after that, the managed bean that uses the EJB Bean gets serialized via a <t:savestate> cause it's request scoped but we need it to live longer than that (We're still working on JSF 1 unfortunately, but we will go to JSF 2 soon and hope to fix the issue with view/flow scope. The problem needs to be solved anyway cause we need the feature in an earlier version of our application.) In the next request, trying to access the EJB Bean, it still exists, but throws the following exception:
java.rmi.RemoteException: CORBA BAD_OPERATION 0x0 no
nested exception is:
org.omg.CORBA.BAD_OPERATION:
The delegate has not been set!
vmcid: 0x0 minor code: 0 completed: No
I tried several ways to look the bean up and I have no idea how to solve this. It both occurs on Websphere 8.0.0.4 and 8.5.5.14. The Bean is implementing Serializable and I even tried to make the Remote Interface extend Serializable.
I'm using #EnableMBeanExport in a SpringBoot application to make my beans with #ManagedResource be available to the JMX server. This works fine in simple local processes with VisualVM.
I'm now trying to add Jolokia into the mix, so I can reference those beans remotely with a REST service instead of setting up a remote RMI connection, which is annoying.
The Jolokia doc page at https://jolokia.org/reference/html/jmx.html says to use the following:
MBeanServer jolokiaServer = JolokiaMBeanServerUtil.getJolokiaMBeanServer();
However, there doesn't appear to be a "JolokiaMBeanServerUtil" class in Jolokia.
Update:
Ok, I found the artifact with the class, but the solution doesn't appear to be as simple as just declaring a bean with this value. When I attempt to call a jmx method with a jolokia url, I get an exception like the following:
java.lang.IllegalArgumentException: Invalid object name. Key properties cannot be empty
at org.jolokia.request.JmxRequestFactory.createGetRequest(JmxRequestFactory.java:99)
at org.jolokia.http.HttpRequestHandler.handleGetRequest(HttpRequestHandler.java:79)
at org.jolokia.http.AgentServlet$4.handleRequest(AgentServlet.java:470)
I have a maven client project that i run as maven test. First thing i do in the junit test is a lookup using the jndi string. Here i receive a stateless bean proxy which is cast to a remote interface. As soon as i call a method from the interface (like saving some domain objects wich uses a data access object wich uses jpa) i receive the exception
javax.ejb.NoSuchEJBException: No such EJB[appname=,modulename=someName,distinctname=,beanname=SomeBean]
The documentation says: "A NoSuchEJBException is thrown if an attempt is made to invoke a business method on a stateful session or singleton object that no longer exists". The thing is that the bean is stateless and not stateful or a singleton. I'm also quite sure that the jndi string is correct, because if i make the same lookup and persistence-method-call in the main method of the client project (run as maven build with "install jboss-as:deploy") everything works fine.
Any suggestions how i could use the persistence methods from the proxy when testing? Some colleagues have a similar setup and it works for them without Arquillian or so.
I don't know why but it works now. What I did was removing the getter-method for the EntityManager within the abstract generic DaoBean that all DaoBeans inherit. Having the getter was suddenly shown as an Error while executing the client (it wasn't shown as error before).
Not terribly experienced using EJB, and I ran into the following problem with which I hope one of you guys can help out.
Suppose the following situation: a set of #Local beans have been defined to provide access to a database. These beans are very simple, and are deployed on application server A (Weblogic 10.3.3). We want to provide access to these local beans via remote, and since we already have a "services" module set-up for providing external access to our services, our idea was to create a new #Remote service that uses the local beans described above (injected via #EJB). These service beans are also deployed on application server A. For example:
#Local
public interface DatabaseBeanLocal { doStuff(); }
#Stateless(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
public class DatabaseBean implements DatabaseBeanLocal { doStuff() { ... } ; }
#Remote
public interface ServiceBean { doSomeOtherStuff(); }
#Stateless
public class ServiceBeanImpl implements ServiceBean
{
#EJB(name = "ejb/DatabaseBean", mappedName = "DatabaseBean")
private DatabaseBeanLocal myDatabaseBean;
... methods etc. ...
}
The client that will actually use these remote beans is actually run on a different application server; application server B (also Weblogic 10.3.3). When we look-up the ServiceBean bean from our client, that works fine. When we call a method on it that needs access to DatabaseBean however, the call fails. The Weblogic server says it cannot find a bean for the DatabaseBean interface.
My questions: is this set-up even possible? In other words: will Weblogic (or another container) inject the local bean into the remote bean so that the client gets an instance of the remote bean that is capable of calling actions on the local bean (I assume not, but I'm asking anyway to be sure)?
If not, the I guess we'll have no other choice than to skip the service layer and provide direct access to the DatabaseBean example above via #Remote.
Update 1
After doing some tests, simply defining DatabaseBean above as #Remote rather than #Local "fixes" this issue. Ofcourse, this is not really a fix since this will call the DatabaseBean remotely, which is ridiculous because it's in the same module as the service. I'm starting to suspect that wrapping a local EJB with a remote EJB is simply not possible.
Update 2
What we've found so far:
We've not been able to manually inject the local EJB so far, because we cannot actually find it at runtime.
Weblogic apparently does not include local EJBs in the JNDI tree.
Calling the ServiceBean from outside the AS on which it is deployed still does not work, because the dependency on the local EJB is never resolved, or resolved client-side which means it's not found.
Local means local to EAR not to AS.
Your local and remote Beans must be in same EAR (not only in same AS). Are they?
-- edit --
Hmm.. If they're in the same EAR then it should work. I.e. answer to your question "is such a setup even possible?" is Yes.
Unfortunately now we're talking abt pure and simple debugging. First thing I would do is try and check if teh local bean (DatabaseBean I guess) is actually registered and working using WebPhere UTC equivalent in WebLogic (I never worked in WebLogic). I can list a 100 other things you can check for more logs/traces/symptoms but well, that's the way debugging goes.
Managed to get this issue resolved. the following configuration works for Weblogic 10.3.3 and allows for a remote EJB to use a local EJB, where the remote EJB can be called from anywhere.
Ultimately — after a lot of testing — the trick was apparently specifying a beanName value for the #EJB annotation used to mark the local bean as a dependency of the remote bean. Doh!
Deployment
#Local EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
#Remote EJB is deployed on AS-A in EAR-1 (in its own module/JAR)
Client code that calls the remote service is deployed on AS-B in its own EAR archive
Annotations
The local EJB is a very simple and straightforward EJB bean, with the following interface and implementation:
#Local
public interface LocalBeanLocal {
// Implementation omitted
}
#Stateless(name = "LocalBean")
public class LocalBean implements LocalBeanLocal {
// Implementation omitted
}
The remote EJB is again a relatively simple EJB bean, except that it has a dependency on LocalBean. This dependency is expressed through the #EJB annotation; but it would seem that the beanName attribute is required for Weblogic to resolve this dependency correctly. Without the beanName attribute, calling the remote EJB would not work for us (in the sense that there would always be some kind of error when the local bean was involved)!
#Remote
public interface RemoteBeanRemote {
// Implementation omitted
}
#Stateless(name = "RemoteBean")
public class RemoteBean implements RemoteBeanRemote {
#EJB(beanName = "LocalBean")
private LocalBeanLocal localBean;
// Implementation omitted
}
What is apparently important here is that the beanName attribute in the remote service dependency declaration (#EJB(beanName = "LocalBean")) should have the same value as the bean name defined in the local bean implementation (#Stateless(name = "LocalBean")).
Lookup
Getting a reference to your remote EJB is done the traditional way, there doesn't seem to be a specific requirement. In our case, we look-up the remote service via JNDI.
I have been working through this tutorial. Halfway though it creates an interface and facades for an EJB. Can anyone tell me when I reference the interface using the #EJB annotation, where does it actually make the link between the interface and the actual enterprise java bean itself.
Thanks for the help.
~ Kyle.
It is AFAIK not mandated by the J2EE specification how this is actually solved or implemented by the application server. The most common solution is that the app server uses its own mapping between bean class names and JNDI names, so that depending on the bean class name, it is bound to a specific JNDI path when deploying the application and the same class name -> JNDI path conversion is used for injecting the EJB reference on the "client side".
It will be done inside the EJB container.
When you add this annotation, you'll actually be telling the IoC container of your application server which implementation of the given EJB you want.