SeamFramework.orgCommunity Documentation

Capítulo 3. Web Beans, a Implementação de Referência da JSR-299

3.1. Utilizando o JBoss AS 5
3.2. Utilizando o Apache Tomcat 6.0
3.3. Utilizando o GlassFish
3.4. O exemplo numberguess
3.4.1. O exemplo numberguess para o Tomcat
3.5. O exemplo translator

A Web Beans está sendo desenvolvida no projeto Seam. Você pode baixar a última versão da Web Beans na página de downloads.

A Web Beans vem com duas aplicações de exemplo: webbeans-numberguess, um war, contendo apenas beans simples (simple beans), e webbeans-translator um ear, contendo beans corporativos (enterprise beans). Existem ainda, duas variações do exemplo numberguess: o exemplo tomcat (adequado para a implantação no Tomcat) e o exemplo jsf2, que você pode usar se estiver utilizando JSF2. Para executar os exemplos, você precisará do seguinte:

Você precisa fazer o download do JBoss AS 5.0.1.GA em jboss.org e descompactá-lo. Por exemplo:"

$ cd /Applications
$ unzip ~/jboss-5.0.1.GA.zip

Depois, faça o download da Web Beans em seamframework.org e descompacte-o. Por exemplo

$ cd ~/
$ unzip ~/webbeans-1.0.0.ALPHA1.zip

Em seguida, temos de dizer aos Web Beans onde o JBoss está localizado. Editar o jboss-as/build.properties e definir a propriedade jboss.home. Por exemplo:

jboss.home=/Applications/jboss-5.0.1.GA

Para instalar a Web Beans, você precisará do Ant 1.7.0 instalado e a variável de ambiente ANT_HOME setada. Por exemplo:

$ unzip apache-ant-1.7.0.zip
$ export ANT_HOME=~/apache-ant-1.7.0

Então, você pode instalar a atualização. O script de atualização irá utilizar o Maven para fazer o download da Web Beans automaticamente.

$ cd webbeans-1.0.0.ALPHA1/jboss-as
$ ant update

Agora, você está pronto para fazer a publicação do seu primeiro exemplo!

Dica

Os scripts para criar os exemplos oferecem uma série de alvos para JBoss AS, entre eles:

  • ant restart - implanta o exemplo no formato explodido

  • ant explode - atualiza o exemplo explodido, sem reiniciar

  • ant deploy - implanta o exemplo no formato jar compactado

  • ant undeploy - remove o exemplo do servidor

  • ant clean - limpa o exemplo

Para implantar o exemplo numberguess:

$ cd examples/numberguess
ant deploy

Inicializando o JBoss AS:

$ /Application/jboss-5.0.0.GA/bin/run.sh

Dica

Se você utiliza o Windows, utilize o script run.bat.

Aguarde até que a aplicação seja implantada, e desfrute de horas de diversão em http://localhost:8080/webbeans-numberguess!

Web Beans includes a second simple example that will translate your text into Latin. The numberguess example is a war example, and uses only simple beans; the translator example is an ear example, and includes enterprise beans, packaged in an EJB module. To try it out:

$ cd examples/translator
ant deploy

Aguarde até que a aplicação seja implantada, e acesse http://localhost:8080/webbeans-translator!

Depois, faça o download do Tomcat 6.0.18 ou posterior em tomcat.apache.org, e descompacte-o. Por exemplo

$ cd /Applications
$ unzip ~/apache-tomcat-6.0.18.zip

Depois, faça o download da Web Beans em seamframework.org e descompacte-o. Por exemplo

$ cd ~/
$ unzip ~/webbeans-1.0.0.ALPHA1.zip

Em seguida, temos de dizer aos Web Beans onde o Tomcat está localizado. Editar o jboss-as/build.properties e definir a propriedade tomcat.home. Por exemplo:

tomcat.home=/Applications/apache-tomcat-6.0.18

Dica

Os scripts para criar os exemplos oferecem uma série de alvos para Tomcat, estes são:

  • ant tomcat.restart - publica o exemplo no formato explodido

  • ant tomcat.explode - atualiza o exemplo explodido, sem reiniciar

  • ant tomcat.deploy - publica o exemplo no formato jar compactado

  • ant tomcat.undeploy - remove o exemplo do servidor

  • ant tomcat.clean - clean the example

Para implantar o exemplo numberguess no tomcat:

$ cd examples/tomcat
ant tomcat.deploy

Inicializando o Tomcat:

$ /Applications/apache-tomcat-6.0.18/bin/startup.sh

Dica

Se você utiliza o Windows, utilize o script startup.bat.

Aguarde até que a aplicação seja implantada, e desfrute de horas de diversão em http://localhost:8080/webbeans-numberguess!

TODO

Na aplicação numberguess você terá 10 tentativas para adivinhar um número entre 1 e 100. Após cada tentativa, você será informado se você disse muito acima, ou muito a baixo.

O exemplo numberguess é composto de um número de Web Beans, arquivos de configuração, e páginas Facelet JSF , empacotados como um war. Vamos começar com os arquivos de configuração.

