SeamFramework.orgCommunity Documentation
La Web Beans Reference Implementation viene sviluppata all'indirizzo the Seam project. Si può scaricare l'ultima release di Web Beans dalla pagina di download.
La Web Beans RI (Reference Implementation) viene distribuita con due applicazioni deployabili d'esempio, webbeans-numberguess
, un esempio in formato war, che contiene solo bean semplici, e webbeans-translator
, un esempio in formato ear, che contiene bean enterprise. Per eseguire gli esempi occorre fare le seguenti cose:
l'ultima release di Web Beans RI,
JBoss AS 5.0.0.GA, and
Ant 1.7.0.
Attualmente, la RI di Web Beans può essere eseguita solo sull'Application Server 5 di JBoss. Occorre scaricare JBoss AS 5.0.0.GA da jboss.org, e scompattarlo. Per esempio:
$ cd /Applications $ unzip ~/jboss-5.0.0.GA.zip
Scaricare Web Beans RI da seamframework.org, e scompattarla. Per esempio
$ cd ~/ $ unzip ~/webbeans-$VERSION.zip
Quindi, occorre indicare a Web Beans dove è stato installato JBoss. Modificate il file jboss-as/build.properties
e valorizzate la proprietà jboss.home
. Per esempio:
jboss.home=/Applications/jboss-5.0.0.GA
Poiché Web Beans è un software nuovo, occorre aggiornare JBoss AS per poter eseguire la RI di Web Beans. Versioni future di JBoss AS includeranno questi update, e questa operazione non sarà necessaria.
Attualmente, sono necessari due aggiornamenti. In primo luogo, occorre aggiungere un nuovo deployer, webbeans.deployer
. Esso aggiunge JBoss AS il supporto per gli archivi Web Bean, e permette alla RI di Web Beans RI di interrogare il container EJB3 e scoprire quali EJB sono presenti nell'applicazione. In secondo luogo, è necessario un aggiornamento di JBoss EJB3.
Per installare gli aggiornamenti, occorre avere installato Ant 1.7.0, e avere valorizzato la variabile d'ambiente ANT_HOME
. Per esempio:
$ unzip apache-ant-1.7.0.zip $ export ANT_HOME=~/apache-ant-1.7.0
Quindi, è possibile installare gli aggiornamenti. Lo script di aggiornamento userà Maven per scaricare automaticamente Web Beans e EJB3.
$ cd webbeans-$VERSION/jboss-as $ ant update
Ora, siete pronti a fare il deploy del primo esempio!
Gli script di build degli esempio offrono una quantità di target, cioè:
ant restart
- fa il deploy dell'esempio in formato esploso
ant explode
- aggiorna un esempio in formato esploso, senza riavviare il deploy
ant deploy
- fa il deploy dell'esempio in formato jar compresso
ant undeploy
- rimuove l'esempio dal server
ant clean
- ripulisce l'esempio
Per fare il deploy dell'esempio Indovina Numero:
$ cd examples/numberguess ant deploy
Start JBoss AS:
$ /Application/jboss-5.0.0.GA/bin/run.sh
If you use Windows, use the run.bat
script.
Attendete che l'applicazione sia installata, e godetevi ore di divertimento all'indirizzo http://localhost:8080/webbeans-numberguess!
La RI di Web Beans include un secondo semplice esempio che tradurrà i vostri testi in Latino. L'esempio Indovina Numero è in formato war, e usa soltanto bean semplici; l'esempio col traduttore è in formato ear, e include dei bean enterprise, assemblati in un modulo EJB. Per provarlo:
$ cd examples/translator ant deploy
Attendete che l'applicazione sia installata, e visitate l'indirizzo http://localhost:8080/webbeans-translator!
Nell'applicazione Indovina Numero avete a disposizione 10 tentativi per indovinare un numero tra 1 e 100. Dopo ciascun tentativo, siete informati se siete stati troppo alti o troppo bassi.
L'esempio Indovina Numero comprende un certo numero di Web Bean, file di configurazione e pagine JSF, assemblati in un war. Iniziamo dai file di configurazione.
Tutti i file di configurazione di questo esempio si trovano in WEB-INF/
, che è situato in WebContent
nell'albero dei sorgenti. Innanzitutto, c'è faces-config.xml
, in cui JSF viene informata di usare 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
>
Vi è un file vuoto web-beans.xml
, che identifica l'applicazione come applicazione Web Beans.
Infine c'è web.xml
:
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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"> <display-name >Web Beans Numbergues example</display-name> <!-- JSF --><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>
<context-param> <param-name >javax.faces.DEFAULT_SUFFIX</param-name> <param-v
alue >.xhtml</param-value> </context-param> <session-config> <session-timeout >10</session-timeout> </session-config> </web-app >
![]() | Enable and load the JSF servlet |
![]() | Configure requests to |
![]() | Tell JSF that we will be giving our source files (facelets) an extension of |
![]() | Configure a session timeout of 10 minutes |
Whilst this demo is a JSF demo, you can use the Web Beans RI with any Servlet based web framework.
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:composition template="template.xhtml"> <ui:define name="content"> <h1 >Guess a number...</h1> <h:form
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
> I'm thinking of a number between #{game.smallest} and #{game.biggest}. You have #{game.remainingGuesses} guesses. </div> <div> Y
our guess: <h:inputText id="inputGuess" value="#{game.guess}" required="true" size="3"
disabled="#{game.number eq game.guess}"> <f:validateLongRange maximum="#{game.biggest}" minimum="#{game.smallest}"/> <
/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 >
![]() | Facelets is a templating language for JSF, here we are wrapping our page in a template which defines the header. |
![]() | There are a number of messages which can be sent to the user, "Higher!", "Lower!" and "Correct!" |
![]() | 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. |
![]() | This input field is bound to a Web Bean, using the value expression. |
![]() | 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. |
![]() | 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. |
L'esempio consiste di 4 classi, delle quali le prime due sono tipi di binding. Innanzitutto, c'è il tipo di binding @Random
, usato per iniettare un numero casuale:
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface Random {}
C'è anche il tipo di binding @MaxNumber
, usato per iniettare il numero massimo iniettatabile:
@Target( { TYPE, METHOD, PARAMETER, FIELD })
@Retention(RUNTIME)
@Documented
@BindingType
public @interface MaxNumber {}
Alla classe Generator
è affidata la generazione del numero casuale, per mezzo di un metodo produttore. Inoltre essa espone il massimo numero possibile attraverso un metodo produttore:
@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;
}
}
E' possibile notare che Generator
ha scope applicazione; quindi non si ottiene un diverso numero casuale ogni volta.
Il Web Bean finale nell'applicazione è Game
avente scope di sessione.
Si noti anche che è stata usata l'annotazione @Named
, in modo che sia possibile usare il bean in espressioni EL presenti nelle pagine JSF. Infine, si è utilizzata l'iniezione del costruttore per inizializzare il gioco con un numero casuale. E naturalmente, è necessario dire al giocatore se ha vinto, informazione di feedback che viene fornita con un 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
>(){});
}
}
L'esempio Traduttore prende le frasi che vengono inserite e le traduce in latino.
L'esempio Traduttore è assemblato in un ear, e contiene EJB. Di conseguenza, la sua struttura è più complessa di quella dell'esempio Indovina Numero.
EJB 3.1 and Java EE 6 permettono di assemblare gli EJB in un war, cosa che rende questa struttura molto più semplice!
Innanzitutto, diamo un'occhiata all'aggregatore ear, che è situato nel modulo webbeans-translator-ear
. Maven genera automaticamente il file 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
>
Qua viene impostato il context path, in modo da avere un url gradevole (http://localhost:8080/webbeans-translator).
Se non si sta usando Maven per generare questi file, sarebbe necessario avere il file 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
>
Quindi, esaminiamo il war. Proprio come nell'esempio Indovina Numero, abbiamo un faces-config.xml
(per abilitare Facelets) e un web.xml
(per abilitare JSF) in WebContent/WEB-INF
.
Più interessante è il facelet usato per tradurre il testo. Proprio come nell'esempio Indovina Numero c'è un template, che circoscrive la form (qui omessa per brevità):
<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
>
L'utente può inserire del testo nell'area di testo sulla sinistra e premere il pulsante di traduzione per vedere il risultato sulla destra.
Infine, si esamini il modulo ejb, webbeans-translator-ejb
. In src/main/resources/META-INF
si trova un file vuoto web-beans.xml
, usato per marcare l'archivio come contenente Web Beans.
Abbiamo lasciato per ultimo il boccone più prelibato, il codice! Il progetto ha due bean semplici, SentenceParser
e TextTranslator
e due bean enterprise, TranslatorControllerBean
e SentenceTranslator
. Dovreste ormai essere piuttosto familiari all'aspetto di un Web Bean, così ci limiteremo a evidenziare le parti più interessanti.
Sia SentenceParser
che TextTranslator
sono bean dependenti, e TextTranslator
usa l'inizializzazione via costruttore:
public class TextTranslator {
private SentenceParser sentenceParser;
private Translator sentenceTranslator;
@Initializer
TextTranslator(SentenceParser sentenceParser, Translator sentenceTranslator)
{
this.sentenceParser = sentenceParser;
this.sentenceTranslator = sentenceTranslator;
TextTranslator
è un bean stateless (con un'interfaccia business locale), dove avviene la magia - naturalmente, non potevamo sviluppare un traduttore completo, ma gli abbiamo dato un buon avvio!
Infine, vi è un controller orientato all'UI, che raccoglie il testo dall'utente, e lo invia al traduttore. Questo è un bean stateful di sessione, dotato di nome, con scope richiesta, in cui viene iniettato il traduttore.
@Stateful
@RequestScoped
@Named("translator")
public class TranslatorControllerBean implements TranslatorController
{
@Current TextTranslator translator;
Il bean possiede pure dei metodi getter e setter per tutti i campi della pagina.
Poichè si tratta di un bean stateful di sessione, è necessario un metodo di rimozione (remove method):
@Remove
public void remove()
{
}
Il manager Web Beans chiamerà il metodo di rimozione quando il bean verrà distrutto; in questo caso al termine della richiesta.
Ciò conclude il nostro breve tour degli esempi della RI di Web Beans. Per saperne di più, o per trovare ulteriore aiuto, per favore visitate http://www.seamframework.org/WebBeans/Development.
Abbiamo bisogno di aiuto in tutte le aree - soluzione dei bug, scrittura di nuove caratteristiche ed esempi e traduzione di questa guida.