Может ли EJB3-компонент "самостоятельно внедрять" и вызывать свои собственные методы через контейнер EJB? - PullRequest
11 голосов
/ 11 марта 2009

Можно ли "самостоятельно внедрить" EJB-компонент для вызова локальных методов как методов bean-компонента? В некоторых случаях это может быть выгодно, например, если используются управляемые контейнером транзакции и что-то должно быть выполнено в новой транзакции.

Пример того, как это может работать:

Foo.java:

@Local
public interface FoO {
    public void doSomething();
    public void processWithNewTransaction(); // this should actually be private
}

FooBean.java:

@Stateless
public class FooBean implements Foo {

    @EJB
    private Foo foo;

    public void doSomething() {
        ...
        foo.processWithNewTransaction();
        ...
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public void processWithNewTransaction() {
        ...
    }
}

Если я извлечу processWithNewTransaction() в другой бин, его необходимо будет представить в качестве открытого метода в интерфейсе, даже если он должен вызываться только FooBean. (Та же проблема с моим кодом выше, поэтому в определении интерфейса есть комментарий.)

Одним из решений было бы переключиться на управляемые компонентом транзакции. Однако для этого потребуется изменить весь бин для управления собственными транзакциями и добавить много методов для всех методов.

Ответы [ 5 ]

11 голосов
/ 05 января 2013

Можно сделать self injection. Вам нужно использовать SessionContext.

SessionContext sc = ...
sc.getBusinessObject(FooBean.class).processWithNewTransaction()
11 голосов
/ 04 сентября 2012

Самостоятельная инъекция EJB действительно возможна. Причина, по которой бесконечная рекурсия в этом случае не произойдет, довольно проста: контейнер не внедряет фактический экземпляр компонента из пула. Вместо этого он вводит прокси-объект. Когда вы вызываете метод на внедренном прокси (foo), контейнер получает экземпляр компонента из своего пула или создает его, если нет доступных экземпляров.

2 голосов
/ 29 июля 2011

Я бы не согласился, часто для управления транзакциями полезно вызывать метод локального компонента через контейнер.

Точно в качестве примера, если бы вам пришлось вызывать метод локального компонента внутри цикла, вам было бы лучше иметь транзакцию на одну итерацию, чем для всех итераций. (при условии, что бизнес-логика не "все или ничего", как отправка доставки или выпуск акций)

2 голосов
/ 11 марта 2009

Обновление : Как отмечено другими ответами, это действительно технически возможно. Пожалуйста, посмотрите ответы Csaba и Michael о том, как и почему это работает, несмотря на бесконечную рекурсию.


Я не могу дать 100% точный ответ, но я почти уверен, что это невозможно.

Я так думаю, потому что для внедрения bean-компонента Foo в сам bean-компонент Foo первоначально необходимо создать экземпляр Foo, который он может внедрить впоследствии. Но чтобы создать это, он должен ввести уже существующий экземпляр Foo в Foo, который будет создан ... что приводит к бесконечной рекурсии.

Если вам нужны отдельные транзакции, я бы посоветовал упростить задачу и создать два независимых компонента / интерфейса.

1 голос
/ 13 марта 2009

Интересный вопрос. Я никогда не создаю метод с другим атрибутом транзакции в одном и том же компоненте, то есть это требует рефакторинга. Это обычно затрудняет обнаружение ошибок в приложении при его развитии.

РЕДАКТИРОВАТЬ: исправлены опечатки

...