SeamFramework.orgCommunity Documentation

Capítulo 3. Web Beans, the Reference Implementation of JSR-299

3.1. Using JBoss AS 5
3.2. Using Apache Tomcat 6.0
3.3. Using GlassFish
3.4. El ejemplo numberguess
3.4.1. The numberguess example for Tomcat
3.5. Ejemplo de traductor

The Web Beans is being developed at the Seam project. You can download the latest developer release of Web Beans from the the downloads page.

Web Beans comes with a two deployable example applications: webbeans-numberguess, a war example, containing only simple beans, and webbeans-translator an ear example, containing enterprise beans. There are also two variations on the numberguess example, the tomcat example (suitable for deployment to Tomcat) and the jsf2 example, which you can use if you are running JSF2. To run the examples you'll need the following:

You'll need to download JBoss AS 5.0.1.GA from jboss.org, and unzip it. For example:

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

Next, download Web Beans from seamframework.org, and unzip it. For example

$ cd ~/
$ unzip ~/webbeans-$VERSION.zip

Después necesitaremos decirle a Web Beans en dónde está localizado JBoss. Editar jboss-as/build.properties y establecer la propiedad jboss.home. Por ejemplo:

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

To install Web Beans, you'll need Ant 1.7.0 installed, and the ANT_HOME environment variable set. For example:

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

Then, you can install the update. The update script will use Maven to download Web Beans automatically.

$ cd webbeans-$VERSION/jboss-as
$ ant update

Ahora, ¡está listo para desplegar su primer ejemplo!

Sugerencia

The build scripts for the examples offer a number of targets for JBoss AS, these are:

  • ant restart - despliega el ejemplo en formato explotado

  • ant explode - actualiza un ejemplo explotado, sin reiniciar el despliegue

  • ant deploy - despliega el ejemplo en formato JAR comprimido

  • ant undeploy - quita el ejemplo del servidor

  • ant clean - borra el ejemplo

Para desplegar el ejemplo numberguess:

$ cd examples/numberguess
ant deploy

Start JBoss AS:

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

Sugerencia

If you use Windows, use the run.batscript.

Espere que despliegue la aplicación, y diviértase en 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

Espere a que despliegue la aplicación, y ¡visite http://localhost:8080/webbeans-translator!

You'll need to download Tomcat 6.0.18 or later from tomcat.apache.org, and unzip it. For example:

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

Next, download Web Beans from seamframework.org, and unzip it. For example

$ cd ~/
$ unzip ~/webbeans-$VERSION.zip

Next, we need to tell Web Beans where Tomcat is located. Edit jboss-as/build.properties and set the tomcat.home property. For example:

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

Sugerencia

The build scripts for the examples offer a number of targets for Tomcat, these are:

  • ant tomcat.restart - deploy the example in exploded format

  • ant tomcat.explode - update an exploded example, without restarting the deployment

  • ant tomcat.deploy - deploy the example in compressed jar format

  • ant tomcat.undeploy - remove the example from the server

  • ant tomcat.clean - clean the example

To deploy the numberguess example for tomcat:

$ cd examples/tomcat
ant tomcat.deploy

Start Tomcat:

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

Sugerencia

If you use Windows, use the startup.batscript.

Espere que despliegue la aplicación, y diviértase en http://localhost:8080/webbeans-numberguess!

TODO

En la aplicación numberguess se le dan 10 intentos para adivinar un número entre 1 y 100. Después de cada intento, se le dirá si es mayor o menor a su número.

El ejemplo de numberguess consta de una cantidad de Web Beans, archivos de configuración y páginas Facelet JSF, empaquetadas como WAR. Empecemos con los archivos de configuración.

Todos los archivos de configuración para este ejemplo están localizados en WEB-INF/, el cual está almacenado en WebContent en el árbol fuente. Primero, tenemos faces-config.xml, en donde le pedimos a JSF que utilice 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
>

