2014-01-04 4 views
3

Это в основном о понимании различий при введении запоминания состояния EJB (SFSB) с @Inject по сравнению с впрыскиванием с @EJB.Несколько экземпляров с учетом состояния EJB при закачке через КДИ

Одним из основных отличий должно быть контекстная осведомленность при инъекции через @Inject. Таким образом, мое предположение было то, что если я создаю два @RequestScoped бобы и ввести в каждый представляет собой SFSBдважды (один раз с @Inject, один раз @EJB), то SFSB впрыскивается через @Inject бы быть же экземпляр в обоих @RequestScoped бобов, в то время как те, вводится через @EJB будет разные экземпляры.

Это предположение кажется неправильным, но я не понимаю, почему. Не следует ли CDI осознавать тот факт, что обе бобовые являются @RequestScoped и поэтому вводят то же самое SFSB? Почему это не так, или мой тестовый код несколько испорчен?

Это мой SFSB и его интерфейс:

import javax.annotation.PostConstruct; 
import javax.annotation.PreDestroy; 
import javax.ejb.Local; 
import javax.ejb.PrePassivate; 
import javax.ejb.Stateful; 

import package.MyStateful; 

@Stateful 
@Local(MyStateful.class) 
public class MyStatefulImpl implements MyStateful { 

    @PostConstruct 
    private void postConstruct() { 
      System.out.println("SFSB postconstruct ref: " + this.toString()); 
    } 

    @PreDestroy 
    private void preDestroy() { 
      System.out.println("SFSB predestroy ref: " + this.toString()); 
    } 

    @PrePassivate 
    private void prePassivate() { 
      System.out.println("SFSB prepassivate ref: " + this.toString()); 
    } 

    @Override 
    public String myToString() { 
      return toString(); 
    } 
} 

public interface MyStateful { 
    String myToString(); 
} 

И это один @RequestScoped боб:

import javax.ejb.EJB; 
import javax.enterprise.context.RequestScoped; 
import javax.inject.Inject; 
import javax.inject.Named; 

import package.MyStateful; 

@Named 
@RequestScoped 
public class MyFirstRequestScoped { 

    @Inject 
    MyStateful myStatefulByCDI; 

    @EJB 
    MyStateful myStatefulByEJB; 

    public MyStateful getMyStatefulByCDI() { 
      System.out.println("first#myStatefulByCDI proxy ref: " + myStatefulByCDI.toString()); 
      System.out.println("first#myStatefulByCDI stateful ref: " + myStatefulByCDI.myToString()); 
      return myStatefulByCDI; 
    } 

    public MyStateful getMyStatefulByEJB() { 
      System.out.println("first#myStatefulByEJB proxy ref: " + myStatefulByEJB.toString()); 
      System.out.println("first#myStatefulByEJB stateful ref: " + myStatefulByEJB.myToString()); 
      return myStatefulByEJB; 
    } 

} 

Существует еще один @RequestScoped боб имени MySecondRequestScoped с аналогичной реализации.

Когда они вызываются из страницы JSF Xhtml через EL (ничего особенного, просто <h:outputText value="#{myFirstRequestScoped.myStatefulByCDI}" /> и так далее, чтобы вызвать их создания), это вывод на консоль (WebSphere ApplicationServer 8.5.5.0):

[1/4/14 12:39:11:759 CET] 000000dc SystemOut  O SFSB postconstruct ref: [email protected] 
[1/4/14 12:39:11:761 CET] 000000dc SystemOut  O SFSB postconstruct ref: [email protected] 
[1/4/14 12:39:11:761 CET] 000000dc SystemOut  O first#myStatefulByCDI proxy ref: [email protected](BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA11-0143-4000-E000-6A007F000001)) 
[1/4/14 12:39:11:762 CET] 000000dc SystemOut  O first#myStatefulByCDI stateful ref: [email protected] 
[1/4/14 12:39:11:768 CET] 000000dc SystemOut  O SFSB postconstruct ref: [email protected] 
[1/4/14 12:39:11:768 CET] 000000dc SystemOut  O SFSB postconstruct ref: [email protected] 
[1/4/14 12:39:11:769 CET] 000000dc SystemOut  O second#myStatefulByCDI proxy ref: [email protected](BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA18-0143-4000-E001-6A007F000001)) 
[1/4/14 12:39:11:769 CET] 000000dc SystemOut  O second#myStatefulByCDI stateful ref: [email protected] 
[1/4/14 12:39:11:769 CET] 000000dc SystemOut  O first#myStatefulByEJB proxy ref: [email protected](BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA0E-0143-4000-E000-6A007F000001)) 
[1/4/14 12:39:11:769 CET] 000000dc SystemOut  O first#myStatefulByEJB stateful ref: [email protected] 
[1/4/14 12:39:11:769 CET] 000000dc SystemOut  O second#myStatefulByEJB proxy ref: [email protected](BeanId(Project#ProjectEJB.jar#MyStatefulImpl, 5D0CBA18-0143-4000-E000-6A007F000001)) 
[1/4/14 12:39:11:770 CET] 000000dc SystemOut  O second#myStatefulByEJB stateful ref: [email protected] 
[1/4/14 12:39:11:848 CET] 000000dc SystemOut  O SFSB predestroy ref: [email protected] 
[1/4/14 12:39:11:849 CET] 000000dc SystemOut  O SFSB predestroy ref: [email protected] 
[1/4/14 12:50:11:765 CET] 00000120 SystemOut  O SFSB prepassivate ref: [email protected] 
[1/4/14 12:50:11:766 CET] 00000120 SystemOut  O SFSB prepassivate ref: [email protected] 

