Back-End

5 ago, 2010

Trabalhando com JBoss Weld e JSF 2.0

Publicidade

Olás! 

O framework de desenvolvimento JSF vem ganhando bastante espaço entre desenvolvedores e empresas. A versão 1.2 trouxe bastante melhorias, mas ainda é como se ele tivesse diversos GAPs, por exemplo, por muito tempo utilizei o JBoss Seam para suprir coisas chatas que o JSF 1.2 não provia por padrão.

Não vamos gastar tempo aqui explicando o que é o JBoss Weld; veja abaixo a explicação sobre ele, a partir do site oficial http://seamframework.org/Weld.

Weld is the reference implementation (RI) for JSR-299: Java Contexts and Dependency Injection for the Java EE platform (CDI). CDI is the Java standard for dependency injection and contextual lifecycle management. JSR-299 is a Java Community Process (JCP) standard that integrates cleanly with the Java EE platform. Any Java EE 6-compliant application server provides support for JSR-299 (even the web profile).

Pré-Requisitos

Ter JDK 6 instalada, Maven 2.2.1 ou posterior e um editor à sua escolha. No meu caso, vou utilizar o bom e velho Eclipse.

Criando o projeto Web vazio

Vamos criar nosso projeto base a partir do archetype:generate do maven. Crie o diretório com o nome do seu projeto e execute a seguinte linha de comando:

mvn archetype:generate -DinteractiveMode=n -DarchetypeArtifactId=maven-archetype-webapp -Dversion=0.0.1-SNAPSHOT -DgroupId=br.com.brenooliveira.weld -DartifactId=weld_tutorial

Acredito que você já utilizava o Maven antes e já deve saber que ele não cria todos as pastas necessárias, mas apenas a estrutura mínima. Então ainda precisamos criar as seguintes pastas:

weld_tutorial/src/test

weld_tutorial/src/test/java

weld_tutorial/src/test/resources

weld_tutorial/src/main/java

Configurando o pom.xml

No pom.xml, apenas vamos adicionar as dependências necessárias para que nosso projeto funcione e também vamos configurar um jetty para facilitar nosso desenvolvimento.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelversion>4.0.0</modelversion>
<groupid>teste-weld</groupid>
<artifactid>weld-tutorial</artifactid>
<packaging>war</packaging>
<version>1.0.0-SNAPSHOT</version>
<name>spronline Maven Webapp</name>
<url>http://maven.apache.org</url>

<repositories>
<!-- Adicionamos o Repositório do JBoss para garantia de encontrar as dependências -->
<repository>
<id>repository.jboss.org</id>
<name>JBoss Repository</name>
<url>http://repository.jboss.org/maven2</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<dependencies>
<dependency>
<groupid>junit</groupid>
<artifactid>junit</artifactid>
<version>3.8.1</version>
<scope>test</scope>
</dependency>

<!-- Comum -->
<dependency>
<groupid>javax.enterprise</groupid>
<artifactid>cdi-api</artifactid>
<scope>provided</scope>
<version>1.0-CR1</version>
</dependency>

<dependency>
<groupid>javax.annotation</groupid>
<artifactid>jsr250-api</artifactid>
<version>1.0</version>
</dependency>

<dependency>
<groupid>javax.faces</groupid>
<artifactid>jsf-api</artifactid>
<version>2.0.0-RC</version>
</dependency>

<!-- Especifico para Jetty -->
<dependency>
<groupid>javax.faces</groupid>
<artifactid>jsf-impl</artifactid>
<scope>runtime</scope>
<version>2.0.0-RC</version>
</dependency>

<dependency>
<groupid>javax.servlet</groupid>
<artifactid>jstl</artifactid>
<version>1.2</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupid>org.jboss.weld.servlet</groupid>
<artifactid>weld-servlet</artifactid>
<version>1.0.0-CR1</version>
<scope>runtime</scope>
</dependency>

<dependency>
<groupid>org.glassfish.web</groupid>
<artifactid>el-impl</artifactid>
<version>2.1.2-b04</version>
<scope>runtime</scope>
<exclusions>
<exclusion>
<groupid>javax.el</groupid>
<artifactid>el-api</artifactid>
</exclusion>
</exclusions>
</dependency>
</dependencies>

<build>
<finalname>weldtutorial</finalname>
<plugins>
<!-- Força compilar em Java 1.6 -->
<plugin>
<groupid>org.apache.maven.plugins</groupid>
<artifactid>maven-compiler-plugin</artifactid>
<configuration>
1.6
<target>1.6</target>
</configuration>
</plugin>

