Spring com Seam, Parte 1: Contruindo um Componente Híbrido Spring-Seam – Etapa 02

Dando continuidade ao artigo Spring com Seam.

Spring com Seam, Parte 1: Contruindo um Componente Híbrido Spring-Seam – Etapa 02

Componente híbrido Spring-Seam

Existe uma certa quantidade de comportamento “mágico” que o Spring adiciona aos seus beans na forma de BeanPostProcessors. Se você registra uma classe do framework Spring que depende de uma funcionalidade provida diretamente por um componente Seam, você carrega a tarefa de emular o trabalho feito pelo container Spring. Seria melhor deixar o Spring fazer seu trabalho necessário e então acessar o Seam e consumir o produto final.

Isso descreve perfeitamente o comportamento de um componente híbrido Spring-Seam. Seam provê uma tag XML que é usada em uma definição de um bean Spring para indicar então ao bean Spring que ele pode ser tratado como um componente Seam de primeira classe. Assim como outros componentes Seam, o componente híbrido é, dado um nome, registrado no container Seam e envolvido com interceptores Seam quando instanciado. Vamos ver agora como Seam permite que você entrelace esta funcionalidade na definição de um bean Spring.

Preparando o Spring

Para iniciar a criação de um componente híbrido Spring-Seam, existem dois requisitos que sua aplicação deve atender. Você deve primeiramente incluir a biblioteca de integração de IoC do Seam, jboss-seam-ioc.jar, em seu classpath. Em seguida, como ilustrado na Listagem 5, você deve registrar o namespace do XML do Seam no arquivo de configuração do Spring para usar tags customizadas a partir do namespace do Seam (ex:). Note que nós estamos agora tratando com namespace do Spring que são usados no arquivo de configuração do Spring, não os namespaces do Seam que foram apresentados anteriormente.

Listagem 5. Registrando o namespace do XML do Seam



As tags customizadas no namespace do seam fazem mais que simplesmente reduzir keystrokes e prover validação implícita dos nomes das propriedades. O atributo chave do uso de tags customizadas no arquivo de configuração do Spring é o ganho de criação de bean capturado por uma implementação da classe NamespaceHandler do Spring. Esta implementação é destinada a um prefixo particular de um namespace de XML. A classe NamespaceHandler transforma os elementos XML que ela reconhece para produzir um bean Spring, decorar um bean existente ou registrar funcionalidade no container Spring.

Seam fornece uma implementação da classe NamespaceHandler para processar tags no arquivo de configuração do Spring que usa o namespace do Seam. Uma certa tag, , é usada para decorar um bean Spring como um SpringComponent, o nome formal da classe de um componente híbrido Spring-Seam. Este componente é então oferecido como um componente Seam autêntico para o container Seam. Seam usa o SpringComponent como um encapsulador que procura através do container Spring para localizar a instância formada do bean do Spring. A classe NamespaceHandler pode também suportar as tags  e , que serão tratada na parte 2 desta série.

Um ponto importante para se lembrar: se você não estiver usando Seam para inicializar o Spring e você planeja usar componentes híbridos Spring-Seam, você deve estar certo de que a declaração SeamListener aparece antes da declaração ContextLoaderListener no descritor web.xml. Esta ordenação é necessária porque o container Seam está ativo e pronto para tratar os retornos vindos de sua classe customizada NamespaceHandler quando o arquivo de configuração do Spring é processado. No entanto, você pode ainda encontrar outros problemas não relacionados durante a inicialização. Portanto, é recomendado fortemente usar Seam para inicializar o container Spring.

Vamos ver agora como incorporar a tag  em uma definição de um bean Spring.

Incorporando a tag

Seam é capaz de decorar um bean Spring como um componente Seam através da inclusão de uma tag  dentro do elemento  que define o bean Spring. Esta configuração é diferente da abordagem de RLE mencionada anteriormente porque ela permite ao bean Spring se tornar um “cidadão” de primeira classe no container Seam. Isso nos dá muito mais controle sobre como o bean Spring se comporta sob o tempo de execução do Seam. Vamos explorar esta integração colocando-a em prática a partir de agora.

A definição do bean Spring tournamentManager está apresentada na Listagem 6. Este bean atua como a interface de negócio para gerenciar uma coleção de torneios de golf. Os dados do torneio de golf é mantido por um partner (cujo nome do pacote é org.open18.parter) e exposto para a aplicação Open 18, um portal de comunidade de golf, através de um Web service. O foco da aplicação Web de exemplo usado neste artigo será direcionado ao gerenciamento por trás (back-end) dos dados do torneio. Note que o bean tournamentManager foi promovido para um componente Seam através do uso da tag .

