When I try to access EJB from another module inside one Application I got NullPointerException.
I'll explain an example to be more exact.
EAR Structure following:
EAR
|
— core.jar (EJB-module with core EJB) — application core
|
— app.jar (another EJB-module with EJBs) — business logic here
|
— web.war (servlets)
At code.jar there is EJB:
#LocalBean
#Singleton
#Startup
public class AppInfo(){
private int counter;
public void incCounter(){
counter++;
}
public int getCounterValue(){
return counter;
}
}
At module app.jar we have Stateless EJB which tries to read counter.
#Stateless
public class SomeBean{
#EJB private AppInfo appinfo;
public void run(){
int counter = appInfo.getCounterValue(); // here method throws with NPE
System.out.println("Counter value is: "+counter);
}
}
At module web.war there is servlet that increment counter value for every request:
public class MyServlet extends HttpServlet{
#EJB private AppInfo appInfo;
protected void doPost(params){
appInfo.incCounter();
...
other code
}
}
While debugging, I detected that:
At servlet injection work well: when entering doPost() appInfo is Proxy object for AppInfo EJB.
At SomeBean there is NPE: at run() entry point value of appInfo = null.
How I do correctly inject EJB from core.jar to another EJB from App?
P.S. I deploy EAR to JBoss 6.1 EAP
P.S.S. I also tried using #Remote: not working (appInfo is still equals null)
I think Local should work - this is in the same Application.
Try the fully qualified package name:
#EJB(beanName="my.package.AppInfo")
It seems to be that this is a JBoss deployment ordering issue. When the container creates a new instance of SomeBean and tries to inject the AppInfo bean, this one hasn't been created/deployed yet.
Try to rename your jars file, indicating the correct dependency order. (eg. a_core.jar and b_app.jar).
Other possibility could be to inject the singleton bean on a setter method.
To access EJB from another module, you need to do with following ways:
Use Remote access instead of Local access. or
Use JNDI.
For details, read this tutorial.
Related
I have to create project with interface(IGraphRemote), sessionbean(Graph) and client class(AppClient)
I tried to prepare simple project with one method register(int hwork, String album) - hwork its my homework's number, album its my album's number, but it doesn't work and returns an error: java.lang.NullPointerException , so connection wasn't established. How can i fix that ?
My files:
IGraphRemote
public interface IGraphRemote {
public boolean register(int hwork, String album);
}
Graph
#Remote
public class Graph implements IGraphRemote{
public boolean register(int hwork, String album) {
return (hwork == 6
&& album.equals("119962"));
}
}
And AppClient
public class AppClient {
#EJB
private static IGraphRemote gremote;
public static void main(String[] args) {
AppClient ap = new AppClient();
System.out.println(ap.gremote.register(6, "119962"));
}
}
here are my project
Error:
Exception in thread "main" java.lang.NullPointerException
at AppClient.main(AppClient.java:22)
Java Result: 1
It's obvious from your code and also in the stack trace that you try to run a standard j2se application with a main method from within a web application, so how do you expect dependcy injection to happen unless there is some other code create the ejb instance and inject it in the ejb reference. EJB is a J2EE component and it can't be created in standard java application, you need an ejb container with a naming service to manage the EJB lifecycle. You can create a standard j2se client by connecting to the naming service and lookup for the bean, but your EJB MUST be deployed in an ejb container in the first place such as TomEE, Glassfish, websphere,..etc
First of all, your EJB bean can not be static, waht is desrcibed here:
Injecting a static EJB, nonsense?
Second, if you want to inject your EJB bean, your app has to run in EJB container, like Glassfish or JBoss. If you run your app like simple Java SE applicaiton, your IGraphRemote gremote will always be null unless you initialize it by yourself.
I have an EAR file containing a WAR.
The EAR contains an EJB jar. The EJB exposes a Local and Remote interface.
#Stateless(name = "FooServiceEJB")
#Local(IFooServiceLocal.class)
#Remote(IFooService.class)
public class FooServiceBean implements IFooService, IFooServiceLocal {
...
}
The WAR file defines a JAXRS annotated class.
#Path("/foo")
#LocalBean
#Stateless
public class FooResource {
...
}
I wish to inject the local 'view' of the EJB into the JAXRS resource class. Apparently I have two options, which I assumed would be equivalent (for the most part):
Use #EJB
Use #Inject (To many, this appears to be the preferred option - see Should I use #EJB or #Inject)
I'm running JBoss EAP 6.2.0.GA (AS 7.3.0.Final-redhat-14).
The difference in behaviour that I am seeing is as follows (on JBoss - haven't tried any other app servers):
If I use #EJB to inject the local ejb, then the call semantics are by reference (as expected). For example:
#EJB
private FooServiceLocal fooService;
However, if I use #Inject to inject the local ejb, the call semantics are by value (i.e. serialization occurs). For example:
#Inject
private IFooServiceLocal fooService;
Here's a snapshot of the thread stack with the class that I believe is performing the serialization. The thread stack is completely different when I use the #EJB annoation.
http://i.stack.imgur.com/BXSaz.png
Any ideas why I am seeing this difference in behaviour?
TL;DR: Web Service uses an #Injected class, #Injected class uses #EJBs. #EJBs are null. Why are they null and how do I fix this?
I'm using Glassfish 3 and I have a #Stateless #WebService that is #Injecting a class with a #Dependent annotation on it. I'd like this class to be able to use other stateless ejbs as fields like this:
#EJB(name = "ejb/MySessionBean", beanName = "MySessionBean")
private MySessionLocal mySessionLocal;
But, when I try to call this web service, these #EJB fields are null (although the #Dependent class itself seems to be injected into the web service correctly). Is it possible to do what I'm trying to do?
I should add that my Web Service and my EJBs are in an EJB jar in an ear's root. The #Dependent class is inside a jar in the ear's lib/ directory.
UPDATE: I've discovered that the #EJBs work correctly (are not null) if I move the #Dependent class into the same jar as the web service. To me this suggests a classloader issue? An ear's ejb jar can #Inject a class in a "lib/*.jar", but a class in a "lib/*.jar" can't get an #EJB from a ejb jar in the ear's root.
It's still unclear to me if this is by design.
An ear's ejb jar can #Inject a class in a "lib/*.jar", but a class in a "lib/*.jar" can't get an #EJB from a ejb jar in the ear's root.
It's still unclear to me if this is by design.
I believe this is by design. A library (something in the .ear file's library directory) does not have to be processed by the machinery that fills #EJB-annotated slots. To put it another way, only a Java EE module (an EJB jar, a web application) will have its #EJB-annotated fields "filled".
CDI, by contrast, has no such restrictions (provided that the relevant META-INF/beans.xml files exist), so it can "fill" #Inject-annotated fields with beans sourced from any bean archive.
I have found a workaround, though I'd prefer not to have to use it. Its always been the case that I can get a reference to the #EJB by doing this (in my "lib/*.jar"):
//inside EjbLookup.java
public <T> T lookupEjb(String sessionBeanClassName) {
return lookup("java:comp/env/ejb/" + sessionBeanClassName);
}
public <T> T lookup(String name) {
try {
Context c = new InitialContext();
return (T) c.lookup(name);
} catch (NamingException ne) {
log.error(ne.getMessage(), ne);
throw new RuntimeException(ne);
}
}
So I can create a class like this in my "lib/*.jar":
import javax.enterprise.inject.Produces;
public class EjbProducer {
private EjbLookup ejbLookup = new EjbLookup();
#Produces
public MySessionLocal getMySessionLocal() {
return ejbLookup.lookupEjb("MySessionBean");
}
}
And now I can #Inject the EJB anywhere in my "lib/*.jar" by doing this:
#Inject
private MySessionLocal mySessionLocal;
On the other hand, if I attempt to use this code inside the EJB jar itself, I get an error about how the stateless ejb could not be created. Perhaps that has more to do with the way you're supposed to use JNDI than CDI though. I can work around this by using #EJB when I'm inside the ejb jar and using #Inject when I'm in the lib.
I have 2 EJB module projects and I want from one of the projects to call a stateless no-interface bean from another project. I want to inject the bean to be called using the EJB annotation. The problem is the injection doesn't work(I use NetBeans 7.4 if that is relevant).
The stateless no-interface EJB being called:
package standalonepackage;
import javax.ejb.Stateless;
import javax.ejb.LocalBean;
#Stateless
#LocalBean
public class StandaloneBean {
private static final String message="Greetings!";
public String returnMessage(){
return message;
}
}
The interface of the bean that calls the bean above(this ejb resides in another ejb module project)
#Local
public interface ExampleBeanLocal {
public String getMessage();
}
The implementation of the interface:
#Stateless
public class ExampleBean implements ExampleBeanLocal {
#EJB
private StandaloneBean standaloneBean;
#Override
public String getMessage() {
return String.format("Me - and the second message %s", standaloneBean.returnMessage());
}
}
I also have a main class that just calls the ExampleBean getMessage method(MainClass is located in the second ejb module project):
public class MainClass {
private static ExampleBeanLocal instance = new ExampleBean();
public static void main(String[] args) {
System.out.println(instance.getMessage());
}
}
What am I missing?
First of all if you want to access your business logic as EJB then first you will need to deploy the EJB in an application server. During the deployment process the application server will create something called the JNDI name which is like a gatepass to access your business logic.
Secondly, there are two ways you can invoke an EJB.
1. Creating ContextLookup using JNDI name
2. Using Context Dependency Injection CDI (only within the same Container)
You cannot invoke an EJB using CDI from a POJO ( since it is not contained in any container and the EJB your accessing is in a different JVM ). If you want to access an EJB from a POJO you'll need to use #Remote and use the ContextLookup way of accessing an EJB, you can find more information here
http://wiki.netbeans.org/CreatingEJB3UsingNetbeansAndGlassfish
You need application server with EJB container to run this. Have a look at JBoss, Apache TomEE or something else.
you can use this way to run your jar GLASFISH_HOME/bin/appclient -client app.jar
before compiling your maven project mvn assembly:assembly
and add your main class in your pom.xml
#Local
public interface EJBA{
// declares a method 'validate'
}
#Stateless
public class EJBABean implements EJBA{
// implements the method 'validate'
}
class Model{
#EJB
private EJBA ejbA;
public void doSomething(){
ejbA.validate();
}
}
Now, if I do the following from the execute method of a Struts 1.2 action class
new Model().validate();
ejbA of Model is null, resulting in a NullPointerException. The question is similar to this but, in my case, I am running the client code (Model) as well as the bean in the JBoss 6.1 Final server itself. The model and the EJB are in the a separate jar file and the the action classes are in a war file. Both of these are packaged inside an ear file.
If I use a context lookup using [ear-name]/EJBABean/local, I am able to access it though. What am I doing wrong ?
Your Model class is not managed by the container and therefore JBoss is not able to identify ejbA as an injected EJB. You have to turn your Model class into an EJB by annotating it with #Stateless/#Stateful/#Singleton.
That's why a JNDI lookup in which the container doesn't take part, works perfectly.