Так что, похоже, что:

  • 4 экземпляры SFSB созданы; Я бы ожидал, что это будет всего 3. Те, кто вводится через @EJB, не знают контекста, поэтому я бы подумал, что все нормально, если они созданы для каждой точки инъекции. Но так как CDI должен знать контекст (@RequestScoped), я думал, что CDI заново создаст уже созданный SFSB.
  • Единственное различие между @Inject и @EJB, кажется, здесь что жизненный цикл автоматически управляется при закачке через CDI - метод аннотированный @PreDestroy вызывается для тех (36b3bb10 и 456cec27). Эти инъекции через @EJB (c03fcdee и 9b3971c7) позже пассивируются и, кажется, не разрушаются в любое время позже.

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

Кстати, это ведет себя так же при использовании @SessionScoped бобов, даже если второй компонент создаются после перехода по ссылке на другую страницу (чтобы убедиться, что SFSB впрыскивается через @Inject определенно уже существует). Более того, SFSB экземпляры , введенные через @EJB, создаются всего лишь один раз для времени жизни сеанса, точно так же, как те, которые вводятся через @Inject - так что они, похоже, также знают об этом контексте ...? При смешивании @SessionScoped и @RequestScoped бобов, то @SessionScoped боб получает другой экземпляр SFSB закачиваемый чем @RequestScoped боба, который прекрасно - но, кажется, не особенность КДИ как-то, так как это верно для как тех случаи, от SFSB, вводимого через @Inject, а также для инъекций через @EJB.

Edit: Вывод наблюдаемого поведения: Единственное различие между нагнетание SFSB через @Inject и @EJB, кажется, что в первом случае SFSB автоматически уничтожается, когда сфера остается и в последнем случае это не. Это верно? Это может показаться мне странным, так как я ожидал, что CDI будет вести себя по-другому ...

Какие-либо намеки на то, что мне не хватает, т. Е. Недоразумение, когда дело доходит до "C" в категории "CDI"? Я надеюсь, что это не какая-то «специальность» WebSphere ...

+0

'@ EJB', кажется, исходит из другой эпохи технологий, чем CDI. Помимо всего прочего, для поиска используется JNDI. –

+0

Несомненно, '@ EJB' существует гораздо дольше, чем' CDI', который является частью Java EE с версии 6 (см. Http://www.oracle.com/technetwork/java/javaee/tech/javaee6technologies-1955512 .html). Но, к сожалению, для меня это не объясняет поведение, описанное выше. – stef77

ответ

3

Для того, чтобы ваш SFSB был охвачен запросом, вы должны указать область @RequestScoped. Затем вы должны увидеть тот же самый экземпляр. Теперь, поскольку оба из них proxy'd, самый простой способ подтвердить - установить некоторое значение из одного компонента и получить значение из другого компонента.

+0

Хорошо, это сработало ... Проверяли идентификаторы toString, поэтому я знаю, что это тот же «SFSB». Итак, это как ** «При вводе« SFSB »с CDI, чтобы получить правильный экземпляр« SFSB »,« SFSB »должен иметь аннотацию Scope»? ** Я считаю это довольно запутанным, поскольку когда я решил изменить свой веб-уровень, чтобы использовать другую область (например, беседа вместо запроса, так как я разделил страницу и сделал какой-то процесс мастером на нескольких страницах), мне также нужно изменить аннотацию Scope на моем EJB? Кажется, я неправильно понимаю некоторые понятия. Как вы используете 'SFSB' вместе с CDI наилучшим образом? – stef77

+0

Приоритет должен быть соответствующим. По большей части я не использую SFSB, я использую stateless в своих приложениях. В этих случаях я не предоставляю объем. Естественный характер, если необходимо, будет в чисто CDI-объекте. –

+0

Да, есть руб! Я видел это наоборот, я думал, что у меня будет «SFSB», и, как вы выразились, при необходимости, я бы добавил область, то есть «CDI». Но если у меня есть уже обработанный бит CDI и добавьте '@ Stateful', если мне нужны эти возможности, это звучит более законно для меня.Интересно, есть ли много вариантов использования для 'SFSB', теперь с' CDI', особенно для приложения с веб-интерфейсом, но это еще один вопрос. Большое спасибо за ваш ответ и объяснения! – stef77

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