将EJB注入Jersey资源类

时间:2016-03-23 14:35:03

标签: java-ee jersey glassfish jax-rs glassfish-3

我有以下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

1 个答案:

答案 0 :(得分:1)

这是解决方案。创建以下两个类:

<强> 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的类并通过@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