<!-- Embedded Jetty (jetty:run) -->
<plugin>
<groupid>org.mortbay.jetty</groupid>
<artifactid>maven-jetty-plugin</artifactid>
<configuration>
<!-- Coloca um path com um nome mais amigavel -->
<contextpath>${build.finalName}</contextpath>
<!-- Aqui é onde declaramos BeanManager é contruido. -->
<jettyenvxml>${basedir}/src/test/resources/jetty-env.xml</jettyenvxml>
<!-- Para quem já trabalhou com JRebel sabe o quanto isso é bom. Um ótima feature do Jetty -->
<scanintervalseconds>3</scanintervalseconds>
</configuration>
</plugin>
</plugins>
</build>
</project>

Configurando nosso web.xml

Com o JSF 2 ainda precisamos configurar algumas coisas no web.xml, o que se tornou opcional é aquele arquivo faces-config.xml, então no web.xml:

<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemalocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" version="2.5">
<display-name>Weld Tutorial</display-name>

<context-param>
<param-name>javax.faces.DEFAULT_SUFFIX</param-name>
<param-value>.xhtml</param-value>
</context-param>
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.jsf</url-pattern>
</servlet-mapping>

<!-- Configuração de alguns parametros do Weld para o Jetty -->
<listener>
<listener-class>org.jboss.weld.environment.servlet.Listener</listener-class>
</listener>

<resource-env-ref>
<description>Object factory for the CDI Bean Manager</description>
<resource-env-ref-name>BeanManager</resource-env-ref-name>
<resource-env-ref-type>javax.enterprise.inject.spi.BeanManager</resource-env-ref-type>
</resource-env-ref>
</web-app>

Também é necessário indicar ao Weld para inicializar o DI (Dependency Injection). Para isso, basta criar um arquivo chamado beans.xml dentro da pasta WEB-INF/. A simples presença desse arquivo diz ao container que WEB-INF/classes é um bean deployment archive.

Preparando o Jetty

Para que nosso aplicativo funcione no jetty, precisamos configurar o jetty-env.xml, apenas vamos declarar quem é o nosso injetor de dependências.

<configure id="webAppCtx" class="org.mortbay.jetty.webapp.WebAppContext">
<new id="appManager" class="org.mortbay.jetty.plus.naming.Resource">
<arg>
<ref id="webAppCtx">
</ref></arg>
<arg>BeanManager</arg>
<arg>
<new class="javax.naming.Reference">
<arg>javax.enterprise.inject.spi.BeanManager</arg>
<arg>org.jboss.weld.resources.ManagerObjectFactory</arg>
<arg>
</arg></new>
</arg>
</new>
</configure>

Escrevendo nosso HelloWorld.java

Quem trabalhou com JSF 1.2 ou versões anteriores com certeza se lembra do quanto era entediante declarar todos os managed-bean; e quem já utilizou o JBoss Seam sabe o quanto é mais simples e também o quanto diminui a quantidade de linhas no faces-config.xml, pois essa configuração de XML é trocada para anotações, muito semelhante a como o JBoss Seam faz, para não falar igual. Então nossa classe HelloWorld.java fica:

package br.com.brenooliveira.actions;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.inject.Inject;
import javax.inject.Named;

@Named
@SessionScoped
public class HelloWorld implements Serializable {

private static final long serialVersionUID = 6325770734571129423L;

private String text = "Hello World JSF!";

public String getText() {
return text;
}
}

Como você pode observar, apenas adicionamos a anotação @Named. Ainda seria possível passar um valor nela, que acabaria definindo o nome do managed-bean.

Escrevendo .xhtml

Criado o nosso managed-bean, vamos chamar o atributo dela em nossa página xhtml.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://java.sun.com/jsf/html">
<h:head>
<title>JSF Demo</title>
</h:head>
<h:body>
<h1>Funcionou?</h1>
<h:form>
<h:commandButton action="#{helloWorld.doAction}" value="Chamar doAction()" />
<h:commandButton action="#{helloWorld.login}" value="Chamar login()" />
</h:form>
<p>My weld-injected bean says: #{helloWorld.text}</p>
</h:body>
</html>

Aqui não tem muito segredo, apenas chamamos o atributo de nosso managed-bean.

Executando o nosso projeto

Para executar o projeto, vamos utilizar o jetty. Se você observou no início, nós adicionamos o plugin do jetty para maven, então abra uma linha de comando no diretório do pom.xml e execute a seguinte linha de comando:

mvn war:inplace jetty:run

Depois basta acessar http://localhost:8080/weldtutorial/index.jsf e ver o resultado final.

Até a próxima!