SeamFramework.orgCommunity Documentation

Capítulo 5. Escopos e contextos

5.1. Tipos de escopo
5.2. Escopos pré-definidos
5.3. O escopo de conversação
5.3.1. Demarcação de contexto
5.3.2. Propagação de conversação
5.3.3. Timeout de conversação
5.4. O dependent pseudo-scope
5.4.1. A anotação @New

Até agora, vimos alguns exemplos de anotações de tipo de escopo. O escopo de um Web Bean determina o ciclo de vida das instâncias do Web Bean. O escopo também determina que clientes se referem a quais instâncias do Web Bean. De acordo com a especificação Web Beans, um escopo determina:

  • Quando uma nova instância de qualquer Web Bean com esse escopo é criada

  • Quando uma instância de qualquer Web Bean com esse escopo é destruída

  • Cada referência injetada refere-se a qualquer instância de um Web Bean com esse escopo

Por exemplo, se temos um Web Bean de escopo de sessão CurrentUser, todos os Web Beans que são chamados no contexto dele HttpSession verão a mesma instância do CurrentUser. Essa instância será criada automaticamente na primeira vez que um CurrentUser for necessário nessa sessão, e será automaticamente destruída quando a sessão terminar.

Web Beans possui um modelo extensível de contexto. É possível definir novos escopos, criando uma nova anotação de tipo de escopo:

@Retention(RUNTIME)

@Target({TYPE, METHOD})
@ScopeType
public @interface ClusterScoped {}

Evidentemente, essa é a parte mais fácil do trabalho. Para esse tipo de escopo ser útil, nós também precisamos definir um objeto Context que implementa o escopo! Implementar um Context é geralmente uma tarefa muito técnica, destinada apenas ao desenvolvimento do framework.

Podemos aplicar uma anotação de tipo de escopo a uma classe de implementação de um Web Bean para especificar o escopo do Web Bean:

@ClusterScoped

public class SecondLevelCache { ... }

Normalmente, você usará um dos escopos pré-definidos na Web Bean.

A Web Beans pré-define quatro tipos de escopos:

Para uma aplicação web que utiliza Web Beans:

Os escopos de request e aplicação também estão disponíveis:

Se a aplicação tentar invocar um Web Bean com um escopo que não tem um contexto ativo, uma ContextNotActiveException é lançada pelo gerenciador do Web Bean em tempo de execução.

Três dos quatro escopos pré-definidos devem ser extremamente familiares a todos os desenvolvedores Java EE, então não vamos perder tempo discutindo-os aqui. Um dos escopos, porém, é novo.

O escopo de conversação da Web Beans é um parecido com o tradicional escopo de sessão na medida em que mantém estado associado a um usuário do sistema, e o mantém durante várias requisições para o servidor. No entanto, ao contrário do escopo de sessão, o escopo de conversação:

Uma conversação representa uma tarefa, uma unidade de trabalho do ponto-de-vista do usuário. O contexto de conversação mantém o estado associado ao usuário que estiver utilizando no momento. Se o usuário estiver fazendo várias coisas ao mesmo tempo, existem várias conversações.

A conversação está ativa durante qualquer requisição JSF. No entanto, a maioria das coversações é destruída no final da requisição. Se uma conversação deve manter estado através de múltiplas requisições, deve explicitamente ser promovida para uma conversação de longa duração (long-running conversation).

Web Beans oferece um Web Bean pré-definido para o controle do ciclo de vida das conversações em uma aplicação JSF. Esse Web Bean pode ser obtido por injeção:

@Current Conversation conversation;

Para promover a conversação associada a requisição atual em uma conversação de longa duração, chame o método begin() no código da aplicação. Para agendar a destruição do atual contexto de conversão de longa duração no final da requisição atual, chame end().

No exemplo a seguir, um Web Bean em escopo de conversação controla a conversação ao qual estiver associado:

@ConversationScoped @Stateful

public class OrderBuilder {
    private Order order;
    private @Current Conversation conversation;
    private @PersistenceContext(type=EXTENDED) EntityManager em;
    
    @Produces public Order getOrder() {
        return order;
    }
    public Order createOrder() {
        order = new Order();
        conversation.begin();
        return order;
    }
    
    public void addLineItem(Product product, int quantity) {
        order.add( new LineItem(product, quantity) );
    }
    public void saveOrder(Order order) {
        em.persist(order);
        conversation.end();
    }
    
    @Remove
    public void destroy() {}
    
}

Esse Web Bean é capaz de controlar seu próprio ciclo de vida através do uso da API Conversation. Mas alguns outros Web Beans têm um cliclo vida que depende totalmente de um outro objeto.

Além dos quatro escopos pré-definidos, Web Beans possui o chamado dependent pseudo-scope. Esse é o escopo padrão para um Web Bean que não declare explicitamente um tipo de escopo.

Por exemplo, esse Web Bean tem o tipo de escopo @Dependent:

public class Calculator { ... }

Quando um ponto de injeção num Web Bean resolve para um Web Bean dependente, uma nova instância do Web Bean dependente é criada a cada vez que o primeiro Web Bean for instanciado. Instâncias de Web Beans dependentes nunca são compartilhadas entre diferentes Web Beans ou diferentes pontos de injeção. Eles são objetos dependentes de alguma outra instância de Web Bean.

Instâncias de Web Bean dependentes são destruídas quando a instância de que eles dependem é destruída.

Web Beans torna fácil a obtenção de uma instância dependente de uma classe Java ou um EJB, mesmo se a classe ou EJB já tiverem sido declarados como um Web Bean com outro tipo de escopo.