Creare un backoffice in 5 minuti con OpenXava parte I

Da un po’ di tempo si parla di framework che permettono di creare interfacce grafiche partendo dal proprio modello dei dati o da una sua rappresentazione. Il termine scaffolding indica proprio questo: generare codice (che di solito permette di eseguire operazioni CRUD su entità) con un tool automatico invece di scriverlo a mano. Lo scaffolding è stato reso popolare da Ruby On Rails ed è attualmente presente in molti framework in diversi linguaggi di programmazione, per esempio è supportato da Django in Python, CakePhp e Symfony in php e Grails in Groovy. Ovviamente esiste qualcosa anche in Java: un esempio è Spring Roo e un altro che vedremo in dettaglio in questo articolo è OpenXava.

Il sito ufficiale di OpenXava definisce questo progetto un AJAX Java Framework for Rapid Development of Enterprise Applications. L’enfasi è soprattutto su due parole: AJAX e Rapid. Infatti le interfacce web create con OpenXava sfruttano tecnologie AJAX dietro le quinte per avere una interfaccia veloce da utilizzare. Il perché venga usato anche il termine Rapid lo vedremo nel corso di questo post, buona lettura!

View generate runtime Vs code generation

L’idea dietro OpenXava non è quella della creazione di codice ma bensì quella di generare runtime delle interfacce web partendo dal modello dei dati. Ovviamente ci sono sia dei pro che dei contro nei due approcci, sicuramente uno dei vantaggi dell’utilizzo di OpenXava è quello che il codice da manutenere è veramente poco. Inoltre è un approccio molto pulito e non ci sono i classici problemi del codice generato: la domanda se modifico il codice generato e poi lo rigenero perdo le mie modifiche? con OpenXava non la sentirete mai.

Fino ad adesso abbiamo parlato di modello dei dati, ma da cosa parte OpenXava per creare le pagine web? La risposta a questa domanda è secondo me uno dei punti di forza di OpenXava: tutto parte dalle entità JPA annotate. Questo approccio permette di ridurre lo sviluppo di una web app (o almeno delle più semplici) nella progettazione delle entity JPA. Partendo da questo è possibile generare il database (anche OpenXava mette a disposizione un build di ant per fare questo) e autogenerare le pagine web. Semplice, no?

OpenXava in azione

Ma che interfacce web crea OpenXava? Un esempio vale più di mille parole, vediamolo all’opera con una anagrafica dei comuni italiani.

Lista comuni con OpenXava

Se osservate per bene l’immagine potete riconoscere le innumerevoli feature presenti in questa lista:

  • paginazione dei dati
  • combo per numero di righe per pagina
  • numero totale di righe
  • ordinamento dei dati cliccando sull’header di una colonna
  • filtro dei dati con scelta dell’operatore di filtro
  • resize delle colonne
  • ordinamento e scelta delle colonne
  • selezione multipla per applicazione azioni (per esempio la cancellazione) su più righe
  • esportazione dei dati in excel e pdf

Non sono feature innovative ma personalmente per averle in una pagina ho sempre dovuto sudare parecchio!

Cliccando su una riga si passa al dettaglio corrispondente, nel caso di una città per esempio abbiamo questa pagina web:

Dettaglio di una città con OpenXava

Anche in questo caso le feature sono quelle che un utente si aspetta: i dati sono raggruppati (anche usando tab), c’è la validazione e la possibilità di scegliere le entità collegate usando una ricerca (per esempio in questo caso la provincia di un comune). Potete vedere altri esempi di utilizzo nella pagina delle demo del sito ufficiale. Ma basta chiacchiere, è arrivato il momento di vedere un po’ di codice nei dettagli!

Creazione di un progetto in Eclipse con OpenXava

