Вызов метода производителя в области сеанса CDI из сеансового компонента EJB без сохранения состояния

Я хочу внедрить текущего пользователя, используя @Inject @Current User во всех слоях (т. е. веб-слое, слое EJB). Для этого у меня есть следующий метод CDI Producer:

@Named
@SessionScoped
public class UserController {
   @Resource SessionContext sessionContext;
   @EJB UserDao userDao;

   @Produces @Current
   public User getCurrentUser() {
     String username = sessionContext.getCallerPrincipal().getName();
     User user = userDao.findByUsername(username);
   }
}

@Qualifier
@Target({TYPE, METHOD, PARAMETER, FIELD})
@Retention(RUNTIME)
public @interface Current{}

Теперь я хочу внедрить текущего пользователя в сессионный компонент EJB без сохранения состояния следующим образом:

@Stateless
public class SomeBackendService {
   @Inject @Current
   private User user;
}

Мой вопрос: всегда ли текущий пользовательский объект повторно вводится после изменения сеанса, потому что зависимости сеансового компонента без сохранения состояния обычно вводятся один раз во время создания, и компонент может быть объединен и использоваться в разных сеансах?


person Theo    schedule 07.08.2011    source источник


Ответы (3)


Хотя я не пробовал именно эту ситуацию, в CDI bean-компоненты обычно не вводятся повторно. Вместо этого вводится прокси, который знает о своем контексте.

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

Таким образом, хотя область @Stateless в основном является «приложением», возможно, что прокси-сервер, представляющий User в вашем «SomeBackendService», по-прежнему делегирует правильную версию с областью действия сеанса.

p.s.

Если под слоями вы на самом деле подразумеваете модули, как в веб-модулях, и модули EJB, которые являются частью EAR, это будет немного сложнее, так как CDI не всегда работает должным образом между модулями (особенно в JBoss AS). Частично это связано с неясностью того, что такое «приложение», и, следовательно, областью применения является EAR.

person Arjan Tijms    schedule 07.08.2011
comment
Совсем забыл про прокси. Я попробовал это, и это работает, как ожидалось. Спасибо. - person Theo; 08.08.2011

Да, в каждый бизнес-метод, называемый контейнером, будут повторно внедрены все зависимости вашего SLSB. Вот текст, который гарантирует это в спецификации EJB 3.1:

«Если сеансовый компонент использует внедрение зависимостей, контейнер внедряет эти ссылки после создания экземпляра компонента и до того, как в экземпляре компонента будут вызваны какие-либо бизнес-методы». - Раздел 4.3.2

У меня тоже было это сомнение, и я разместил вопрос, объясняющий эту ситуацию здесь

person Marlon Patrick    schedule 04.09.2013

По замыслу ваш сессионный компонент без сохранения состояния не должен иметь состояние «Пользователь», он во что бы то ни стало не имеет состояния.

Если вы хотите, чтобы ваш EJB имел состояния, используйте вместо этого @Stateful.

person Michael Qin    schedule 05.03.2013