Внедрить EJB в подресурс JAX-RS 2.0, когда подресурс получен через ResourceContext

Я использую Джерси 2.8 с Glassfish 4.0. У меня есть класс локатора ресурсов, который выглядит ниже

@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());
    }
}

и подкласс ресурса, который

@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 файл помещается в META-INF и WEB-INF.

В MyServiceLocator класс private MyEJBHome myEJB успешно внедряется. И объект MySubService mss внедряется успешно, и в него внедряется EJB.

Проблема в том, что когда MySubService получен через ResourceContext, EJB не внедряется в него.

Раньше я использовал Glassfish 3 и Jersey 1.17 с проприетарным ResourceContext, и абсолютно тот же код работал нормально.

Я много гуглил и читал много похожих (но немного разных) вопросов, и, как я понял, материал, отличный от JAX-RS (в моем случае EJB), не может быть введен, когда подресурс получен через ResorceContext. Это правда? Если да, как я могу это обойти? Одним из возможных решений является внедрение объектов подресурсов в класс локатора ресурсов, но их слишком много, и это кажется очень уродливым.

EDIT Внедрение с помощью @Inject работает, если создать биндер, привязать класс ejb к интерфейсу ejb и зарегистрировать этот биндер. Но я не хочу описывать привязку для сотен своих ejbs. Также, насколько я понимаю, это специфическая привязка для системы HK2, и я не хочу, чтобы к ней привязывались.

Различные действия с настройкой аннотаций @Named и попытками закачки через CDI не помогли. Кажется, что при получении подресурса через ResourceContext Джерси использует только HK2, и поэтому CDI не может выполнять свою работу. Это правильно?


person panvik    schedule 15.05.2014    source источник


Ответы (1)


Единственным подходящим решением, которое я нашел, было создание собственного поставщика аннотаций и инъекций.

@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;
    }
}

Затем можно ввести ejb, используя эту аннотацию, например

@EJBInject(beanName="MyBean") MyBeanEJBHome myBean;

В таком случае любые стандартные EJB-инъекции, которые могут понадобиться MyBeanEJBHome, тоже работают корректно.

person panvik    schedule 19.05.2014