Concludiamo con questo articolo l‘argomento dell‘integrazione tra Wicket e altri framework Java. Dopo aver trattato Spring e poi iBatis, in questo numero ci concentriamo in particolare su Hibernate, senza dimenticare quanto visto in precedenza.
Nei due articoli precedenti è stata descritta l’integrazione di Wicket con Spring attraverso tre tipi di strategie di approccio e l’implementazione dello strato di persistenza tramite iBatis. In questa ultima parte spiegheremo invece come integrare Wicket, Spring e, per quanto riguarda la persistenza, Hibernate.
Come per la prima parte, la versione di Wicket a cui faremo riferimento è la 1.4-m3. A partire dalla versione 1.4 Wicket richiede necessariamente Java 1.5 o release successiva.
Hibernate
Hibernate [5] è una piattaforma middleware Java Open Source per la persistenza dei dati su database relazionali, distribuita con licenza LGPL. Fornisce quindi un servizio di ORM (Object-Relational Mapping). Tramite Hibernate è quindi possibile eseguire un mapping (via XML o Java Annotations) tra le classi che compongono il modello applicativo (ad oggetti) e le tabelle del database (modello relazionale). Questo nuovo strato software si fa carico di tutto ciò che riguarda la persistenza (salvataggio e recupero delle istanze delle classi su database), generando automaticamente gli statement SQL necessari, svincolando gli sviluppatori da tali compiti. L’applicazione rimane portabile sui database relazionali di qualsiasi vendor. Hibernate impone un unico vincolo: effettuerà la persistenza delle istanze di classi a patto che queste siano POJO (Plain Old Java Object) con un costruttore senza argomenti.
In figura 1 viene mostrato lo schema logico di una applicazione che fa uso di Hibernate per la persistenza.
Figura 1 – Il funzionamento di un’applicazione con Hibernate.
In figura 2 viene mostrata l’architettura di Hibernate.
Figura 2 – Architettura della piattaforma Hibernate.
Con il passare del tempo Hibernate ha perso la sua natura monolitica e attualmente è composto da un core più una serie di altri componenti aggiuntivi. Ne esiste anche un porting per .NET.
Per maggiori approfondimenti consiglio la lettura dell’ottimo articolo di Leonardo Casini pubblicato in passato su MokaBbyte [6] e successivamente del libro “Java Persistence with Hibernate” di Christian Bauer & Gavin King [7].
La release di Hibernate a cui faremo riferimento in questo articolo è la 3.3.1 GA. Richiede Java 1.5 o release superiore.
Integrazione di Hibernate nell’applicazione Comics Convention Registration
Ricorreremo anche in questo articolo all’ausilio dell’applicazione di esempio implementata per gli altri di questa serie.
Nei due precedenti articoli abbiamo trasformato l’applicazione iniziale in una applicazione Spring based, descrivendo tre possibili strategie di approccio e abbiamo implementato lo strato di persistenza tramite il pattern DAO [4] e il framework iBatis. In questo articolo andremo a sostituire iBatis con Hibernate.
Il database applicativo è costituito dall’unica tabella participant, in cui vengono salvati tutti i partecipanti registrati alla convention. Nel modello dell’applicazione abbiamo una classe Java, Participant.java, che corrisponde a tale tabella. Dobbiamo scrivere il mapping file XML in cui viene fatta l’associazione tra la classe e la corrispondente tabella. Il contenuto del file Participant.hbm.xml (salvato al livello della classe Java corrispondente) è:
"-//Hibernate/Hibernate Mapping DTD//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <class name="it.wicketexamples3.model.Participant" table="participant"> <id name="id" column="id"> <property name="firstName" column="firstName"/> <property name="secondName" column="secondName"/> <property name="country" column="country"/> <property name="talk" column="talk"/> <property name="pictureName" column="pictureName"/>
Nel tag viene dichiarata l’associazione tra la classe (indicata con il full package name) e la tabella. Tramite il tag definiamo la chiave della tabella. Con il tag indichiamo il tipo di algoritmo utilizzato per la generazione automatica del valore del campo (il valore native indica che la generazione viene fatta secondo la strategy prevista del vendor del database applicativo). Tramite il tag dichiariamo invece l’associazione tra gli attributi della classe e i campi della tabella.
Abbiamo già precedentemente disegnato l’interfaccia della classe DAO relativa ai Participant:
public interface ParticipantDAO { public List selectAllParticipants(); public Participant selectParticipantById(String participantId); public void insertParticipant(Participant insertParticipant); public void deleteParticipant(String participantId); public void updateParticipant(Participant participantToUpdate); }
In essa abbiamo dichiarato i metodi relativi al CRUD (Create, Read, Update and Delete) dei Participant e il metodo per recuperarli tutti. Passando a Hibernate, tale interfaccia non cambierà: quindi in tutti i punti dell’applicazione in cui è necessario un accesso ai dati, e sono presenti invocazioni ai metodi del DAO, tutto rimane come prima. Non è necessario un refactoring delle classi. C’è solo da implementare l’interfaccia in questione facendo riferimento ad Hibernate.
Dopo aver importato nel progetto le librerie di Hibernate necessarie, bisogna cambiare l’ancestor della classe it.wicketexamples3.dao.ParticipantDAO: non sarà più SqlMapClientSupport, ma org.springframework.orm.hibernate3.support.HibernateDaoSupport :
public class ParticipantDAOImpl extends HibernateDaoSupport implements ParticipantDAO { public List selectAllParticipants() { return getHibernateTemplate().find("from Participant"); } public Participant selectParticipantById(String participantId) { return (Participant)getHibernateTemplate().get(Participant.class, participantId); } public void insertParticipant(Participant insertParticipant) { getHibernateTemplate().saveOrUpdate(insertParticipant); } public void deleteParticipant(String participantId) { } public void updateParticipant(Participant participantToUpdate) { getHibernateTemplate().saveOrUpdate(participantToUpdate); } }
In ogni metodo viene semplicemente invocato il metodo apposito dell’istanza di org.springframework.orm.hibernate3.HibernateTemplate del DAO.
Resta infine solamente da adeguare lo Spring context file applicativo. La definizione del DataSource rimane la stessa del caso di iBatis. Vanno invece registrati due nuovi bean, sessionFactory e transactionManager:
it/wicketexamples3/model/Participant.hbm.xml org.hibernate.dialect.MySQL5Dialect update class="org.springframework.orm.hibernate3.HibernateTransactionManager">
Il primo è la factory che Spring mette a disposizione per la gestione delle sessioni di Hibernate. È qui che vanno registrati i mapping files e le altre proprietà di Hibernate, tra le quali il SQL dialect da utilizzare (nel nostro caso, MySQL5Dialect). Il secondo è il TransactionManager utilizzato. Non c’è bisogno di scrivere a parte un file di configurazione di Hibernate (hibernate.cfg.xml) poiche’ passiamo attraverso i template di Spring. Nella registrazione del bean participantDao basta valorizzare come property solo sessionFactory:
Non cambia nulla per quanto riguarda il bean wicketApplication:
Non è necessaria alcuna altra modifica al codice applicativo.
Il project Eclipse con tutti i sorgenti completi dell’applicazione di esempio (wicket-6_esempi.zip) può essere scaricato come allegato dal menu in alto a sinistra. Le librerie necessarie per la compilazione e/o il runtime sono le seguenti:
- commons-dbcp.jar (runtime)
- commons-pool.jar (runtime)
- hibernate3.jar (compilazione)
- antlr-2.7.6.jar (runtime)
- commons-collections-3.1.jar (runtime)
- commons-logging-1.0.4.jar (runtime)
- dom4j-1.6.1.jar (runtime)
- javassist-3.4.GA.jar (runtime)
- jta-1.1.jar (runtime)
- mysql-connector-java-5.1.7-bin.jar (runtime)
- slf4j-api-1.5.0.jar (compilazione)
- slf4j-jcl-1.5.0.jar (runtime)
- spring.jar (compilazione)
- wicket-1.4-m3.jar (compilazione)
- wicket-extensions-1.4-m3.jar (compilazione)
- wicket-spring-1.4-m3.jar (compilazione)
Conclusioni
Come abbiamo visto, anche questa integrazione non è risultata complessa. Quindi la scelta di Wicket per lo sviluppo del Presentation Layer di una Java web application, oltre a mettere a disposizione i vantaggi insiti nel framework stesso, non pregiudica affatto la scelta degli strumenti con cui vengono implementati gli altri layer.
Riferimenti
[1] Karthik Gurumurthy, “Pro Wicket”, Apress, 2006
[2] Sito ufficiale di Wicket presso Apache
[3] Dhananjay Nene, “A beginners guide to Dependency Injection”, The ServerSide.com
[4] S. Rossini – L. Dozio, “Il pattern Data Access Object”, MokaByte 62, Aprile 2002
https://www.mokabyte.it/2002/04/pattern-dao.htm
[5] Sito ufficiale di Hibernate
[6] L. Casini, “Oggetti persistenti con Hibernate”, MokaByte 101, Novembre 2005
https://www.mokabyte.it/cms/article.run?articleId=ESY-ID9-SF1-9B4_7f000001_7470813_791de7f5
[7] Christian Bauer, Gavin King, “Java Persistence with Hibernate”, Manning, 2007