Estrutura de um projeto Seam

August 30th, 2008 by rafaelliu Leave a reply »

O seam-gen é um gerador de scaffolding muito útil para quem programa em Seam. O seam-gen em si é uma ferramenta CLI, mas o JBoss Tools nos dá uma GUI para facilitar nossa vida. Bom, então o primeiro passo é instalar o plugin do JBoss Tools. É só baixar do site deles e descompactar no diretório do Eclipse, nada de mais.

Você notará que serão adicionadas várias perspectivas, entre elas, a Seam. Vamos selecionar essa perspectiva e criar um novo Seam Project. Com isso já temos um projeto funcional com segurança, apresentação de erros, e conexão com banco de dados. Também é criado um projeto <projeto>-Test para testes. Vamos entender um pouco do que nos foi gerado.

  1. classe usada pelo Seam para autenticaçãoseam-gen-structure
  2. arquivo chave. Indica ao Seam que ele deve procurar nesse diretório por componentes
  3. persistence.xml do JPA
  4. arquivo com algumas propriedados a serem substituidas pelo Ant no components.xml
  5. import.sql do Hibernate
  6. mensagens para internacionalização
  7. arquivo Drools com regras de autorização
  8. datasource gerado para o JBoss
  9. arquivo de configuração do Seam (componentes, integração)
  10. arquivo de configuração WAR do JBoss
  11. arquivo de configuração do Seam (regras de fluxo, segurança, controle de conversação)
  12. similar ao arquivo pages.xml, mas específico para o login.xhtml
  13. arquivo de configuração do plugin Hibernate Console

Vamos ver por alto algumas configurações interessantes. Na parte de segurança temos no components.xml:

<event type="org.jboss.seam.security.notLoggedIn">
<action execute="#{redirect.captureCurrentView}"/>
</event>
<event type="org.jboss.seam.security.loginSuccessful">
<action execute="#{redirect.returnToCapturedView}"/>
</event>

O Seam possui o conceito de eventos. Eventos são mensagens que podem ser capturadas ou lançadas, no estilo broadcast. O Seam em si lança vários eventos e podemos capturar esses eventos através de XML, como no exemplo acima. O trecho acima está invocando métodos do componente built-in #{redirect} quando eventos de segurança forem lançados. Ele especifica que a view id JSF deve ser salva quando o usuário não-logado tentar acessar uma página restrita e que essa view id deve ser restaurada uma vez que ele se autentique.
Um outro trecho especifica que componente é responsável pela autenticação:

<security:identity authenticate-method="#{authenticator.authenticate}"
security-rules="#{securityRules}"
remember-me="true"/>

E no pages.xml dizemos que página deve ser utilizada para login:

<exception class="org.jboss.seam.security.NotLoggedInException">
<redirect view-id="/login.xhtml">
<message>Please log in first</message>
</redirect>
</exception>

Aqui temos um tratamento de exceção bem parecido com o de servlets que definimos no web.xml. O usuário será redirecionado para a página login.xhtml e uma mensagem JSF será adicionada.
Se olharmos no login.pages.xml vemos ainda:

<navigation from-action="#{identity.login}">
<rule if="#{identity.loggedIn}">
<redirect view-id="/home.xhtml"/>
</rule>
</navigation>

O que nos lembra bastante as navigation rules JSF. De fato parecem muito, mas as extendem em funcionalidade, podendo não só enviar o usuário para outra página como também lançar um evento, executar um método para avaliar qual será a próxima página, e algumas coisas mais avançadas.

O objetivo desse post é apenas nos familiarizar mais com o Seam e dar uma visão sobre o scaffold que nos foi gerado de base e que iremos usar para desenvolver nossa aplicação. Ainda vamos falar com mais detalhes de eventos, componentes e configurações.

Advertisement

8 comments

  1. Estou querendo no page.xml fazer com que somente se estiver logado e possui a role ADMIN pode acessar o sistema, se não vai para página de login…

    como seria feito?

  2. rafaelliu says:

    Use o <restrict>, está bem documentado no site oficial.

  3. Romano says:

    Ola Rafael,

    Usei o seam-gen para gerar uma aplicação crud e agora estou customizando. Seria duas entidades, Noticia e Tipos de Noticias. Assim uma noticia poderia ter varias noticias.

    O código gerado pelo seam-gean para eu fazer uma inclusão de uma noticia, eu tenho que primeiro escolher um tipo de noticia e depois retorno para tela de inclusão de noticia para adiciona-la. Na minha customização eu inclui um Data Model List na NoticiaHome e inclui o metodo abaixo:

    @Factory(value=”tpNoticias”)
    @SuppressWarnings(“unchecked”)
    public void consultar(){
    tpNoticias = getEntityManager().createQuery(“select t from Tiponoticias t”).getResultList();
    }

    A página rederiza agora com a opção do Tipo de noticia para o usuário escolher. Só que o problema eh quando eu tento incluir uma noticia ele gera a exceção : no transaction is in progress

    Eu já vi diversas soluções abandonando o EntityHome e chamando na classe action o EntityManager.

    Queria saber se eh possivel continuar usando o EntityHome ou isso seria uma limitação mesmo.

    Abs

  4. rafaelliu says:

    @Romano

    Não entendi sua pergunta.. É possível sim usar EntityHome com controle transacional (@Begin e @End).

    Poderia explicar melhor?

  5. Romano says:

    Oi Rafael,

    Desculpa se eu não fui claro, estou usando o seam-gen para criar uma aplicação do zero. O meu problema pontual é que quando eu tento dar persist na classe NoticiaHome que extende a EntityHome ele gera a exceção: WARN [lifecycle] #{noticiasHome.persist}: javax.persistence.TransactionRequiredException: no transaction is in progress.

    A única modificação que eu fiz no código proveninente do seam-gen foi a inclusão de um Data Model Tipo de noticia, uma classe que possui um relacionamento @ManyToOne com a classe Noticias para que o usuário pudesse incluir tudo na mesma página ao inves de ter que ir em outra página para instanciar a classe Tiponoticia e depois retornar pagina de inclusão Noticia como o gerador cria a aplicação.

    Eu também postei a minha duvida no guj com os codigos da classe Noticias, se ajudar:
    http://www.guj.com.br/posts/list/147962.java#799471

    Agradeço desde já,

    Abs,

  6. rafaelliu says:

    @Romano

    O seu EntityHome está bem modificado.. Use um @Begin no seu createInstance(). Se você estiver redirecionando o usuário para a página gerada pelo seam-gen, a conversação já será comitada. Se não você terminar ela, por exemplo através da invocação de um método @End.

    Testa ai, e fala se funcionou.

    abs

  7. Romano says:

    Oi Rafael, acabei saindo de recesso de final de ano. Bem, sobre o último post, o meu NoticiaHome só tem a inclusão da lista de tipo de noticia o resto foi tudo gerado pelo seam-gen.
    Sobre as notações eu inclui a notação @Begin no metodo createInstance(), agora não entendi sobre a criação de um metodo com a notação @End.
    Os metodos crud são herdados pela EntityHome que eh do componente, como eu faria essa invocação? Faria uma sobreposição do metodo?
    Eu poderia te mandar um zip com a aplicação gerada pelo seam-gen?
    Abs,

Leave a Reply