Preloader image

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.

@Stateless
public class Waiter {

    @Inject
    private Soup soup;

    @EJB
    private Chef chef;

    public String orderSoup(String name){
        soup.setName(name);
        return chef.prepareSoup().getName();
    }
}

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