La prima cosa da fare per iniziare a usare OpenXava è scaricare lo zip contenente tutto il necessario per utilizzare questo framework, basta andare sul sito ufficiale openxava.org e cliccare sul pulsante per effettuare il download. Una volta scompattato lo zip vediamo che contiene anche uno workspace di Eclipse con i sorgenti del framework e un tomcat già configurato. Apriamo quindi Eclipse scegliendo la directory del workspace appena scaricato. Occhio alle impostazioni del workspace, in particolare il build automatico è disabilitato, riabilitatelo subito e non fate come qualcuno che se n’è accorto dopo un’ora di comportamenti inspiegabili! 🙂

Il workspace contiene i sorgenti di tutto il framework e alcuni esempi. Per creare un nuovo progetto basta creare un progetto Java standard dentro Eclipse, non è necessario creare niente di particolare. Una volta creato il progetto può essere trasformato in un progetto OpenXava grazie a un build di ant, contenuto in un file chiamato CreateNewProject.xml dentro il progetto OpenXavaTemplate. Per sicurezza facciamo un refresh del progetto dentro Eclipse e siamo pronti per partire!

Il punto di partenza: tre entity JPA

Come già detto tutto inizia da alcune entity JPA, creiamo quelle del nostro esempio. Con molta fantasia creiamo tre entity che sono presenti in molte web app italiane: Region, District e City. La prima e più semplice da creare è Region:

@Entity
@Table(name = "regions")
public class Region implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@Column(nullable = false)
	@Required
	private String name;

	//getter e setter...
}

Possiamo notare che abbiamo usato solo annotation JPA standard, le classiche Entity, Table e Column e un altro paio di annotation per creare una primary key autoincrementante e rendere alcuni campi obbligatori. La seconda entità che vediamo è quella che modella le province:

@Entity
@Table(name = "districts")
public class District implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@Column(nullable = false)
	@Required
	private String name;

	@ManyToOne(fetch = FetchType.LAZY)
	@JoinColumn(name = "region_id")
	@Required
	private Region region;

	@Column(length = 2, nullable = false)
	@Required
	private String code;

	private Integer lat;

	private Integer lon;

	//getter e setter...
}

Anche qui niente di particolare, da notare la relazione ManyToOne verso le regioni. L’ultima entità da vedere è quella delle città:

@Entity
@Table(name = "cities")
public class City implements Serializable {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private int id;

	@Column(length = 5, nullable = false)
	@Required
	private String cap;

	@Column(nullable = false)
	@Required
	private String name;

	@ManyToOne(fetch = FetchType.LAZY, optional = false)
	@JoinColumn(name = "district_id")
	@Required
	private District district;

	private Integer lat;

	private Integer lon;

	private boolean capital;

	//getter e setter...
}

Vi risparmio le discussioni sul fatto che il cap sia una stringa e non un intero, lo so che da buoni informatici almeno una volta avete avuto questo dubbio! 🙂

Abbiamo tutte le entità, dobbiamo censirle nel file persistence.xml del nostro progetto. Creiamo due persistence unit, una da usare nel Tomcat che punta a un datasource e l’altra nei test e nella generazione delle tabelle con la configurazione per accedere al db. In questo esempio ho usato un db MySql ma ovviamente potete usare un qualunque db supportato da JPA (quindi praticamente tutti i db relazionali):

<persistence-unit name="default">
	<provider>org.hibernate.ejb.HibernatePersistence</provider>
	<non-jta-data-source>java:comp/env/jdbc/cnjDS</non-jta-data-source>
	<class>it.cosenonjaviste.openxava.City</class>
	<class>it.cosenonjaviste.openxava.District</class>
	<class>it.cosenonjaviste.openxava.Region</class>
	<properties>
		<property name="hibernate.dialect" 
			value="org.hibernate.dialect.MySQL5InnoDBDialect" />
		<property name="hibernate.show_sql" 
			value="true" />
	</properties>
</persistence-unit>

