Лучший способ интегрировать EJB (JNDI) и CDI - PullRequest
1 голос
/ 17 апреля 2019

В настоящее время у нас есть архитектура развертывания, в которой множество сервисов, ориентированных на данные, предоставляются через RMI бизнес-сервисам.Оба типа (сервисы, ориентированные на данные и бизнес-сервисы) являются сессионными компонентами без сохранения состояния.Каждый пакет интерфейса службы данных (содержащий удаленные интерфейсы) также имеет локатор, который выполняет поиск JNDI.Мы сделали так, чтобы мы могли вызывать сервис, ориентированный на данные, из любой точки логики бизнес-сервиса.

Вот так выглядит локатор:

public final class OMRLocator {

    private static final Logger LOG = Logger.getLogger( OMRLocator.class );

    private static final String ORG_WILDFLY_INITIAL_CTX_FACTORY = "org.wildfly.naming.client.WildFlyInitialContextFactory";

    private OMRLocator() {
    }

    @Produces
    public static OrganisationsAndMandatesRegister locate() {
        try {
            Properties ctxProp = new Properties();
            ctxProp.put( Context.INITIAL_CONTEXT_FACTORY, ORG_WILDFLY_INITIAL_CTX_FACTORY );
            InitialContext ctx = new InitialContext( ctxProp );
            return (OrganisationsAndMandatesRegister) ctx.lookup( OrganisationsAndMandatesConstants.REMOTE_NAME );
        }
        catch ( NamingException ex ) {
            LOG.log( Level.WARN, "Cannot reach: " + OrganisationsAndMandatesConstants.REMOTE_NAME, ex );
            return null;
        }
    }
}

Мы работали на JBOSS EAP6 и начали экспериментировать с CDI.Следовательно, мы добавили beans.xml к бинам data-service и @Produces, чтобы сделать (в данном случае OrganisationAndMandatesRegister CDI инъекционным. Идея состоит в том, что в будущем мы можем упаковать наше приложение и упаковать услуги данныхвместе с бизнес-сервисом в одном корпоративном архиве.

В последнее время мы перешли на JBOSS EAP7.2 (Wildfly 8?), и внезапно мы видим все виды неожиданных задержек и проблем с транзакциями.

Myесть подозрение, что способ, которым мы получаем бины, является фактором этих проблем. Например: я предполагаю, что область действия зависит от жизненного цикла бизнес-EJB, но для каждого вызова locate() в бизнес-сервисе создается новый экземпляр данных.служба создается.

Итак: каков наилучший способ создания удаленного компонента (через RMI) при использовании CDI? Следует ли принимать во внимание область видимости, учитывая, что оба типа служб не имеют состояния (или это делается автоматически)

1 Ответ

2 голосов
/ 03 мая 2019

Если в методе производителя не определена область действия, то используется @Dependend, поэтому найдите подходящую область, возможно, @RequestScoped. Когда вы извлекаете EJB из JNDI, вы не получаете новый объект, вы получаете экземпляр из пула, который может быть одинаковым при нескольких вызовах. Ваша проблема может заключаться в перехватчиках EJB, потому что если зависимая область действия, экземпляр EJB всегда один и тот же, после того, как введен, никогда не освобождается.

Избавьтесь от @Produces, потому что CDI интегрируется с EJB, а EJB можно вводить через @Inject или @EJB. Если вы хотите сохранить класс Locator, вы можете вставить туда EJB и вернуть соответствующий экземпляр EJB (который на самом деле является прокси), в результате чего Locator должен иметь значение @ApplicationScoped. Другой способ заключается в использовании экземпляра, который позволяет осуществлять программный поиск. С типом Object вы можете получить доступ ко всем компонентам CDI (включая EJB) контейнера, поэтому общий интерфейс будет полезен для минимизации доступных компонентов.

См. Следующие ссылки для получения дополнительной помощи.

https://docs.jboss.org/weld/reference/latest/en-US/html/injection.html#_obtaining_a_contextual_instance_by_programmatic_lookup

Внедрение EJB без сохранения состояния с помощью @Inject в CDI Weld ManagedBean (JSF 1.2 EJB Application в jboss 6 AS)

http://www.adam -bien.com / ролик / abien / запись / inject_vs_ejb


Просто подведу итог:

вариант а) Оставить как есть. Возможно, сделайте область видимости явной с помощью @Dependent, чтобы указать, что это вызывается при создании вызывающего компонента (вставка в конструктор вызывающего компонента)

опция b) Использовать @ApplicationScoped сессионный компонент без состояния

@LocalBean // otherwise @EJB will not work
@ApplicationScoped // this instance should be created only once per ear
public class OMRLocator {

    @EJB // does implicitly a remote (default) JNDI lookup
    private OrganisationsAndMandatesRegister instance;

    @Produces
    @Dependent // just to make it explicit
    public OrganisationsAndMandatesRegister locate() {
       return instance;
    }
}
...