I have an EAR application with three modules:
beans are in "app-ejb" module
remote interfaces are in "app-remote"
web services are in "app-war"
app-ejb and app-war use app-remote as library.
all are packaged in "app.ear".
This is working fine, but now I have to use the same beans outside the EAR application, and injection is not working.
I have in app-ejb:
#Stateless
#LocalBean
public class Services implements ServicesRemote {
[...]
}
and his remote interface in app-remote:
#Remote
public interface ServicesRemote {
[...]
}
In my app-war I can inject the remote bean without problem:
#Stateless
#LocalBean
public class UseServices {
#EJB
private ServicesRemote services;
[...]
}
Anyway in my external ejb application, deployed as stand-alone and using the same ejb-remote as library, if I try to inject the same EJB like this:
#Stateless
#LocalBean
public class UseServicesFromAnotherApp {
#EJB
private ServicesRemote services;
[...]
}
Glassfish (4.1) give me an error "Class [ Lcom/[...]/ServicesRemote; ] not found".
Is this expected? How can I inject the remote bean correctly?
Injection doesn't work with remote interfaces. Beans that are "injectable", live inside container's JVM and are available for injection to other beans inside the same application. The same holds true for accessing beans in another application in the same container, although applications may live in the same JVM. Since remote methods are originated from another JVM or another application, injection is not possible. You must use JNDI lookup instead to get a reference to a remote bean.
As a matter or personal taste, I would stay away from EJB Remote interfaces, and instead I would use another "remoting" technique such as REST.
The problem was probably generated by a number of hot deploys, made glassfish unstable.
When I restarted glassfish my code start to work properly (it's actually still working).
Sorry for posting here without trying to restart glassfish first.
Related
I tried inject a stateless EJB in my application client and I get the following error
SEVERE: Exception while preparing the app : Unable to load the EJB module. DeploymentContext does not contain any EJB. Check the archive to ensure correct packaging for C:\glassfish3\glassfish\domains\domain1\applications\EJB.
If you use EJB component annotations to define the EJB, and an ejb or web deployment descriptor is also used, please make sure that the deployment descriptor references a Java EE 5 or higher version schema, and that the metadata-complete attribute is not set to true, so the component annotations can be processed as expected
My client is defined thus:
#EJB
private static Sless sless;
public static void main(String[] args) {
System.out.println("Sless says: " + sless.hello());
}
The class Sless is my interface which is defined thus:
#Remote
public interface Sless {
public String hello();
}
I also have a class implementing Sless
#Stateless
public class SlessBean implements Sless{
#Override
public String hello() {
return "hello, world!\n";
}
}
Any help as to where the problem is coming from would be appreciated.
1) Standalone clients or non-managed POJOs(POJOs which are not maintained by Containers) do not support annotation injection. So #EJB will not work.
2) You will have to do a manual JNDI look up from your standalone client.
What you need for this ?
1) Your EJB extending Remote interface. Because Local interface does not expose EJB to Cross Application or Remote calls.
2) Dependency jar files in your standalone client. ie: ORB Jar
3) You will need to know RMI/IIOP port on your server.
4) You will also have to take care if Standalone client and Server use different JDK/JRE implementations. For ex: 1 using SUN JDK and other using IBM JDK.
Follow this for connecting to EJB on Glassfish from a Standalone client >> https://glassfish.java.net/javaee5/ejb/EJB_FAQ.html#StandaloneRemoteEJB
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 am learning EJB and I am trying to execute the Helloworld example given in EJB In Action book.
My app server is JBoss, I created the Jar file for the bean class and interface in the right directory( I can see the EJB in JMX console).
Now I created a simple client using EJB annotations, but I am getting a NullPointerException.
Here is my client code.
Client code:
package com.client;
import javax.ejb.EJB;
import com.EJB.*;
public class HelloWorldClient {
#EJB
private static HelloWorldInterface HelloBean;
public static void main(String[] args)
{
HelloBean.SayHelloWorldInEJB();
}
}
Bean class
package com.EJB;
import javax.ejb.Stateless;
#Stateless
public class HelloWorldBean implements HelloWorldInterface {
public void SayHelloWorldInEJB() {
// TODO Auto-generated method stub
System.out.println("Hello world from the world of EJB");
}
}
Interface
package com.EJB;
import javax.ejb.Local;;
#Local
public interface HelloWorldInterface {
public void SayHelloWorldInEJB();
}
Note: I tried using specifying the interface as Remote, it still didn't work.
Steps that I did so far to get to this point.
1) Created the file EJB files
2) Made the build.xml and deployed the EJB.
Am I missing any configuration files ???
Now I created a simple client using EJB annotations, but I am getting a NullPointerException.
Your client code looks like an Application Client and such client is supposed to be deployed on the app server and then executed in an Application Client Container (ACC) so that injection can occur. Starting the ACC requires an application server specific command.
The following wiki explains the usage of the ACC in JBoss (how to package, deploy and launch an ACC): How to use an application client in JBoss-5.
If you don't want to use an Application Client Container and instead just run the application client class through a java command, injection won't be possible and you'll have to perform a JNDI lookup.
And in both cases, you'll have to provide and use a remote business interface for your bean.
Resources
How to use an application client in JBoss-5
Creating and Running an Application Client on the GlassFish Server
Related questions
application-client
You would have to make two changes:
Replace the #EJB dependency injection with JNDI lookup. Dependency Injection is not supported for POJOs in EJB 3 (Don't know about EJB 3.1 though )
Then, the interface has to be a remote interface. The reason is that, the client here is a standalone java program - It would be running in JVM different from the web-app JVM.
Both dependency injection through #EJB and having the interface as #Local should work if the client was a servlet in the same server.
I am using Netbeans 6.8 and Glassfish v3.0.
I created an ejb module and created entity classes from database and then created stateless session bean with remote interface. Say eg.
#Remote
public interface customerRemote{
public void add(String name, String address);
public Customer find(Integer id);
}
#Stateless
public class customerBean implements customerRemote{
//implementations of methods
}
Then i created a new web application. But now how do i access remote ejb's in my web application. I could lookup a bean with jndi name but what i want to know is, what type of object it will return? How do i typecast it in customerRemote? I don't have any class named customerRemote in my web application. So, how do i do it? Also, what about the entity class Customer? There is no such class named Customer in my web application also. All ejb's and entity classes are in separate ejb module. Please help me :(
How do i typecast it in
customerRemote? I don't have any class
named customerRemote in my web
application. So, how do i do it? Also,
what about the entity class Customer?
There is no such class named Customer
in my web application also. All ejb's
and entity classes are in separate ejb
module.
Your web application must depend on a library that contains these classes and interfaces. Then you will be able to import the interface and typecast as usual. You have two approaches:
All in one jar. This seems to be what you have now. In this case your web app needs to depend on this jar.
Split API and implementation. A better approach is to split your ejb module in two jars: one jar myModule-api contains the classes that belong to the API of your module. In this case that would be customerRemote and Customer. And another jar myModule-impl contains the implementation (the implementation depends on the API of course). Then in your web app, you only need to depend on the API which is in myModule-api.
I'm using Eclipse 3.5.2, EJB 3.0 and GlassFish 2.1 but I'm sure that this will work for you too.
Well, first of all I have created an EJB project that will be deployed as a stand alone EJB module on the container, and another project that is in fact a web application that uses a single servlet for testing.
I can resolve the same problem adding the next parameters to the #EJB declaration on the servlet that invokes the bean:
public class SimlpeServletClient extends HttpServlet {
.
.
.
#EJB(beanInterface=ISimpleJob.class,mappedName="ISimpleJob")
ISimpleJob statelesBean;
.
.
.
protected void doPost(HttpServletRequest ...){...}
.
.
.
}
And this is the structure of the bean that implements the interface exposed to the servlet:
#Stateless(name="SimpleJobBean", mappedName="ISimpleJob")
#Remote( { ISimpleJob.class })
public class SimpleJobBean implements ISimpleJob {
.
.
.
}
As you can see, it seems like your client only knows the interface to work with, but it doesn't tell the server which resource can fullfill the request.
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.