3
votes

I have a jax-rs service implemented with RestEasy, I am using Jboss as7 and have implemented a signleton ejb with the @Signleton annotation. The signleton is started when the server starts (@startup) and I would like to inject it into the jax-rs usign the @EJB. The problem is that the class is always null and I am started to get lost because in every tutorial I have looked this is the way they are injecting the ejb. Should I use any special xml file? what am I doing wrong?

@Path("/")
public class Service extends Application{
@EJB
private GlobalStore store;
public Service(){
fromejbstore = store.getSentiment();//null pointer is thrown
}
}

the Signleton ejb is:

@Singleton
@Startup
public class GlobalStore {
 Sentiment sentiment;
 @PostConstruct
public void initialize() {
 //do something
}
public Sentiment getSentiment(){return sentiment;}
}
6

6 Answers

3
votes

I have changed my code to look like this and avoid the injection:

    `try{
        InitialContext ctx=new InitialContext();
        localRef = (myEjb) ctx.lookup("java:global/appName/EjbName");
       }catch(NamingException ne){
            System.out.println("\n[MyRestService]NamingException: "+ne);
            ne.printStackTrace();
       }`

Could not find the reason the @EJB annotation is not working, probably this has something to do with the RestEasy.

3
votes

AFAIK, the @EJB annotation injection doesn't work for POJOs - try turning your Service class into a stateless session bean (by adding @Stateless annotation on the class level) and the GlobalStore injection should work like a charm

1
votes

I had same problem when I call from Rest services to EJB. I got null when i inject the @EJB.When I tried to add @Stateless in the services class then there is no problem. I think you can add @Stateless in your Service class. Then it will no problem.

0
votes

I think you are activating your JAX-RS the wrong way. A class extending Application and annotated with @ApplicationPath is the Java EE 6 "no XML" approach to activate JAX-RS.

@ApplicationPath("/rest")
public class JaxRsActivator extends Application {
 /* class body intentionally left blank */
}

Then your Service should be in the same package like JaxRsActivator but does not need to extend Application:

@Path("/test")
public class Service
{
  @EJB private GlobalStore store;

  @GET @Path("/test")
  public String getTime()
  {
   boolean test = (store==null);
   return "Test: "+test;
  }
}

You can test it with your browser http://<host>/<context>/rest/test/test.

0
votes

The supplied answer above is correct. Add @Stateless to the service, add a @Local annotated interface which the service implements, then in the class access that stateless bean by adding @EJB to a reference of that interface. The only other thing you might have to do which I had to on Websphere Liberty Profile was create the beans.xml file in WEB-INF directory to stop the NPE on that cdi bean.

@Stateless
public class ServiceImpl implements Service {
    public void doSomething() {
        System.out.println("I did something");
    }

    @PostConstruct
    public void postConstruct() {
        System.out.println("I was just constructed");
    }

    @PreDestroy
    public void preDestroy() {
        System.out.println("Arrgg I am being destroyed");
    }
}

@Local
public interface Service {
    public void doSomething();
}


public class Client {

    @EBJ Service service;

    public void someMethod() {
        service.doSomething();
    }
}

../WEB-INF/beans.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="
  http://java.sun.com/xml/ns/javaee 
  http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

You can add the post construct and pre destroy annotated methods on your bean to see it being created and destroyed when the app boots up and shuts down.

-2
votes

add beans.xml in web-inf:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
      http://java.sun.com/xml/ns/javaee 
      http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
</beans>

and change the class extends Application:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

import java.util.HashSet;
import java.util.Set;

@ApplicationPath("/rest")

public class YourApplication extends Application
{
   HashSet<Object> singletons = new HashSet<Object>();

   public YourApplication()
   {
      getClasses().add(yourOwnClass.class);
   }

   @Override
   public Set<Class<?>> getClasses()
   {
      HashSet<Class<?>> set = new HashSet<Class<?>>();
      return set;
   }

    enter code here

   @Override
   public Set<Object> getSingletons()
   {
      return singletons;  
   }
}