Listando 6. Definindo um componente híbrido Spring-Seam




Seam deriva a variável de contexto name usada para referenciar o componente Seam a partir do identificador do bean Spring, que pode ser fornecido como a ID ou o atributo name do elemento . Se por alguma razão você não deseja usar o ID do bean Spring como o nome do componente Seam, você pode prover um nome alternativo usando o atributo name da tag , como exibido na Listagem 7.

Listando 7. Providing an alternate Seam component name



Por padrão, o componente Seam tem seu escopo associado ao contexto ScopeType.STATELESS. O contexto stateless é selecionado como o escopo padrão do Seam porque, na maioria das vezes, o bean Spring é um singleton (ver Nota 1). Assim, não existe benefício em armazenar o bean em um escopo real do Seam, pois ele já estará iniciado durante todo o ciclo de vida do container. O contexto stateless é também usado para deixar o Spring gerenciar o escopo do bean, se o bean não for um singleton. O Spring agora suporta escopos customizados, tais como o escopo de fluxo a partir do Fluxo Web do Spring. O uso do contexto stateless previne o Seam de interferências com o plano do Spring para o bean e evita o caso onde Seam está usando uma referência ultrapassada para um bean.

Nota 1. Singleton

Singleton é um padrão de projeto de software (do inglês Design Pattern). Este padrão garante a existência de apenas uma instância de uma classe, mantendo um ponto global de acesso ao seu objeto.

Muitos projetos necessitam que algumas classes tenham apenas uma instância. Por exemplo, em uma aplicação que precisa de uma infra-estrutura de log de dados, pode-se implementar uma classe no padrão singleton. Desta forma, existe apenas um objeto responsável pelo log em toda a aplicação que é acessível unicamente através da classe singleton.

Exemplo em Java

Segue um exemplo em Java de classe Singleton usada em log de dados. Esta classe suporta inicialização sob demanda e ambientes multi-thread.

 

public class SingletonLog {

// Construtor privado. Suprime o construtor publico padrão.

private SingletonLog() {

// Leitura da configuração de log. Normalmente descrita em um arquivo.

}

 

// Faz o log de eventos da aplicação

public void doLog(String eventDescription) {

}

 

//Retorna a instancia única da classe SingletonLog

public static SingletonLog getInstance() {

return SingletonLogHolder.instance;

}

 

//Classe auxiliar para criação da instancia. Evita problemas de sincronização de threads.

private static class SingletonLogHolder {

private static SingletonLog instance = new SingletonLog();

}

}


Tenha em mente, mesmo assim, que a partir do uso do contexto stateless, Seam irá requisitar o bean a partir do container Seam toda vez que a variável de contexto correspondente é resolvida. Este mesmo lookup recorrente ocorreria se o bean Spring fosse acessado através de uma ponte do RLE. Você não precisa se preocupar em adicionar overhead a menos que o bean Spring seja um protótipo, onde neste caso você deve saber que o bean será instanciado em cada lookup.

Se você pretende fazer o bean Spring stateful (o posto de singleton), é melhor tê-lo armazenado em um escopo Seam. O escopo Seam é apoiado usando o atributo scope na tag . Para armazenar um bean Spring em um escopo Seam, o bean Spring deve também ser associado ao escopo do protótipo Spring.

Para demonstrar esta capacidade, vamos definir um bean de critérios de busca, exibido na Listagem 8, que é usado em conjunção com o bean tournamentManager para filtrar a coleção de torneios que são exibidos na interface do usuário. A escolha do escopo de conversação assegura que o critério de busca é carregado em memória pelo período da interação do usuário com o formulário de busca.

Listagem 8. Um bean Spring de escopo de conversação


A cada momento que um bean protótipo é requerido a partir do container Spring, Spring
aloca uma nova instância. Mas, apesar do bean resolvido ser armazenado em uma variável de
contexto de escopo de conversação neste caso, Seam somente pede ao Spring para criar
uma instância uma vez por conversação do usuário. É um casamento ideal da funcionalidade
de cada container. No próximo artigo, você aprenderá sobre outra forma de definer o escopo
de um bean Spring para um contexto do Seam usando mecanismo de definição do escopo do
Spring, e você irá também estudar os perigos da impedância do escopo.

Ebook exclusivo
Dê um upgrade no início da sua jornada. Crie sua conta grátis e baixe o e-book

Artigos relacionados