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