Parte 3 - Iniciando no JBoss Seam
Este blog deixou de ser mantido, mas o autor continua escrevendo aqui. Não deixe de assinar o novo feed!
Finalmente chegamos à última parte do tutorial e vamos fazer o Seam funcionar! É só ter fé e seguir todos os passos direitinho. Pronto para continuar? Então… vamos lá!
Adicionando as bibliotecas do Seam
Se você criou uma Library com os arquivos do Seam, como mostrado na primeira parte do tutorial, então adicioná-las no nosso projeto é bem simples. Clique com o botão direito sobre o projeto Registration-ejb e vá em Properties. Selecione a opção Libraries e adicione a Library Seam, como mostra a imagem:
Faça o mesmo com o projeto Registration-war. Isso é necessário para que possamos utilizar a taglib do Seam.
Configurando o projeto web
Vamos começar as modificações no arquivo web.xml, adicionando um parâmetro de contexto e adicionando o listener do Seam, respectivamente:
Muita atenção para digitar esses dados conforme mostram as imagems! Aqui vão algumas informações para você entender o que está acontecendo:
- Quando o Seam for pesquisar por nossos EJBs via JNDI, ele precisa saber os nomes aos quais esses componentes estão ligados para poder obtê-los. Então, este parâmetro indica uma forma padrão - uma nomenclatura - para que o Seam possa montar o nome dos componentes antes de requisitá-los ao serviço de nomes. Então, se existisse um Bean chamado CalcularCredito, então o Seam iria pesquisar pelo nome “Registration/CalcularCredito/local” no serviço de nomes e, caso o Bean esteja registrado certinho, então uma referência local ao bean CalcularCredito é obtida.
- Este Listener serve para que o Seam seja carregado durante o startup da aplicação web, sendo também necessário para controlar o ciclo de vida e gerenciar os contextos de sessão e aplicação.
Vamos agora adicionar o PhaseListener do Seam no arquivo faces-config.xml, para permitir que o Seam se integre ao ciclo de vida da nossa aplicação JSF:
-
-
<?xml version=‘1.0′ encoding=‘UTF-8′?>
-
-
<faces-config>
-
<lifecycle>
-
<phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener>
-
</lifecycle>
-
-
<application>
-
…
-
Note que a listagem só mostra um trecho do faces-config.xml, sendo que o resto deve ser mantido como está!
Configurando o projeto ejb
O Seam precisa que seja criado um arquivo chamado seam.properties… mesmo que este arquivo não tenha conteúdo nenhum! Sim, eu sei que isto é muito estranho, mas, fazer o quê?! Então, vamos criar o arquivo, no diretório /src/conf/:
Não precisa colocar nada dentro do arquivo seam.properties. Bem, colocamos este arquivo dentro do diretório /src/conf por este diretório agrupar outros arquivos de configuração, como a configuração dos EJBs e da API de persistência.
Então você deve estar se perguntando: “Mas… então, qual é o lugar certo deste arquivo?”. A resposta é: “Na raíz do JAR!”. Vamos então criar uma task do Ant para copiar este arquivo para a raiz antes de efetuar o empacotamento da aplicação.
Abra o arquivo build.xml, através da guia Files. Cole a seguinte task no final deste arquivo:
-
-
<project>
-
…
-
<target name="-pre-compile">
-
<copy file="${meta.inf}/seam.properties" todir="${build.dir}/ear-module" />
-
</target>
-
</project>
-
Finalizando as configurações do Seam no projeto Registration-ejb, vamos criar um novo arquivo-padrão de Deployment e configurar o interceptor do Seam para que este possa, erhm, interceptar as chamadas aos nossos EJBs para tratar da “bijeção” de atributos de e para o contexto:
Depois de criado o arquivo ejb-jar.xml, o edite para que fique de acordo com a imagem abaixo:
-
-
<?xml version="1.0" encoding="UTF-8" ?>
-
-
<ejb-jar>
-
-
<assembly-descriptor>
-
<interceptor-binding>
-
<ejb-name>*</ejb-name>
-
<interceptor-class>
-
org.jboss.seam.ejb.SeamInterceptor
-
</interceptor-class>
-
</interceptor-binding>
-
</assembly-descriptor>
-
* para conhecer melhor os conceitos do Seam, como “bijeção”, vale uma olhada na documentação do projeto Seam.
Modificando a aplicação
A primeira - e mais significativa - mudança é a seguinte: iremos remover o managed bean User e mapear as variáveis do contexto JSF diretamente a um Entity Bean! Então, você está livre para ir até ao arquivo faces-config.xml e remover o nosso Managed Bean.
Já no projeto Registration-ejb, renomeie o pacote mbean para bean. Vá até o pacote bean, na guia Projects, e o arraste, do projeto Registration-war, para o projeto Registration-ejb.
Criando um Entity Bean
Chegou a hora de fazermos um upgrade no nosso ex-ManagedBean e promovê-lo a Entity Bean! Oh, meu Deus! Este deve ser um momento glorioso na vida da classe User
Modifique a classe User de acordo com a listagem:
-
-
// …
-
@Scope(ScopeType.EVENT)
-
-
@Table(name="users")
-
@NamedQuery(name="users.findByUsername",
-
query="SELECT u FROM User u WHERE u.username = :username")
-
-
@Id
-
@Column(length=20, nullable=false)
-
@NotNull @Length(min=5, max=20)
-
private String username;
-
-
@Column(length=20, nullable=false)
-
@NotNull @Length(min=5, max=20)
-
private String password;
-
-
@Column(length=150)
-
@Length(max=150)
-
private String name;
-
-
// …
-
}
-
Algumas coisas merecem ser explicadas. Oh, a primeira: não implementei aqui os métodos equals(), hashCode() e toString() pelo fato de o exemplo funcionar perfeitamente sem esses métodos, embora eles DEVAM ser implementados em um Bean de uma aplicação real! Ah, e o resto do código do Bean User continua do jeito que estava antes.
Agora, deixe-me explicar algumas coisas coisas. As anotações @Entity, @Table, @NamedQuery, @Id e @Column fazem parte da especificação JPA e, portanto, estão fora do escopo deste tutorial. Agora, as anotações @Name, @Scope, @NotNull e @Length:
@Name- É utilizada pelo Seam para registrar um componente sob um determinado nome único na aplicação. É através desse nome que o Seam faz a localização dos componentes;@Scope- É utilizada pelo Seam para determinar o escopo de um componente. Caso esta anotação não esteja presente, o Seam atribui um escopo ao componente de acordo com o seu tipo. Por exemplo, Session Beans Stateless são associados ao escopo Stateless. Session Beans Stateful são associados ao escopo Conversation. Mais detalhes sobe a atribuição de escopos-padrão aos componentes e sobre os tipos de escopo disponíveis no Seam, leia a documentação;@NotNull- O Seam integra facilmente com o Hibernate Validator e esta anotação serve para validar um determinado atributo, não permitindo que este seja nulo. Caso algum problema de validação seja detectado, podemos fazer com que o Seam mostre novamente o formulário para que os dados sejam re-digitados pelo usuário;@Length- Assim como@NotNull, mas permite que façamos uma validação de comprimento, onde, nos exemplos, só permitimos que a requisição seja aceita caso os atributos username e password tenham tamanhos entre 5 e 20 caracteres.
Configurando o Persistence Unit
Ok… vamos prosseguir com a modificação da nossa aplicação. Você notou que o NetBeans sublinhou a anotação @Entity? O que ele quer dizer é que nós não criamos nenhuma unidade de persistência na nossa aplicação:
Provavelmente você ainda não vai ter o Data Source criado e configurado, portanto, no combo Data Source, selecione a opção New Data Source. Na janela que aparecer, basta configurar uma conexão com um banco de dados e dar um nome para o Data Source:
No meu caso, eu criei uma base chamada test no meu servidor MySQL e dei o nome “db_registration” para o Data Source. Confirme a criação do Data Source e conclua também a criação da unidade de persistência:
Ainda precisamos fazer uma mudança no arquivo persistence.xml para que ele funcione corretamente no JBoss. Troque o nome do Data Source de “db_registration” para “java:/db_registration”. Também devemos informar o dialeto do banco de dados:
-
-
<?xml version=‘1.0′ encoding=‘UTF-8′?>
-
<persistence>
-
<persistence-unit name="default" transaction-type="JTA">
-
<provider>org.hibernate.ejb.HibernatePersistence</provider>
-
<jta-data-source>java:/db_registration</jta-data-source>
-
<properties>
-
<property name="hibernate.hbm2ddl.auto" value="update" />
-
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLInnoDBDialect" />
-
</properties>
-
</persistence-unit>
-
</persistence>
-
Ufa! Configuramos a parte de persistência da aplicação. Ahhhh claro: não esqueça de copiar o seu driver JDBC para o diretório lib do seu JBoss! Senão, durante o startup do Hibernate, ele não conseguirá localizar o driver JDBC e te mostrará um belo de um erro!
Criando um Stateless Session Bean
Vamos agora criar um Session Bean do tipo Stateless para tratar os eventos de submissão do formulário de cadastro. Clique com o botão direito do mouse no projeto Registration-ejb e selecione a opção New-Session Bean…. Dê o nome RegisterUser ao Session Bean. AH, crie-o no pacote business:
Modifique a interface RegisterUserLocal:
-
-
package business;
-
-
import javax.ejb.Local;
-
-
@Local
-
public interface RegisterUserLocal {
-
}
-
Modifique também a implementação da interface:
-
-
// …
-
@Stateless
-
public class RegisterUserBean implements RegisterUserLocal {
-
-
@PersistenceContext
-
private EntityManager em;
-
-
@In
-
private User user;
-
-
-
.setParameter("username", user.getUsername()).getResultList();
-
-
if (l.size() == 0) {
-
em.persist(user);
-
return "registered";
-
}
-
-
FacesMessages.instance().add("User #{user.username} already exists.");
-
return null;
-
}
-
}
-
Finalmente… integrando o JSF ao EJB!
Ok!! Tenha calma, pois falta muito pouco! Para finalizar, volte até o arquivo welcomeJSF.jsp e modifique a tag
-
-
<%@page contentType="text/html" %>
-
<%@page pageEncoding="UTF-8" %>
-
-
<%@taglib prefix="f" uri="http://java.sun.com/jsf/core" %>
-
<%@taglib prefix="h" uri="http://java.sun.com/jsf/html" %>
-
<%@taglib prefix="s" uri="http://jboss.com/products/seam/taglib" %>
-
-
<f:view>
-
<f:loadBundle basename="bundle.messages" var="msg" />
-
</head>
-
<h:form>
-
<s:validateAll>
-
<h:panelGrid columns="2">
-
<h:outputLabel for="username" value="#{msg.register_label_username}" />
-
<h:inputText id="username" value="#{user.username}" required="true" />
-
-
<h:outputLabel for="password" value="#{msg.register_label_password}" />
-
<h:inputSecret id="password" value="#{user.password}" required="true" />
-
-
<h:outputLabel for="name" value="#{msg.register_label_name}" />
-
<h:inputText id="name" value="#{user.name}" />
-
-
<h:commandButton id="submit" value="#{msg.register_label_submit}"
-
ction="#{registerUser.register}" />
-
</h:panelGrid>
-
</s:validateAll>
-
</h:form>
-
</body>
-
</html>
-
</f:view>
-
É isso! Rode sua aplicação e veja o Seam ligando os nossos EJBs com as páginas JSF!
Conclusão
Você deve estar traumatizado com a quantidade de configuração necessária.. mas pare um pouco para pensar: todas as configurações que fizemos não são do tipo que aumentam conforme a aplicação vai crescendo, ou seja, provavelmente você poderá ter dezenas de EJBs interagindo com diversas páginas JSF e tabelas do banco de dados sem ter que acrescentar nenhuma linha à configuração já criada. Isso é uma bênção em aplicações de médio a grande porte.
E então? Você gostou deste tutorial? Ou achou o mesmo um belo pé-no-saco? Ele funcionou com você? Ou só deu problemas? Comente!
* Créditos ao tutorial Trying out JBoss’Seam, de Brian Leonard, que deu uma força para que eu conseguisse montar este tutorial!
UPDATE: Não deixe de conferir as partes um e dois do tutorial!
Tags: introdução, java, jsf, netbeans, seam, tutorial