All the configuration files for this example are located in WEB-INF/, which is stored in WebContent in the source tree. First, we have faces-config.xml, in which we tell JSF to use Facelets:


<?xml version='1.0' encoding='UTF-8'?>
<faces-config version="1.2"
              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-facesconfig_1_2.xsd">
    
    <application>
        <view-handler
>com.sun.facelets.FaceletViewHandler</view-handler>
    </application>

</faces-config
>

Existe um arquivo web-beans.xml vazio, que assinala esta aplicação como uma aplicação Web Beans.

Finalmente no web.xml:

Let's take a look at the Facelet view:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:s="http://jboss.com/products/seam/taglib">

  <ui:composit(1)ion template="template.xhtml">
    <ui:define name="content">
       <h1
>Guess a number...</h1>
       <h:form(2) id="NumberGuessMain">
          <div style="color: red">
             <h:messages id="messages" globalOnly="false"/>
             <h:outputText id="Higher" value="Higher!" rendered="#{game.number gt game.guess and game.guess ne 0}"/>
             <h:outputText id="Lower" value="Lower!" rendered="#{game.number lt game.guess and game.guess ne 0}"/>
          </div>
   
          <div(3)>
             I'm thinking of a number between #{game.smallest} and #{game.biggest}.
             You have #{game.remainingGuesses} guesses.
          </div>
     
          <div>
             Y(4)our guess: 
             <h:inputText id="inputGuess" 
                          value="#{game.guess}" 
                          required="true" 
                          size="3" 
              (5)            disabled="#{game.number eq game.guess}">
                <f:validateLongRange maximum="#{game.biggest}" 
                                     minimum="#{game.smallest}"/>
             <(6)/h:inputText>
            <h:commandButton id="GuessButton"  
                             value="Guess" 
                             action="#{game.check}" 
                             disabled="#{game.number eq game.guess}"/>
          </div>
          <div>
            <h:commandButton id="RestartButton" value="Reset" action="#{game.reset}" immediate="true" />
          </div>
       </h:form>
    </ui:define>
  </ui:composition>
</html
>
1

Facelets is a templating language for JSF, here we are wrapping our page in a template which defines the header.

2

There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!"

3

As the user guesses, the range of numbers they can guess gets smaller - this sentance changes to make sure they know what range to guess in.

4

This input field is bound to a Web Bean, using the value expression.

5

A range validator is used to make sure the user doesn't accidentally input a number outside of the range in which they can guess - if the validator wasn't here, the user might use up a guess on an out of range number.

6

And, of course, there must be a way for the user to send their guess to the server. Here we bind to an action method on the Web Bean.

The example exists of 4 classes, the first two of which are binding types. First, there is the @Random binding type, used for injecting a random number:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface Random {}

Há também o binding type @MaxNumber, utilizado para injetar o número máximo que pode ser injetado:

@Target( { TYPE, METHOD, PARAMETER, FIELD })

@Retention(RUNTIME)
@Documented
@BindingType
public @interface MaxNumber {}

A classe Generator é responsável por criar um número aleatório, através de um método produtor. Ela também expõe o número máximo possível através de um método produtor:

@ApplicationScoped

public class Generator {
   
   private java.util.Random random = new java.util.Random( System.currentTimeMillis() );
   
   private int maxNumber = 100;
   
   java.util.Random getRandom()
   {
      return random;
   }
   
   @Produces @Random int next() { 
      return getRandom().nextInt(maxNumber); 
   }
   
   @Produces @MaxNumber int getMaxNumber()
   {
      return maxNumber;
   }
}

Você perceberá que o Generator está no escopo de aplicação; portanto, não obtemos um número aleatório diferente a cada vez.

O Web Bean final da aplicação é o Game em escopo de sessão.

You'll note that we've used the @Named annotation, so that we can use the bean through EL in the JSF page. Finally, we've used constructor injection to initialize the game with a random number. And of course, we need to tell the player when they've won, so we give feedback with a FacesMessage.

package org.jboss.webbeans.examples.numberguess;



import javax.annotation.PostConstruct;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.webbeans.AnnotationLiteral;
import javax.webbeans.Current;
import javax.webbeans.Initializer;
import javax.webbeans.Named;
import javax.webbeans.SessionScoped;
import javax.webbeans.manager.Manager;
@Named
@SessionScoped
public class Game
{
   private int number;
   
   private int guess;
   private int smallest;
   private int biggest;
   private int remainingGuesses;
   
   @Current Manager manager;
   
   public Game()
   {
   }
   
   @Initializer
   Game(@MaxNumber int maxNumber)
   {      
      this.biggest = maxNumber;
   }
   public int getNumber()
   {
      return number;
   }
   
   public int getGuess()
   {
      return guess;
   }
   
   public void setGuess(int guess)
   {
      this.guess = guess;
   }
   
   public int getSmallest()
   {
      return smallest;
   }
   
   public int getBiggest()
   {
      return biggest;
   }
   
   public int getRemainingGuesses()
   {
      return remainingGuesses;
   }
   
