Search code examples
jakarta-eejerseyglassfishjax-rsglassfish-3

Inject EJB into Jersey Resource Class


I have the following Jersey resource:

@Path("service")
public class Service implements IService {

    @EJB
    RESTWebserviceController restWebserviceController;
...

(where RESTWebserviceController is a @Stateless EJB)

Like advised in other threads to this topic, I created the following implementation of the InjectableProvider interface.

@Provider
public class EJBProvider implements InjectableProvider<EJB, Type> {

    @Override
    public ComponentScope getScope() {
        return ComponentScope.Singleton;
    }

    @Override
    public Injectable getInjectable(ComponentContext cc, EJB ejb, Type t) {
        if (!(t instanceof Class)) {
            return null;
        }

        try {
            Class c = (Class) t;
            Context ic = new InitialContext();

            final Object o = ic.lookup(c.getName());

            return new Injectable<Object>() {
                public Object getValue() {
                    return o;
                }
            };
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }
}

Still, the container can't inject the RESTWebserviceController. Im running Glassfish 3.1.2 using Jersey 1.11.

The following errors and warnings have been detected with resource and/or provider classes:
Missing dependency for field: schnittstelle.rest.controller.RESTWebserviceController schnittstelle.rest.Service.restTWebserviceController

Solution

  • Here's the solution. Create the following two classes:

    ApplicationBeans.java

    import javax.enterprise.context.ApplicationScoped;
    import javax.enterprise.context.spi.CreationalContext;
    import javax.enterprise.inject.spi.Bean;
    import javax.enterprise.inject.spi.BeanManager;
    import javax.inject.Inject;
    import javax.naming.InitialContext;
    import javax.naming.NamingException;
    
    /**
     * Gives direct access to managed beans - Designed to be used from unmanaged code
     * 
     * @author lgrignon
     * 
     */
    @ApplicationScoped
    public class ApplicationBeans {
    
        protected static ApplicationBeans instance;
        @Inject
        private BeanManager beanManager;
    
        /**
         * Gets instance
         * 
         * @return Instance from managed environment
         */
        public static ApplicationBeans instance() {
            if (instance == null) {
                BeanManager beanManager;
                InitialContext ctx = null;
                try {
                    ctx = new InitialContext();
                    beanManager = (BeanManager) ctx.lookup("java:comp/BeanManager");
                } catch (NamingException e) {
                    try {
                        beanManager = (BeanManager) ctx.lookup("java:app/BeanManager");
                    } catch (NamingException ne) {
                        throw new RuntimeException("Unable to obtain BeanManager.", ne);
                    }
                }
    
                instance = getBeanFromManager(beanManager, ApplicationBeans.class);
            }
    
            return instance;
        }
    
        /**
         * Gets bean instance from context
         * 
         * @param <T>
         *          Bean's type
         * @param beanType
         *          Bean's type
         * @param annotations
         *          Bean's annotations
         * @return Bean instance or null if no
         */
        public static <T> T get(final Class<T> beanType, Annotation... annotations) {
            return instance().getBean(beanType, annotations);
        }
    
        /**
         * Gets bean instance from context
         * 
         * @param <T>
         *          Bean's type
         * @param beanType
         *          Bean's type
         * @param annotations
         *          Bean's annotations
         * @return Bean instance or null if no
         */
        public <T> T getBean(final Class<T> beanType, Annotation... annotations) {
            return getBeanFromManager(beanManager, beanType, annotations);
        }
    
        @SuppressWarnings("unchecked")
        private static <T> T getBeanFromManager(BeanManager beanManager, final Class<T> beanType, Annotation... annotations) {
            Set<Bean<?>> beans = beanManager.getBeans(beanType, annotations);
            if (beans.size() > 1) {
                throw new RuntimeException("Many bean declarations found for type " + beanType.getSimpleName());
            }
    
            if (beans.isEmpty()) {
                throw new RuntimeException("No bean declaration found for type " + beanType.getSimpleName());
            }
    
            final Bean<T> bean = (Bean<T>) beans.iterator().next();
            final CreationalContext<T> context = beanManager.createCreationalContext(bean);
            return (T) beanManager.getReference(bean, beanType, context);
        }
    }
    

    InjectionProvider.java

    import javax.inject.Inject;
    import java.lang.reflect.Type;
    import javax.ws.rs.ext.Provider;
    import com.sun.jersey.core.spi.component.ComponentContext;
    import com.sun.jersey.core.spi.component.ComponentScope;
    import com.sun.jersey.spi.inject.Injectable;
    import com.sun.jersey.spi.inject.InjectableProvider;
    
    @Provider
    public class InjectionProvider implements InjectableProvider<Inject, Type> {
    
        public ComponentScope getScope() {
            // CDI will handle scopes for us
            return ComponentScope.Singleton;
        }
    
        @Override
        public Injectable<?> getInjectable(ComponentContext context,
                Inject injectAnno, Type t) {
            if (!(t instanceof Class)) {
                throw new RuntimeException("not injecting a class type ?");
            }
    
            Class<?> clazz = (Class<?>) t;
    
            final Object instance = ApplicationBeans.get(clazz);
    
            return new Injectable<Object>() {
                public Object getValue() {
                    return instance;
                }
            };
        }
    }
    

    Then, make the class, which should be injected @RequestScoped and inject it via @Inject. If you don't already have a beans.xml file, create one in the WEB-INF folder (for war exports):

    <?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>
    

    Source: Louis GRIGNON's answer (Injecting into a Jersey Resource class)