2012-01-03 3 views
8

У меня есть @RequestScoped CDI bean, который я хочу превратить в EJB, чтобы получить декларативные транзакции. (Я на EJB 3.1, Java EE 6)Проходящее состояние между методами EJB/@RequestScoped и @Stateless

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

Например, я хочу сделать что-то вроде

@Stateless 
@Named 
@RequestScoped 
public class Foo { 
    private String var1; // can't use instance vars in @Stateless? 
    private String var2; 

    public void transactionForRequest() { 
    var1 = value; 
    var2 = value; 
    .... 
    subroutine(); 
    } 
} 

Я предполагаю, что выше не работы- это правильно?

я рассматриваю два варианта:

  • Используйте @Stateful вместо @Stateless, наряду с @Named и @RequestScoped.
  • Храните @Stateless и используйте карту EJBContext.getContextData для замены переменных экземпляра.

Что лучше? И есть ли другая альтернатива, о которой я не думаю? (Кроме того, подождите, пока Java EE 7 или переключится на Spring. :-))

+0

Использование '@ Stateful' может быть более фотоискусство. Считаете ли вы, что с помощью обычного компонента Faceless bean и управляемого компонента '@ ConversationScoped' передаются состояния? –

+0

Как бы это сработало - вы бы сделали EJB '@ Stateless', а затем' @ Inject' CDI bean? Может ли этот CDI быть '@ RequestScoped'? – wrschneider

+0

Я бы сохранил bean-компонент как '@ Stateless' и использовал' @ ConversationScoped' bean для передачи переменных со страниц на страницы. Ознакомьтесь с этой статьей [http://blog.goyello.com/2011/06/08/jee6-cdi-and-conversation-scope/] о создании мастера. –

ответ

12

Хотя @Stateless, @Singleton и @MessageDriven может быть областью видимости ссылки впрыскивается через @Inject, они не могут быть@RequestScoped или любой другой области. Только модель @Stateful достаточно гибкая, чтобы поддерживать области. Другими словами, вы можете аннотировать класс @Stateful Bean себя как @RequestScoped, @SessionScoped и т.д ..

Проще говоря @Stateless, @Singleton исправили «областей» уже. @Singleton есть по существу @ApplicationScoped и @Stateless возможно, какой-то макияж область как @InvocationScoped, если это есть. Жизненный цикл компонента @MessageDriven полностью зависит от соединителя, который его управляет, и поэтому также не может иметь пользовательскую область.

Смотрите также https://stackoverflow.com/a/8720148/190816

+0

Дэвид, просто чтобы убедиться - если у меня есть ссылка '@ RequestScoped' на' @ Stateless' EJB - что он меня купит? Я получаю одну и ту же ссылку во время всего запроса, но все же (вероятно) ссылка на прокси, поэтому каждый раз, когда я использую эту ссылку, я могу закончить другой экземпляр EJB. Это верно? –

+0

Точно. Чтобы представить это в перспективе, в OpenEJB мы создаем только один прокси для каждого компонента без состояния и совместно используем все приложение. То же самое для Синглтона. В случае размещения RequestScoped (или другой области действия) в Stateless или Singleton он должен рассматриваться как ошибка при развертывании. Мне пришлось бы дважды проверить спецификацию и TCK, но это, безусловно, так, как я бы это сделал. Все остальное просто вводит в заблуждение. –

+0

Спасибо за разъяснение Дэвид. Это просто еще раз, когда связь между EJB и CDI может быть дезориентирована ... –

1

Если вы используете брандмауны Faceless, то вы несете ответственность за любое управление состоянием, и обычно вы делаете это на уровне веб-приложения с помощью HttpSessions. И да, вы не можете использовать переменные экземпляра, поскольку биты фатализуются пулами.

3

Я бы пошел с SFSB вместо SLSB. Вы хотите сохранить состояние, поэтому для меня это самая важная информация - это работа для Stateful EJB.

Также я не думаю, что EJBContext#getContextData() поможет вам. Насколько я помню, он действителен только на время звонка. Таким образом, каждый вызов метода на вашем EJB создаст новую карту данных контекста (по крайней мере, это то, что я ожидал бы.)

+0

Рад слышать, что @Stateful + @RequestScoped будет работать - по какой-то причине «сессионный компонент с состоянием» по-прежнему звучит как грязное слово, но «сеансовый компонент с запросом» звучит намного лучше. Также - 'EJBContext # getContextData()' отлично работает для меня в этой ситуации, потому что подпрограмма является вызовом локального метода ('this.subroutine()'), а не вызовом EJB. – wrschneider

+0

Вы правы - если его местный вызов, чем контекстные данные, прекрасен. Я думал, что вы ввели свой EJB ('@ EJB' или' @ Inject') и вызывают несколько методов на экземпляре прокси. –

 Смежные вопросы

  • Нет связанных вопросов^_^