Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
328 views
in Technique[技术] by (71.8m points)

glassfish - Inject EJB into JAX-RS 2.0 subresource when subresource is got via ResourceContext

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...