SeamFramework.orgCommunity Documentation

Capítulo 19. Gerenciamento de contextos

19.1. Gerenciamento dos contextos embutidos

Weld permite que você gerencie facilmente os contextos embutidos através de injeção e execução dos métodos de ciclo de vida. Weld define dois tipos de contexto, gerenciado e não gerenciado. Contextos gerenciados podem ser ativados (permitindo instâncias de beans serem buscadas do contexto), invalidados (agendando instâncias de beans para serem destruídas) e desativados (evitando instâncias de beans de serem buscadas e, se o contexto foi invalidado, causando a destruição das mesmas. Contextos não gerenciados são sempre ativos, alguns podem oferecer a habilidade de destruir instâncias.

Os contextos gerenciados podem tanto ser acoplados ou desacoplados. Um contexto desacoplado possui um escopo dentro da thread em que foi ativado (instâncias colocadas em contexto numa thread não são visíveis nas outras threads), e é destruído após sua invalidação e desativação. Contextos acoplados são anexados a algum recipiente de dados externo (como o Http Session ou um mapa manualmente propagado) ao associar o recipiente com o contexto antes de ativar e o desassociando após desativar.

Weld provides a number of built in contexts, which are shown in Tabela 19.1, “Contextos avaliáveis no Weld”.

Tabela 19.1. Contextos avaliáveis no Weld

EscopoQualificadoresContextoNotas
@Dependent@DefaultDependentContextO contexto dependente é desacoplado e não gerenciado
@RequestScoped@UnboundRequestContextUm contexto de requisição desacoplado, útil para testes
@RequestScoped@BoundRequestContextUm contexto de requisição acoplado acoplado a um mapa manualmente propagado, útil para testes ou em ambientes non-Servlet
@DefaultBoundRequestContext
@RequestScoped@HttpRequestContextUm contexto de requisição acoplado a uma requisição Servlet, usado em qualquer contexto de requisição com base em Servlets
@DefaultHttpRequestContext
@RequestScoped@EjbRequestContextUm contexto de requisição acoplado a um contexto de invocação de um interceptador, utilizado para invocações de EJB fora das requisições de Servlets
@DefaultEjbRequestContext
@ConversationScoped@BoundConversationContextUm contexto de conversação acoplado a dois mapas manualmente propagados (um que representa a requisição e outro que representa a sessão), útil para testes ou em ambientes non-Servlet
@DefaultBoundConversationContext
@ConversationScoped@HttpConversationContextUm contexto de conversação acoplado a uma requisição Servlet, usado em qualquer contexto de conversação com base em Servlets
@DefaultHttpConversationContext
@SessionScoped@BoundSessionContextUm contexto de sessão acoplado a um mapa manualmente propagado, útil para testes ou em ambientes non-Servlet
@DefaultBoundSessionContext
@SessionScoped@HttpSessionContextUm contexto de sessão acoplado a uma requisição Servlet, usado em qualquer contexto de sessão com base em Servlets
@DefaultHttpSessionContext
@ApplicationScoped@DefaultApplicationContextUm contexto de aplicação apoiado por um singleton com escopo de aplicação, é não-gerenciado e desacoplado mas oferece uma opção para destruir todas as entradas
@SingletonScoped@DefaultSingletonContextUm contexto singleton apoiado por um singleton com escopo de aplicação, é não-gerenciado e desacoplado mas oferece uma opção para destruir todas as entradas

Os contextos não-gerenciados possuem pouco interesse em uma discussão sobre gerenciamento do ciclo de vida de contextos, assim, a partir daqui concentraremos nos contextos gerenciados (contextos não-gerenciados certamente desempenham um papel vital no funcionamento de sua aplicação e no Weld!). Como você pode observar na tabela acima, os contextos gerenciados oferecem uma série de diferentes implementações para o mesmo escopo; em general, cada opção de contexto para um escopo possui a mesma API. Nós vamos ver abaixo uma série de cenários comuns no gerenciamento de ciclo de vida; de posse deste conhecimento e o Javadoc, você deverá ser capaz de lidar com qualquer das implementações de contexto que o Weld dispõe.

Vamos começar com o simples BoundRequestContext, o qual você pode usar para fornecer ao escopo de requisição fora de uma requisição Servlet ou uma invocação de EJB.

   /* Inject the BoundRequestContext. */

   /* Alternatively, you could look this up from the BeanManager */ 
   @Inject BoundRequestContext requestContext;
   
   ...
   
   /* Start the request, providing a data store which will last the lifetime of the request */
   public void startRequest(Map<String, Object
> requestDataStore) {
      // Associate the store with the context and acticate the context
      requestContext.associate(requestDataStore);
      requestContext.activate();
   }
   
   /* End the request, providing the same data store as was used to start the request */
   public void endRequest(Map<String, Object
> requestDataStore) {
      try {
         /* Invalidate the request (all bean instances will be scheduled for destruction) */
         requestContext.invalidate();
         /* Deactivate the request, causing all bean instances to be destroyed (as the context is invalid) */
         requestContext.deactivate();
      } finally {
         /* Ensure that whatever happens we dissociate to prevent any memory leaks */
         requestContext.dissociate(requestDataStore);
      }
   }

O contexto de sessão acoplado funciona da mesma maneira, exceto que a invalidação e desativação do contexto de sessão faz com que todas conversações na sessão sejam destruídas também. Os contextos de sessão e requisição http também funcionam de forma semelhante e podem ser úteis se você estiver criando threads a partir de uma requisição http). O contexto de sessão http oferece adicionalmente um método que pode destruir imediatamente o contexto.

