Reputation: 11
I am using Jersey 2.8 with Glassfish 4.0. I have a resource locator class which looks like below
@Path("/")
@ManagedBean
public class MyServiceLocator {
@Context
ResourceContext rc;//javax.ws.rs.container.ResourceContext
@EJB
private MyEJBHome myEJB;
@Inject//javax.inject.Inject
MySubService mss;
@Path("/mysubservice")
public MySubService getMySubService() {
return rc.getResource(MySubService.class);
//also tried return rc.initResource(new MySubService());
}
}
and a sub resource class which is
@ManagedBean
public class MySubService {
@EJB
public MyEJBHome myEJB;
@Context
HttpHeaders heads;
/*@Inject
private myEJBHome myEJB2;*/
@Path("/mypath")
@GET
@Produces(MediaType.APPLICATION_JSON)
public Object doSomething(@Context SecurityContext securityContext) {...}
}
beans.xml
file is put to META-INF and WEB-INF.
In MyServiceLocator class private MyEJBHome myEJB
is injected successfully. And MySubService mss
object is injected successfully and with EJB injected into it.
The problem is that when MySubService is got via ResourceContext the EJB is not injected into it.
Previously i used Glassfish 3 and Jersey 1.17 with proprietary ResourceContext and absolutely the same code worked ok.
I googled a lot and read a lot of similar (but a bit different) questions and as i understood non JAX-RS stuff (EJB in my case) can't be injected when sub resource is got via ResorceContext. Is it true? If yes how can i work it around? The one possible solution is to inject sub resource objects to the resource locator class but there are too many of them and it seems to be very ugly.
EDIT Injection with @Inject works if to create a binder, bind ejb class to ejb interface and register that binder. But i don't want to describe binding for hundreds of my ejbs. Also as i understand it is specific binding fir HK2 system and i don't want to be linked to it.
Different actions with setting @Named annotations and trying to inject via CDI didn't help. It seems that when getting sub-resource via ResourceContext Jersey uses only HK2 and that's why CDI can't do it's work. Is that correct?
Upvotes: 0
Views: 888
Reputation: 11
The only appropriate solution i found was to create my own annotation and inject provider.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface EJBInject {
String beanName();
}
@Provider
public class EjbInjectProvider implements InjectionResolver<EJBInject> {
@Override
public Object resolve(Injectee injectee, ServiceHandle<?> handle) {
try {
String beanName = injectee.getParent().getAnnotation(EJBInject.class).beanName();
return new InitialContext().lookup("java:global/MyApp/" + beanName);
} catch (Exception e) {
return null;
}
}
@Override
public boolean isConstructorParameterIndicator() {
return false;
}
@Override
public boolean isMethodParameterIndicator() {
return false;
}
}
Then ejb can be injected using that annotation like
@EJBInject(beanName="MyBean") MyBeanEJBHome myBean;
In such case any standard EJB injections which MyBeanEJBHome might need work correctly, too.
Upvotes: 1