将 EJB 注入 Jersey 资源 Class

Inject EJB into Jersey Resource Class

我有以下 Jersey 资源:

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

    @EJB
    RESTWebserviceController restWebserviceController;
...

(其中 RESTWebserviceController 是一个 @Stateless EJB)

正如其他主题中建议的那样,我创建了 InjectableProvider 接口的以下实现。

@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;
        }
    }
}

仍然,容器无法注入 RESTWebserviceController。我 运行 Glassfish 3.1.2 使用 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

这是解决方案。创建以下两个 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;
            }
        };
    }
}

然后,制作应该注入@RequestScoped的class并通过@Inject注入。如果您还没有 beans.xml 文件,请在 WEB-INF 文件夹中创建一个(用于 war 导出):

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

来源:Louis GRIGNON 的回答 (Injecting into a Jersey Resource class)