Hay un archivo web-beans.xml vacío, el cual marca esta aplicación como una aplicación de Web Beans.

Por último, está 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.

El ejemplo existe de 4 clases, las primeras dos son tipos de enlace. Primero, hay un tipo de enlace @Random, utilizado para inyectar un número aleatorio:

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

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

También hay un tipo de enlace @MaxNumber, utilizado para inyectar el número máximo posible:

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

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

La clase Generator es responsable de crear el número aleatorio, a través de un método de productor. También expone el número máximo posible a través del método de productor:

@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;
   }
}

Notará que el Generador es una aplicación en ámbito por lo tanto no obtenemos un número aleatorio diferente cada vez.

El Web Bean final en la aplicación es la sesión en ámbito Juego.

Notará que hemos utilizado la anotación @Named, para poder utilizar el bean a través de EL en la página JSF. Por último, hemos utilizado la inyección de constructor para inicializar el juego con un número aleatorio. Y, claro está, necesitamos decirle al jugador cuando haya ganado, por lo tanto le damos retroalimentación con 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
>(){});
   }
   
}

El ejemplo de traductor tomará las oraciones que entre y las traducirá en Latín.

El ejemplo de traductor está incorporado como un EAR, y contiene EJB. Como resultado, su estructura es más compleja que el ejemplo de Numberguess.

Primero, demos una mirada al agregador EAR, el cual está localizado en el módulo webbeans-translator-ear. Maven genera automáticamente la application.xml:


<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
>

Aquí establecemos la ruta de contexto, la cual nos da una url interesante (http://localhost:8080/webbeans-translator).

Sugerencia

Si no está utilizando Maven para generar estos archivos, usted necesitaría 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
>Ejemplo Ear para la implementaci�n de referencia de 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.

Más interesante aún es el facelet utilizado para traducir texto. Al igual que en el ejemplo de Numberguess tenemos una plantilla, la cual rodea el formulario (omitido aquí por razones de brevedad):


<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
>

El usuario puede entrar texto en el área de texto a mano izquierda y pulsar el botón de traducir para ver el resultado a la derecha.

Por último, veamos el módulo EJB, webbeans-translator-ejb. En src/main/resources/META-INF sólo hay un web-beans.xml vacío, utilizado para marcar el archivo como si contuviera Web Beans.

Hemos guardado la parte más interesante para el final, ¡el código! El proyecto tiene dos beans sencillos, SentenceParser y TextTranslator y dos beans empresariales, TranslatorControllerBean y SentenceTranslator. Por ahora, debe comenzar a familiarizarse con el aspecto de Web Bean, por lo tanto sólo destacaremos aquí las partes más interesantes.

Tanto SentenceParser como TextTranslator son beans dependientes, y TextTranslator utiliza inicialización de constructor:

public class TextTranslator { 

   private SentenceParser sentenceParser; 
   private Translator sentenceTranslator; 
   
   @Initializer
   TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator) 
   { 
      this.sentenceParser = sentenceParser; 
      this.sentenceTranslator = sentenceTranslator;

TextTranslator es un bean con estado (con una interfaz local de negocios), donde lo mágico sucede - claro está, que no desarrollaramos un traductor completo, ¡pero le dimos una buena luz!

Por último, hay un controlador orientado a UI que recoge el texto desde el usuario y lo envía al traductor. Esta es una petición en ámbito, llamada bean con estado de sesión que inyecta el traductor.

@Stateful

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

El bean también tiene capturadores y configuradores para todos los campos en la página.

Como este es un bean de sesión con estado, tenemos que tener un método de eliminación:

   @Remove

   public void remove()
   {
      
   }

El administrador de Web Beans llamará al método de eliminación cuando el bean sea destruido, en este caso al final de la petición.

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.

Necesitamos ayuda en todas las áreas - corrección de errores, escritura de nuevas funciones, escritura de ejemplos y traducción de esta guía de referencia.