Nota

Os contextos de sessão do Weld são "preguiçosos" e não requerem uma sessão para realmente existir até que uma instância de bean precise ser criada.

O contexto de conversação oferece mais algumas opções, as quais veremos por aqui.

   @Inject BoundConversationContext conversationContext;

   
   ...
   /* Start a transient conversation */
   /* Provide a data store which will last the lifetime of the request */
   /* and one that will last the lifetime of the session */
   public void startTransientConversation(Map<String, Object
> requestDataStore, 
                                          Map<String, Object
> sessionDataStore) {
      resumeOrStartConversation(requestDataStore, sessionDataStore, null);
   }
   /* Start a transient conversation (if cid is null) or resume a non-transient */
   /* conversation. Provide a data store which will last the lifetime of the request */
   /* and one that will last the lifetime of the session */      
   public void resumeOrStartConversation(Map<String, Object
> requestDataStore, 
                                         Map<String, Object
> sessionDataStore, 
                                         String cid) {
      /* Associate the stores with the context and acticate the context */
      * BoundRequest just wraps the two datastores */
      conversationContext.associate(new MutableBoundRequest(requestDataStore, sessionDataStore));
      // Pass the cid in
      conversationContext.activate(cid);
   }
   
   /* End the conversations, providing the same data store as was used to start */
   /* the request. Any transient conversations will be destroyed, any newly-promoted */
   /* conversations will be placed into the session */
   public void endOrPassivateConversation(Map<String, Object
> requestDataStore, 
                                          Map<String, Object
> sessionDataStore) {
      try {
         /* Invalidate the conversation (all transient conversations will be scheduled for destruction) */
         conversationContext.invalidate();
         /* Deactivate the conversation, causing all transient conversations to be destroyed */
         conversationContext.deactivate();
      } finally {
        /* Ensure that whatever happens we dissociate to prevent memory leaks*/
         conversationContext.dissociate(new MutableBoundRequest(requestDataStore, sessionDataStore));
      }
   }

O contexto de conversação também oferece uma série de propriedades que controlam o comportamento da expiração da conversação (depois este período de inatividade a conversação será terminada e destruída pelo contêiner) e a duração do tempo limite das travas (o contexto de conversação assegura que uma única thread está acessando qualquer instância de beans ao travar o acesso, se uma trava não pode ser obtida depois de um certo tempo, o Weld lançará um erro em vez de continuar aguardando o travamento). Adicionalmente, você pode alterar o nome do parâmetro utilizado para transferir o id da conversação (por padrão, cid).

O Weld também introduz a noção de um ManagedConversation, a qual estende a interface Conversation com a habilidade de travar, destravar e afetar (atualizar o último timestamp utilizado) uma conversação. Finalmente, todas as conversações não-transientes em uma sessão podem ser obtidas a partir do contexto de conversação, assim como a conversação corrente.

Nota

As conversações do Weld não possuem ids atribuídos até que elas se tornem não-transientes.