@Stateless
public class Waiter {
@Inject
private Soup soup;
@EJB
private Chef chef;
public String orderSoup(String name){
soup.setName(name);
return chef.prepareSoup().getName();
}
}
CDI @RequestScoped
Este exemplo mostra o uso da anotação @RequestScoped para objetos injetados. Um objeto que é
definido como @RequestScoped é criado uma vez para cada requisição e é compartilhado por todos os
beans que o injetam através do mesmo request.
Exemplo
Este exemplo retrata um cenário similar ao cdi-application-scope. O visitante de um restaurante pede uma sopa ao garçom. O pedido é passado para o chefe que prepara o prato e o devolve ao garçom que entrega para o visitante.
Waiter (garçom)
O Waiter session bean recebe uma requisição através do método orderSoup() da classe de teste.
Uma instância de Soup será criada nesse método e ela será compartilhada em toda a requisição com o
bean Chef. O método passa o request para o bean Chef. Ele então retorna o nome da sopa para a
classe de teste.
Soup (sopa)
A classe Soup é um POJO injetável, definida como @RequestScoped. Isso significa que uma instância
será criada apenas uma vez para cada request e será compartilhada por todos os beans que a injetam.
@RequestScoped
public class Soup {
private String name = "Soup of the day";
@PostConstruct
public void afterCreate() {
System.out.println("Soup created");
}
public String getName() {
return name;
}
public void setName(String name){
this.name = name;
}
}
Chef
A classe Chef é um simples session bean com um campo Soup injetado. Normalmente, o parâmetro soup
seria passado para o prepareSoup() como argumento, mas para as necessidades deste exemplo será
passado pelo contexto da requisição.
@Stateless
public class Chef {
@Inject
private Soup soup;
public Soup prepareSoup() {
return soup;
}
}
Caso de teste
Esta é a classe de entrada para este exemplo.
public class RestaurantTest {
private static String TOMATO_SOUP = "Tomato Soup";
private EJBContainer container;
@EJB
private Waiter joe;
@Before
public void startContainer() throws Exception {
container = EJBContainer.createEJBContainer();
container.getContext().bind("inject", this);
}
@Test
public void orderSoup(){
String soup = joe.orderSoup(TOMATO_SOUP);
assertEquals(TOMATO_SOUP, soup);
soup = joe.orderSoup(POTATO_SOUP);
assertEquals(POTATO_SOUP, soup);
}
@After
public void closeContainer() throws Exception {
container.close();
}
}
Executando
O teste chama orderSoup() duas vezes, uma com "Tomato Soup" e outra com "Potato Soup". Nas duas
chamadas o Chef recebe a sopa indicada pelo Waiter, porque os dois beans compartilham a mesma
instância de Soup durante a chamada.
As duas chamadas vêm da thread do teste, que não é uma requisição HTTP. Para essas chamadas locais
de EJB o container mantém um único contexto de requisição para a thread, então o bean Soup é
criado apenas uma vez e a saída mostra um único Soup created. Em uma aplicação web, cada
requisição HTTP tem o seu próprio contexto de requisição e, portanto, a sua própria instância de Soup.
[INFO] Running org.superbiz.cdi.requestscope.RestaurantTest
...
INFO: Deployed Application(path=.../examples/cdi-request-scope)
Soup created
INFO: Undeploying app: .../examples/cdi-request-scope
...
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0