|
È molto più bello sapere qualcosa di tutto, che tutto di
una cosa
|
|
| Home Page |
|
| Articoli |
|
| News |
|
| Forum |
|
| Classi |
|
|
|
|
|
Seam, Getting started
By
Marco immediato
3 novembre 2006
Valutazione Acquisita:
40
|
 |
|
Jboss Seam è un potente application framework per costruire applicazione Web 2.0 di prossima generazione, unificando e integrando tecnologie SOA a Javascript Asincrono e XML (AJAX), Java Server Faces (JSF), Enterprise Java Bean (EJB3) Java Portlets, Business Process Management (BPM) e workflow”.
La promessa è grande e l'idea è affascinante.
Ho provato questo framework scrivendo una piccola applicazione che simulasse un car show room che facesse uso di JSF, AJAX, EJB3 e Hibernate 3.
|
|
|
Getting started
|
top
|
|
Prima di tutto bisogna installare l'application server (ovviamente Jboss!!). Io per questo tutorial ho usato la versione jems1.2.0 scaricabile a questo link: http://sourceforge.net/project/showfiles.php?group_id=22866&package_id=193295 Installare Jboss con il profilo EJB 3.0 specificato.  Fig 1- Installazione Jboss Cosa troviamo dentro Seam? Abbiamo i sorgenti nella directory src, le librerie in lib, ma c’è anche una directory examples dove troviamo molti esempi e quasi tutti fanno uso di EJB3.  La struttura è la seguente: - nella root è collocato il build.xml.
- nella directory view troveremo le nostre jsp e html.
- in src mettiamo il nostro codice sorgente sotto il package it.vetrinaauto.seam
- In resources avremo una serie di file di configurazione (che analizzeremmo più in dettaglio in seguito)
|
|
Back-end
|
top
|
Passiamo ora ad implementare la parte di reperimento dati e logica di business della nostra applicazione.
La prima classe che scriviamo è Auto.java che reperirà i dati relativi all'auto di cui vogliamo mostrare le informazioni:
@Entity @Name("auto") @Scope(EVENT) @Table(name="auto") public class Auto implements Serializable { static final long serialVersionUID = 1l;
private Integer id; private String nome; private String marca; private String colore;
@Id public Integer getId() { return id; } public void setId(Integer id) { this.id = id; } @NotNull @Length(max=100) public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; }
@NotNull public String getMarca() { return marca; } ... ... ...
Questa classe è un semplice Java Bean supportato da annotations, che indicano che la classe reperirà i dati dalla tabella “auto” e che il nome e la marca sono sempre valorizzati, ecc..
Analizziamola nel dettaglio:
@Entity annotation indica che la classe Auto è un entity bean
Un componente Seam ha bisogno di un component name specificato dall'annotation @Name. Questo nome deve essere univoco in un'applicazione Seam. Quando JSF chiede a Seam di risolvere una variabile di contesto con il nome che è lo stesso del componente Seam e quella variabile è null, Seam si occuperà di istanziare quel componente.
Le annotations @NotNull e @Length fanno parte del framework Hibernate Validator. Seam integra Hibernate Validator per la validazione dei dati anche se non si sta usando Hibernat per la gestione della persistenza.
L'annotation EJB standard @Id indica la chiave primaria dell'entity bean.
Molte applicazioni Seam application usano session beans come action listeners JSF.
Ora implementiamo una classe che utilizza il bean appena scritto e alcuni componenti Seam:
AutoManagerBean.java
@Stateful @Scope(SESSION) @Name("autoManager") public class AutoManagerBean implements Serializable, AutoManager { static final long serialVersionUID = 1l; @Logger private Log log; @DataModel private List<Auto> autoList;
@DataModelSelection @Out(required=false) private Auto auto;
@PersistenceContext(type=EXTENDED) private EntityManager em; private int actualPage = 0; private int pageSize = 5; private int maxPages = 0;
@Factory("autoList") public void findAuto() { log.info("...recupero le automobili..."); autoList = em.createQuery( "from Auto a order by a.id" ).getResultList(); log.info("auto recuperate: "+autoList.size()); maxPages = autoList.size() / pageSize ; // calcolo la nuova sottolista per la paginazione autoList = autoList.subList( actualPage*pageSize, Math.min( autoList.size(), (actualPage+1)*pageSize ) ); }
public void nextPage() { if (actualPage<maxPages) actualPage++; this.findAuto(); }
public void prevPage() { if(actualPage>0) actualPage--; this.findAuto(); }
@Remove @Destroy public void destroy() {}
}
Dalle annotations notiamo che questa classe è un session stateful.
L'annotation EJB standard @PersistenceContext è usato per “iniettare” l'EJB3 entity manager. Con type=EXTENDED si indica che il risultato della query avrà lo stesso ciclo di vita del bean, quindi ogni metodo invocato successivamente sul bean stateful non provocherà un'esplicita chiamata all'EntityManager
L'annotation @DataModel espone un attibuto di tipo java.util.List alla pagina JSF come istanza di javax.faces.model.DataModel. Ciò permette di usare la lista in JSF nel tag <h:dataTable> . In questo caso, DataModel è reso disponibile in una variabile di contesto con nome autoList.
La prima volta che navighiamo la pagina JSP, non ci sarà nessun valore per autoList. L'annotation @Factory comunica a Seam di creare un'istanza di AutoManagerBean ed invocare findAuto() per inizializzare la variabile.
Tutti gli stateful session bean di Seam DEVONO avere un metodo con l'annotation @Remove @Destroy per assicurare che Seam rimuoverà il bean quando il suo ciclo di vita finirà.
L’ interfaccia di AutoManagerBean.java sarà:
@Local public interface AutoManager { public void findAuto(); public void destroy(); public void nextPage(); public void prevPage();
}
L'applicazione utilizza anche un altro Stateless ed Entity Bean per reperire i dati di dettaglio delle automobili, per la loro implementazione, molto simile ai bean appena descritti, si rimanda al codice a corredo di questo tutorial.
|
|
Front-end
|
top
|
|
Andiamo ad analizzare la pagina JSP: <h:dataTable var="auto" id="listaAuto" value="#{autoList}" width="400"> <h:column> <f:facet name="header"> <h:outputText value="ID"/> </f:facet> <s:link value="#{auto.id}" id="idAuto" onmouseover="javascript:dettagliAuto(this.id)" /> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Nome"/> </f:facet> <h:outputText value="#{auto.nome}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Marca"/> </f:facet> <h:outputText value="#{auto.marca}"/> </h:column> <h:column> <f:facet name="header"> <h:outputText value="Colore"/> </f:facet> <h:outputText value="#{auto.colore}"/> </h:column> </h:dataTable>
La prima volta che navighiamo la pagina auto.jsp, si cercherà di risolvere la variabile autoList. Siccome il contesto non è ancora inizializzato, Seam chiamerà il metodo factory findAuto() e il risultato sarà renderizzato tramite il tag <h:dataTable>.
|
|
Configurazione
|
top
|
|
In un'applicazione Seam ci sono diversi file di configurazione, sono tutti di facile configurazione e non hanno bisogno di un continuo aggiornamento man mano che si sviluppa l'applicazione: WEB-INF/components.xml <components> <component name="org.jboss.seam.core.init"> <property name="myFacesLifecycleBug">@myFacesLifecycleBug@</property> <property name="jndiPattern">@jndiPattern@</property> </component> <component class="org.jboss.seam.core.Ejb" installed="@embeddedEjb@"/> </components>
Questa configurazione indica a Seam dove reperire gli EJB sull'albero JNDI.
WEB-INF/web.xml
<!-- Seam --> <listener> <listener-class>org.jboss.seam.servlet.SeamListener</listener-class> </listener> <!-- MyFaces --> <listener> <listener-class>org.apache.myfaces.webapp.StartupServletContextListener</listener-class> </listener> <context-param> <param-name>javax.faces.STATE_SAVING_METHOD</param-name> <param-value>client</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> <!-- Faces Servlet Mapping --> <servlet-mapping> <servlet-name>Faces Servlet</servlet-name> <url-pattern>*.seam</url-pattern> </servlet-mapping>
Questo web.xml configura Seam e MyFaces , la configurazione è molto simile in parecchie applicazioni Seam.
WEB-INF/face-config.xml
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE faces-config PUBLIC "-//Sun Microsystems, Inc.//DTD JavaServer Faces Config 1.0//EN" "http://java.sun.com/dtd/web-facesconfig_1_0.dtd"> <faces-config> <!-- Phase listener needed for all Seam applications --> <lifecycle> <phase-listener>org.jboss.seam.jsf.SeamPhaseListener</phase-listener> </lifecycle> </faces-config>
Il faces-config.xml integra Seam con JSF. Da notare che non c'è bisogno di nessuna dichiarazione di managed bean JSF. I managed beans utilizzati sono componenti Seam.
META-INF/ejb-jar.xml
<ejb-jar> <assembly-descriptor> <interceptor-binding> <ejb-name>*</ejb-name> <interceptor-class>org.jboss.seam.ejb.SeamInterceptor</interceptor-class> </interceptor-binding> </assembly-descriptor> </ejb-jar>
L’ ejb-jar.xml integra Seam con EJB3, inserendo SeamInterceptor in tutti i session bean.
META-INF/persistence.xml
<persistence> <persistence-unit name="messageDatabase"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <jta-data-source>java:/DefaultDS</jta-data-source> <properties> <property name="hibernate.hbm2ddl.auto" value="create-drop"/> </properties> </persistence-unit> </persistence>
persistence.xml indica all'EJB persistence provider dove trovare il Datasource. In questo caso si usa HibernateProviderIn con una proprietà che sta ad indicare che le tabelle associate agli entity dell'applicazione saranno create e droppate al momento dello startup, operazione che risulta molto utile in fase di testing.
|
|
Database
|
top
|
|
Fino ad ora abbiamo visto la parte di back-end con i bean, la parte di front-end con la JSP e la confiurazione di un'applicazione Seam, ma dove risiedono i dati? L'applicazione fa uso di HSQL database presente in JBoss AS.
Fig 2 - Lightweight 100% Java SQL Database Engine In pratica allo startup vengono create le tabelle mappate dagli Entity presenti nell'applicazione e vengono inseriti i dati tramite import.sql cioè uno script presente in resources, in modo che le tabelle vengono anche valorizzate.
|
|
AJAX
|
top
|
|
Alla nostra applicazione vogliamo integrare anche AJAX. Quando, per la prima volta, si visualizza la nostra JSP, vengono mostrate in una tabella tutte le automobili presenti nello show room con le relative informazioni minime. Nel momento in cui vogliamo informazioni più dettagliate, e visualizzarle nella nostra JSP, abbiamo bisogno di effettuare una query sulla tabella di dettaglioAuto .
Tutto questo senza effettuare il refresh della pagina! AJAX ci aiuta ad assolvere questo problema perchè effettua una richiesta asincrona al server. Alla chiamata di una funzione di callback, si renderizzano le informazioni ricevute dal server nella pagina tramite JavaScript. Seam facilita l'uso di AJAX grazie alla sua integrazione con il Remoting framework.
La sua configurazione è semplicissima, basta inserire poche righe nel web.xml e nella pagina JSP che utilizza AJAX e siamo pronti ad utilizzarlo. Bisogna inserire questo mappaggio nel file web.xml:
<servlet> <servlet-name>Seam Remoting</servlet-name> <servlet-class>org.jboss.seam.remoting.SeamRemotingServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>Seam Remoting</servlet-name> <url-pattern>/seam/remoting/*</url-pattern> </servlet-mapping>
Inoltre è necessario importare i due seguenti script nella pagina JSP:
<script type="text/javascript" src="seam/remoting/resource/remote.js"> </script>
<script type="text/javascript" src="seam/remoting/interface.js?dettagliAutoManager"> </script>
Il primo script contiene tutto il codice che abilita le funzionalità del framework Remoting. Il secondo script contiene gli stub e la definizione dei tipi dei componenti che si desidera chiamare. Questo script è automaticamente generato ed include la definizione dei tipi di tutte le classi di cui si possono chiamare i metodi remoti. Il nome dello script riflette il nome del componente che si desidera richiamare. Infatti nello script importato nell’esempio, richiameremo un metodo del componente dal nome “dettagliAutoManager” A questo punto analizziamo il codice AJAX che invoca il metodo remoto, riceve i dati dal componente Seam e renderizza il risultato nella JSP tramite JavaScript, il tutto in modo asincrono:
function dettagliAuto(idObj) { idAuto = document.getElementById(idObj).innerHTML; Seam.Component.getInstance("dettagliAutoManager").findDettagliAutoById(idAuto, dettagliAutoMessageCallback); } function dettagliAutoMessageCallback(message) { var ctl = getObject("displayDettaglioAuto"); var ctl2 = getObject("displayDettaglioAuto2");
ctl.innerHTML = "<b>CILINDRATA </b>" + message.getCilindrata() + "<br/><b>ALIMENTAZIONE </b>" + message.getAlimentazione() + "<br/><b>PORTE </b>" + message.getNumeroPorte() + "<br/><br/><b><a href='" + message.getSite() + "' width='100%' height='100%'>"+message.getSite()+"</a></b>";
ctl.scrollTop = ctl.scrollHeight; ctl2.innerHTML = "<img src='" + message.getUrlFoto() + "'/>"; ctl2.scrollTop = ctl.scrollHeight; }
Nella JSP, il metodo metodo dettagliAuto(idObj) viene richiamato così:
<s:link value="#{auto.id}" id="idAuto" onmouseover="javascript:dettagliAuto(this.id)" />
Il punto in cui viene richiamato il metodo remoto é:
Seam.Component.getInstance("dettagliAutoManager").findDettagliAutoById(idAuto, dettagliAutoMessageCallback);
In questa riga di condice viene passato come parametro sia l'id di cui ha bisogno per effettuare la query, sia il nome della funzione di callback che deve essere invocata alla risposta del server.
Quando viene invocata la callback, il reperimento dei dati dal messaggio di ritorno avviene come se si stesse lavorando col vero oggetto di ritorno del metodo remoto.
|
|
Build e deploy
|
top
|
|
Adesso non ci resta che effettuare il build e il deploy della nostra applicazione. Per prima cosa odbiamo configurare il file build.properties presente nella directory di installazione di Seam e valorizzare il campo jboss.home con il path di installazione di Jboss, ad esempio “C:\\Programmi\\jboss-4.0.4.GA”. Il secondo passo è configurare il file build.properties presente nella directory dell'applicazione e valorizzare il campo seam.home con il path di installazione di Seam, ad esempio D:\\jboss_projects\\jboss-seam-1.0.1.GA Ora si può finalmente effettuare il build e il deploy dell'applicazione avviando una shell DOS e posizionarsi sulla root dell'applicazione e lanciare il comando ant. Fig 3- shell DOS dell' applicazione Avviare Jboss e richiamare l'applicazione all'URL http://localhost:8080/seam-auto: Passiamo col puntatore del mouse sopra uno degli id delle auto in modo da richiamare la funzione AJAX:
|
|
Conclusioni
|
top
|
Seam promette molto, promette di voler diventare il framework di riferimento per lo sviluppo delle applicazioni Web 2.0. Di sicuro la potenzialità c'è, un prodotto tutto da scoprire e con enorme sensazione di rapida crescita. La facilità di configurazione e la semplice implementazione dei suoi componenti affascinano molto, così come la sua integrazione con IDE di sviluppo come Eclipse oppure NetBeans.
Seam sembra l’ideale per le piccole applicazioni, tutto da testare il suo comportamento con le grandi applicazioni.
|
|
|

Eccetto dove diversamente specificato, i contenuti di questo sito sono rilasciati sotto licenza Creative Commons
|
|
|