<persistence-unit name="junit">
	<provider>org.hibernate.ejb.HibernatePersistence</provider>
	<class>it.cosenonjaviste.openxava.City</class>
	<class>it.cosenonjaviste.openxava.District</class>
	<class>it.cosenonjaviste.openxava.Region</class>
	<properties>
		<property name="hibernate.connection.driver_class" 
			value="com.mysql.jdbc.Driver" />
		<property name="hibernate.dialect" 
			value="org.hibernate.dialect.MySQL5InnoDBDialect" />
		<property name="hibernate.connection.username" 
			value="..." />
		<property name="hibernate.connection.password" 
			value="..." />
		<property name="hibernate.connection.url"
			value="jdbc:mysql://127.0.0.1/cnj?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8" />
		<property name="hibernate.show_sql" 
			value="true" />
	</properties>
</persistence-unit>

Nella view Servers di Eclipse aggiungiamo un server Tomcat, possiamo usare quello presente nello zip che abbiamo scaricato dal sito di OpenXava. A questo punto possiamo creare il datasource: basta modificare il file context.xml, lo trovate nel progetto Servers creato in automatico da Eclipse quando si aggiunge un server Tomcat. Ecco il frammento di xml da aggiungere:

<Resource name="jdbc/cnjDS" auth="Container" type="javax.sql.DataSource"
   maxActive="20" maxIdle="5" maxWait="10000"
   username="..." password="..." driverClassName="com.mysql.jdbc.Driver"
   url="jdbc:mysql://127.0.0.1/cnj?autoReconnect=true&amp;useUnicode=true&amp;characterEncoding=utf8"/>

Per far funzionare il tutto abbiamo bisogno del driver del nostro db, aggiungiamolo nella cartella lib del Tomcat.

Generazione delle tabelle su database

Una delle feature più affascinanti di JPA è la generazione delle tabelle su database partendo dalle entity (non fate questo discorso al vostro dba, potrebbe non essere molto d’accordo! 🙂 ). Per generare le tabelle possiamo usare il target updateSchema, lo possiamo trovare nel build di ant all’interno del nostro progetto (per la precisione è un build di ant generato da un build di ant!). Su MySql è necessario creare a mano lo schema in quanto lo schema è presente nell’url della connessione al db e deve quindi esistere già prima di iniziare. Anche in questo caso il driver per accedere al db deve essere presente nel classpath, va aggiungo a mano nelle preferenze di Eclipse relative al classpath di ant.

Ed eccoci al risultato finale…

Fino ad adesso abbiamo creato tre entity JPA standard e abbiamo configurato tutto a dovere. In pratica abbiamo creato la parte di model in un framework MVC, sviluppando una web app Java adesso sarebbe il momento di creare tutta la parte di view. Ma invece di scrivere altro codice facciamo partire il Tomcat e apriamo un browser all’url http://localhost:8080/CoseNonJaviste/modules/City dove CoseNonJaviste è il nome del progetto che abbiamo creato e City è il nome dell’entità che vogliamo editare. Quello che possiamo vedere nel browser è questo:

Lista con OpenXava

Lista con OpenXava senza customizzazioni

Cliccando su una riga della tabella possiamo editare il dettaglio:

Dettaglio con OpenXava

Dettaglio con OpenXava senza customizzazioni

OpenXava ha generato queste pagine web interamente runtime leggendo le annotation standard JPA. Ovviamente non può leggere nel pensiero dello sviluppatore e quindi la grafica è standard e sono mostrati tutti i campi dell’entità. Nel dettaglio (e non nella lista) sono mostrati anche i campi delle entità collegate lette usando sempre le relazioni JPA. E’ presente anche un minimo di validazione sui campi obbligatori e sulla lunghezza dei campi.

Conclusioni

Per adesso non abbiamo scritto una singola riga di codice legata ad OpenXava, tutto il codice scritto può essere tranquillamente usato anche in web app create con altri framework. Per arrivare all’esempio visto all’inizio di questo post c’è ancora un po’ (in realtà poco) da lavorare, ma questo sarà l’argomento del prossimo post.

