Comincia con questo numero una serie su Wicket, un Java framework open source a componenti per applicazioni web. In questo primo articolo verranno illustrate l‘architettura e le principali features del framework e verrà mostrato un primo semplice esempio pratico di applicazione.
Wicket è un Java framework a componenti che consente di realizzare applicazioni web sfruttando appieno le potenzialità dei Plain Old Java Object (POJO), di HTML, di AJAX, di Spring e dell’IoC (Inversion of Control) pattern, di Hibernate o di iBatis. Wicket gestisce automaticamente lo stato degli oggetti a livello dei componenti: questo significa che non è necessario impazzire con la gestione dedicata degli HTTPSession objects.
Wicket è open source e rilasciato con licenza Apache. È scaricabile dal sito ufficiale http://wicket.apache.org. La versione a cui faremo riferimento in questa serie di articoli è la 1.4-m2. A partire dalla versione 1.4 Wicket richiede Java 1.5. o release successiva.
Architettura del framework
Wicket porta il modello di programmazione a eventi di Swing nell’ambito dello sviluppo di applicazioni web. Il framework consente una netta separazione fra i ruoli di page designer HTML e sviluppatore Java poichè supporta l’utilizzo di template HTML puri che possono essere lavorati con un qualsiasi editor HTML WYSIWYG. Infatti il framework non richiede l’aggiunta di propri tag all’HTML: ai tag viene aggiunto solamente l’attributo wicket:id per i componenti che devono essere trattati dalla parte Java.
Wicket si contrappone alla natura stateless del linguaggio HTML mettendo componenti stateful a disposizione di chi sviluppa. Inoltre consente di realizzare rich client application nel pieno rispetto delle regole della programmazione object-oriented. Il framework è suddiviso in più librerie:
- wicket-x.x.jar: il core del framework;
- wicket-extensions-x.x.jar: le principali estensioni del framework;
- wicket-datetime-x.x.jar: utilities per la manipolazione di date;
- wicket-ioc-x.x.jar: implementazione del pattern Inversion of Control;
- wicket-spring-x.x.jar: per l’integrazione con Spring (http://www.springframework.org/);
- wicket-velocity-x.x.jar: per l’integrazione con Velocity (http://velocity.apache.org/);
- wicket-guice-x.x.jar: per l’integrazione con Google Guice Ioc container (http://code.google.com/p/google-guice/);
- wicket-auth-roles-x.x.jar: per la gestione dell’autenticazione e delle autorizzazioni nelle pagine web;
- wicket-jmx-x.x.jar: interfaccia verso JMX;
- wicket-objectssizeof-agent-x.x.jar: agent per object size measurements in caso di instrumentazione.
Le figure 1 e 2 mostrano due esempi di componenti facilmente implementabili con Wicket.
Figura 1 – Form che utilizza il field per l’upload multiplo di file
Figura 2 – Tree Table
La prima applicazione di esempio
Vediamo adesso come implementare una semplice applicazione web Wicket-based per capire come è fatta la sua struttura tipica. Le considerazioni fatte in questo paragrafo sono generiche: valgono per tutte le applicazioni web Wicket-based, anche per quelle più complesse. La prima cosa da fare è registrare e mappare la Wicket Servlet nel web deployment descriptor (web.xml):
WicketExamplesApplication org.apache.wicket.protocol.http.WicketServlet applicationClassName it.wicketexamples1.WicketExamplesApplication 1 WicketExamplesApplication /*
L’unico parametro che passiamo alla WicketServlet in fase di inizializzazione è il nome della WebApplication class della nostra applicazione. La WebApplication in Wicket è la main class che esegue il kick off dell’applicazione. Deve estendere la classe
org.apache.wicket.protocol.http.WebApplication
In essa va registrata la site map dell’applicazione. È l’unico punto in cui ciò viene fatto. Nella WebApplication class va indicato inoltre qual è la start page.
public class WicketExamplesApplication extends WebApplication { public WicketExamplesApplication() { } @Override protected void init() { super.init(); //Disable Ajax Debug getDebugSettings().setAjaxDebugModeEnabled(false); // Register main page mountBookmarkablePage("/main", MainPage.class); // Register comment page mountBookmarkablePage("/comment", CommentPage.class); } /** * Marks home page. * */ public Class getHomePage() { return MainPage.class; } }
In questo esempio abbiamo registrato due web page (MainPage e CommentPage) e indicato come home page, fra le due, la MainPage. Entrambe le pagine, come tutte le Wicket Page, devono estendere la classe
org.apache.wicket.markup.html.WebPage
Ad ogni Java WebPage deve corrispondere un template HTML avente lo stesso nome della classe che deve essere presente nello stesso path della classe all’interno del classpath applicativo (vedi figura 3).
Figura 3 – Classpath dell’applicazione di esempio
Ci deve essere una corrispondenza 1:1 tra i widget HTML aventi l’attributo wicket:id e i componenti della WebPage. Il valore di wicket:id è univoco. Il codice del template HTML della Main page è il seguente:
Message goes here Add a comment
I widget che hanno l’attributo wicket:id sono due, lo span message e l’anchor commentLink. Quindi la WebPage corrispondente avrà due component, uno di tipo
org.apache.wicket.markup.html.basic.Label
e l’altro di tipo
org.apache.wicket.markup.html.link.Link:
public class MainPage extends WebPage { public MainPage() { add(new Label("message", "This is my today's post!")); add(new Link("commentLink") { public void onClick() { setResponsePage(CommentPage.class); } }); } }
A runtime, durante la fase di render di una pagina, Wicket invoca il metodo WebPage.render(). La WebPage identifica il template corrispondente e inizia il parse dell’HTML. Per ogni tag che possiede l’attributo wicket:id viene ricercato nella WebPage il Wicket component corrispondente (avente lo stesso wicket:id value) e il rendering viene delegato a tale component. L’istanza di WebPage viene memorizzata in un internal store di tipo org.apache.wicket.PageMap. Wicket mantiene una PageMap per ogni sessione utente. La Main page della nostra applicazione, accessibile da browser invocando l’URL
http://localhost:/
avrà l’aspetto mostrato in figura 4.
Figura 4 – Main Page
Dal link presente nella pagina è possibile accedere alla CommentPage (figura 5):
Figura 5 – Comment Page
Il codice HTML di questa ulteriore pagina è il seguente:
1/1/2004
Comment text goes here.
1/2/2004
More comment text here.
Mentre il codice della corrispondente classe Java è:
public class CommentPage extends WebPage { private List commentList = new ArrayList(); private ListView commentListView; public CommentPage() { add(new CommentForm("commentForm")); add(commentListView = new ListView("comments", commentList) { public void populateItem(final ListItem listItem) { final Comment comment = (Comment)listItem.getModelObject(); listItem.add(new Label("date", comment.getDate().toString())); listItem.add(new MultiLineLabel("text", comment.getText())); } }); } public class CommentForm extends Form { private final Comment comment = new Comment(); public CommentForm(final String componentName) { super(componentName); add(new TextArea("text", new PropertyModel(comment, "text"))); } public final void onSubmit() { final Comment newComment = new Comment(); newComment.setText(comment.getText()); commentList.add(0, newComment); commentListView.modelChanged(); comment.setText(""); } } }
Il codice dell’applicazione di esempio può essere scaricato dal menu in alto a sinistra (WicketExamples1). L’archivio non comprende le librerie necessarie per la compilazione e/o il runtime. Le dipendenze sono le seguenti:
- wicket-1.4-m2.jar (compilazione e runtime)
- slf4j-api-1.5.0.jar (runtime)
- slf4j-jcl-1.5.0.jar (runtime)
Conclusioni
In questo primo articolo è stata data a grandi linee una descrizione del framework. Nel prossimo articolo ne vedremo più in dettaglio componenti e caratteristiche più avanzate.
Riferimenti
[1] Karthik Gurumurthy, “Pro Wicket”, Apress, 2006
[2] Sito ufficiale di Wicket presso Apache
http://wicket.apache.org/