15 de fevereiro de 2007 às 11:06 pm
cara, muito legal seu tutorial, eu não tentei, apenas li
mas está de parabéns!
17 de outubro de 2007 às 5:39 pm
Estou começando agora com o Seam e sem dúvida seu tutorial é muito útil.
Parabéns e obrigado!
17 de outubro de 2007 às 6:01 pm
Eu que agradeço! É sempre bom saber que tem gente aproveitando esses textos.
Abraço.
19 de dezembro de 2007 às 2:25 pm
Cara isto foi um pe no saco apesar de eu nao ter um rsrsrsr,
mto ruim xau bjo
19 de dezembro de 2007 às 2:34 pm
Na época que eu escrevi esse artigo, realmente não havia jeito de escapar de toda essa chatisse de ter que configurar tudo na mão. No entanto, já faz algum tempo que o Seam vem acompanhado de alguns programinhas CLI (targets Ant, na verdade) que já geram um projeto pronto para uso, sem que nenhuma configuração manual seja necessária… bem nos moldes do Rails mesmo.
Quanto a você não ter um saco… bem… azar o seu!
[]s!
24 de março de 2008 às 10:21 am
Embora o tutorial seja “um pouco” antigo, rsrsr, ainda cabe uma questão. Adaptando um projeto netbeans para usar o seam (ao contrário de gerar pelo seam gen), ainda seria possível criar um client desktop (swing, whatever) e fazer uso das entities (com anotações seam) e dos services (não os novos-managed-beans-seam, mas digamos que tenha um service q tenha regras de negocios q seja utilizado pelos novos-managed-beans-seam) ????
O fato é que eu não gostei muito da estrutura criada pelo seam gen… it’s weird… =P
24 de março de 2008 às 8:14 pm
Eu não vejo motivos pq não funcionaria. (embora eu não saiba o que são esses “novos-managed-beans-seam”)
19 de agosto de 2008 às 5:28 pm
Muito bem explicado, parabéns!
25 de setembro de 2008 às 3:01 pm
Muito bom, ja add nos favoritos e vai me servir de consulta para meu projeto.