通过ResourceContext获取子资源时,将EJB插入到JAX-RS 2.0子资源中 [英] Inject EJB into JAX-RS 2.0 subresource when subresource is got via ResourceContext
问题描述
我有一个资源定位器类,看起来像下面
@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);
//也尝试返回rc.initResource(新的MySubService());
}
}
和一个子资源类是
@ManagedBean
public class MySubService {
@EJB
public MyEJBHome myEJB;
@Context
HttpHeaders头;
/ * @ Inject
private myEJBHome myEJB2; * /
@Path(/ mypath)
@GET
@Produces (MediaType.APPLICATION_JSON)
public Object doSomething(@Context SecurityContext securityContext){...}
}
beans.xml
文件放在META-INF和WEB-INF。
在MyServiceLocator类中, private MyEJBHome myEJB
注入成功。而 MySubService mss
对象注入成功,并注入EJB。
问题是当MySubService是通过ResourceContext得到的,EJB没有被注入到其中。
以前我使用Glassfish 3和Jersey 1.17与专有的ResourceContext,绝对相同的代码工作正常
我google了很多,读了很多类似(但有点不同)的问题,正如我理解非JAX-RS的东西(在我的情况下EJB)当通过ResorceContext获取子资源时,将被注入。是真的吗如果是,我可以如何工作?
一个可能的解决方案是将子资源对象注入到资源定位器类中,但是它们中有太多的东西似乎是非常难看的。
strong> EDIT 注入@Inject如果要创建一个绑定器,将ejb类绑定到ejb接口并注册该绑定。但我不想描述对数百个我的ejb的绑定。另外据了解,这是具体绑定的HK2系统,我不想链接到它。
不同的操作设置@Named注释,并尝试注入通过CDI没有帮助看来当通过ResourceContext获得子资源时,泽西只使用HK2,这就是为什么CDI无法做到这一点。这是正确的吗?
我发现唯一适当的解决方案是创建自己的注释并注入提供者。
@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();
返回新的InitialContext()。lookup(java:global / MyApp /+ beanName);
} catch(Exception e){
return null;
}
}
@Override
public boolean isConstructorParameterIndicator(){
return false;
}
@Override
public boolean isMethodParameterIndicator(){
return false;
}
}
然后ejb可以使用注释,如
@EJBInject(beanName =MyBean)
MyBeanEJBHome myBean;
在这种情况下,任何标准EJB注意MyBeanEJBHome可能需要正常工作。
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?
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.
这篇关于通过ResourceContext获取子资源时,将EJB插入到JAX-RS 2.0子资源中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!