Внедрение ресурсов Java EE в динамически загружаемые классы

Вот класс, который генерируется/загружается во время выполнения приложением Java EE (бин @Default Bar предоставляется тем же приложением):

public class Foo {

    @PersistenceContext private EntityManager em;
    @Resource private UserTransaction tx;
    @EJB private MyEJB ejb;
    @Inject Bar bar;

    public Foo() {
    }

    @PostConstruct
    public void postConstruct () { ... }

    public void businessMethod() { ... }

}

Вот как это создается:

    import javax.enterprise.inject.spi.Unmanaged;
    ...

    @Inject private BeanManager bm;
    ...

    Class clazz = loadClazz();

    Unmanaged unmanaged = new Unmanaged(bm, clazz);

    Object obj = unmanaged.newInstance()
            .produce()
            .inject()
            .postConstruct()
            .get();

С JBoss/WildFly все поля вводятся правильно, включая EntityManager, EJB, UserTransaction и т. д.

В TomEE и GlassFish ресурсы Java EE игнорируются, и вводится только поле bar.

  1. Следует ли считать это ошибкой в ​​TomEE и GlassFish, или это просто белое пятно в спецификации JavaEE/CDI, которое по-разному реализовано на серверах приложений? Это определенно не чисто проблема CDI, потому что и GlassFish, и WildFly используют одну и ту же реализацию CDI, а именно JBoss Weld;
  2. Как я могу добиться этого с помощью TomEE и GlassFish? Портативное решение предпочтительнее, но некоторый код, зависящий от сервера, в порядке (боюсь, это неизбежно с проблемами такого рода).

Общая цель состоит в том, чтобы предоставить полный спектр CDI-инъекций (простые @Inject, а также ресурсы Java EE, такие как @PersistenceContext, @Resource, @EJB и т. д.) в динамический код. Моя первая попытка состояла в том, чтобы сгенерировать класс на лету, который включал бы аннотированные поля + динамическую бизнес-логику (и да, это сработало, хотя и только в WildFly). Вообще говоря, у меня есть набор определений динамических инъекций, например:

@Annotation(param = "value") @Qualifier1 @Qualifier2 ... Type name;

где Annotation является одним из Inject, PersistenceContext, Resource, EJB и т. д., и я хочу получить экземпляр, который был бы внедрен, если бы он находился внутри управляемого компонента CDI. Таким образом, допустим гипотетический метод, который будет принимать метаданные инъекции и возвращать соответствующий экземпляр.


person Dimitri    schedule 26.03.2016    source источник
comment
Какую версию TomEE вы используете?   -  person John Ament    schedule 28.03.2016
comment
TomEE 7.0.0-M3 (последний моментальный снимок разработки с поддержкой JavaEE 7)   -  person Dimitri    schedule 28.03.2016


Ответы (1)


Пробовали ли вы объявлять ресурсы через поля производителя?

Таким образом, вы можете @Inject EntityManager, UserTransaction и т. д. не прибегать к аннотациям до CDI.

Поскольку внедрение CDI через @Inject, кажется, работает во всех ваших средах, это может быть жизнеспособным решением.

person Harald Wellmann    schedule 26.03.2016
comment
При таком подходе будут зафиксированы такие параметры, как lookup для @Resource, unitName для @PersistenceContext и т.д. Я тоже хочу, чтобы они были динамичными. Или, может быть, вы полагаете, что я также мог бы сгенерировать класс производителя (служит мостом между аннотациями до CDI и @Inject)? Я боюсь, что контейнер CDI не подберет динамически загружаемый класс производителя. - person Dimitri; 27.03.2016