   public String check()
   {
      if (guess
>number)
      {
         biggest = guess - 1;
      }
      if (guess<number)
      {
         smallest = guess + 1;
      }
      if (guess == number)
      {
         FacesContext.getCurrentInstance().addMessage(null, new FacesMessage("Correct!"));
      }
      remainingGuesses--;
      return null;
   }
   
   @PostConstruct
   public void reset()
   {
      this.smallest = 0;
      this.guess = 0;
      this.remainingGuesses = 10;
      this.number = manager.getInstanceByType(Integer.class, new AnnotationLiteral<Random
>(){});
   }
   
}

O exemplo translator pegará qualquer frase que você fornecer, e traduzi-las para o Latim.

O exemplo translator é construído como um ear, e contém EJBs. Como resultado, a sua estrutura é mais complexa do que exemplo numberguess.

First, let's take a look at the ear aggregator, which is located in webbeans-translator-ear module. Maven automatically generates the application.xml for us:


<plugin>
   <groupId
>org.apache.maven.plugins</groupId>
   <artifactId
>maven-ear-plugin</artifactId>
   <configuration>
      <modules>
         <webModule>
            <groupId
>org.jboss.webbeans.examples.translator</groupId>
            <artifactId
>webbeans-translator-war</artifactId>
            <contextRoot
>/webbeans-translator</contextRoot>
         </webModule>
      </modules>
   </configuration>
</plugin
>

Aqui nós definiremos o caminho do contexto, que nos dá uma url amigável (http://localhost:8080/webbeans-translator). ulink>) .

Dica

Se você não está usando o Maven para gerar esses arquivos, você precisaria META-INF/application.xml:


<?xml version="1.0" encoding="UTF-8"?>
<application 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/application_5.xsd"
             version="5">
  <display-name
>webbeans-translator-ear</display-name>
  <description
>Ear Example for the reference implementation of JSR 299: Web Beans</description>
  
  <module>
    <web>
      <web-uri
>webbeans-translator.war</web-uri>
      <context-root
>/webbeans-translator</context-root>
    </web>
  </module>
  <module>
    <ejb
>webbeans-translator.jar</ejb>
  </module>
</application
>

Next, lets look at the war. Just as in the numberguess example, we have a faces-config.xml (to enable Facelets) and a web.xml (to enable JSF) in WebContent/WEB-INF.

Mais interessante é o facelet utilizado para traduzir texto. Tal como no exemplo numberguess temos um template, que envolve o formulário (omitido aqui por brevitude):


<h:form id="NumberGuessMain">
            
   <table>
      <tr align="center" style="font-weight: bold" >
         <td>
            Your text
         </td>
         <td>
            Translation
         </td>
      </tr>
      <tr>
         <td>
            <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
         </td>
         <td>
            <h:outputText value="#{translator.translatedText}" />
         </td>
      </tr>
   </table>
   <div>
      <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
   </div>
   
</h:form
>

O usuário pode digitar um texto no textarea esquerdo, e clicar no botão traduzir para ver o resultado à direita.

Finally, let's look at the ejb module, webbeans-translator-ejb. In src/main/resources/META-INF there is just an empty web-beans.xml, used to mark the archive as containing Web Beans.

We've saved the most interesting bit to last, the code! The project has two simple beans, SentenceParser and TextTranslator and two enterprise beans, TranslatorControllerBean and SentenceTranslator. You should be getting quite familiar with what a Web Bean looks like by now, so we'll just highlight the most interesting bits here.

Tanto SentenceParser e TextTranslator são beans dependentes, e TextTranslator usa inicialização por construtor :

<h:form id="NumberGuessMain">

            
   <table>
      <tr align="center" style="font-weight: bold" >
         <td>
            Your text
         </td>
         <td>
            Translation
         </td>
      </tr>
      <tr>
         <td>
            <h:inputTextarea id="text" value="#{translator.text}" required="true" rows="5" cols="80" />
         </td>
         <td>
            <h:outputText value="#{translator.translatedText}" />
         </td>
      </tr>
   </table>
   <div>
      <h:commandButton id="button" value="Translate" action="#{translator.translate}"/>
   </div>
   
</h:form
>

TextTranslator é um bean stateless (com uma interface de negócios local), onde a mágica acontece - obviamente, não poderíamos desenvolver um tradutor completo, mas demos-lhe um bom caminho!

Finally, there is UI orientated controller, that collects the text from the user, and dispatches it to the translator. This is a request scoped, named, stateful session bean, which injects the translator.

@Stateful

@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController
{
   
   @Current TextTranslator translator;

O bean também tem getters e setters para todos os campos da página.

Como esse é um stateful session bean, temos de ter um método de remoção:

   @Remove

   public void remove()
   {
      
   }

O gerenciador do Web Beans irá chamar o método remover para você quando o bean for destruído, neste caso no final da requisição.

That concludes our short tour of the Web Beans examples. For more on Web Beans , or to help out, please visit http://www.seamframework.org/WebBeans/Development.

Precisamos de ajuda em todas as áreas - correção de bugs, escrita de novas funcionalidades, escrita de exemplos e tradução deste guia de referência.