OpenXava contiene molte feature che ancora non abbiamo visto (per esempio editor e validazione può essere customizzata ed è possibile inserire azioni aggiuntive). Se Volete approfondire l’argomento potete dare un’occhiata alla documentazione ufficiale o al libro Rapid Java Web Development scritto direttamente da Javier Paniza, il project leader di OpenXava.

Fabio Collini

Software Architect con esperienza su piattaforma J2EE e attualmente focalizzato principalmente in progetti di sviluppo di applicazioni Android. Attualmente sono in Nana Bianca dove mi occupo dello sviluppo di alcune app Android. Coautore della seconda edizione di Android Programmazione Avanzata e docente di corsi di sviluppo su piattaforma Android. Follow me on Twitter - LinkedIn profile

  • Anonimo

    Ho fatto alcuni lavori con questo framework e posso confermare che è davvero eccellente. Consiglio, a tutti quelli che vogliono usarlo, l’acquisto del libro indicato perchè oltre a supportare lo sviluppatore, spiega con esempi pratici tutto quello che il framework offre. Comunque Javier risponde abbastanza velocemente anche sul forum. Personalmente ho integrato OpenXava anche con SQLite, un pò più complicato perchè non supportato nativamente da Hibernate, ma funziona tutto alla grande.

    • Grazie per il commento! Io (per adesso!) non l’ho usato su software seri ma giocandoci un po’ sembra fatto veramente bene. Una pecca secondo me è la documentazione (sia quella ufficiale che domande/risposte a giro) che è poca rispetto ad altri framework, fa piacere sentire che il supporto è comunque buono.

      • Anonimo

        Grazie a voi per questo bel sito, l’ho scoperto da poco ma i vostri articoli sono molto ben fatti e infatti, ho in programma di leggermi tutti gli articoli che avete scritto :).
        Riguardo a OpenXava, se devi realizzare un CRUD credo sia tra i framework migliori che ci sono in giro. Per la documentazione, prendi il libro, ti aiuterà tantissimo. Comunque anche sui siti del progetto c’è moltissimo materiale, magari non organizzato alla perfezione, ma c’è. Dopotutto da quello che sono riuscito finora a capire, ad OpenXava non so se ci lavorano altre persone oltre a Javier.
        Ciao e continuate così.

  • Antonio Musarra

    Ciao e complimenti per la spiegazione chiara.
    Ho utilizzato spesso tool del genere che aiutano parecchio soprattutto quando devi fare le cose per ieri. Pongo una domand: come la mettiamo quando il nostro data sources é rappresentato servizi (soap o rest che siano)?

    Mi piace questo blog, vi farò riferimento nel mio.

    A presto,
    Antonio.

    • Fabio Collini

      Ciao, che io sappia openxava deve partire da un db e non da servizi rest. Sinceramente non so se esiste un progetto che genera l’interfaccia grafica partendo da servizi rest, se trovi qualcosa di interessante faccelo sapere!
      Ciao e grazie per i complimenti

  • PP

    Buon tutorial introduttivo, ma… ho qualche dubbio su OpenXava…

    Che tu sappia:

    1) OpenXava è facilmente “customizzabile”?
    i.e.: nell’esempio, se volessi recuperare lat e long da google con una “mio” servizio, aggiungendo un “button”… si può fare?

    2) Ho visto che per configurare i ruoli, ecc. c’è XavaPro… ma costa un sacco e nn è quindi più open… non esiste un’alternativa gratuita o meno dispendiosa?

    Grazie, ciao.

    • Fabio Collini

      Ciao,
      eccoti qualche risposta:
      1) si, è possibile customizzare molti aspetti della ui fra cui anche i button da mettere nella form
      2) altri tool simili a openxava e totalmente free io non li ho trovati, se trovi qualcosa facci sapere!
      Ciao, Fabio