venerdì 30 maggio 2008

Prêt-à-portlét

Il progetto su cui sto lavorando adesso prevede un portale B2B da cui un fornitore può offrire dei microservizi ad altre, fornendogli i relativi moduli per la configurazione e l'inserimento dei dati necessari al servizio stesso.
Dopo un giro tra le alternative ho optato per Liferay, un prodotto che conoscevo ma che non immaginavo fosse arrivato al livello a cui è.
Probabilmente è anche sovrabbondante per gli scopi del progetto, però supporta lo standard JSR-168, che consente di scrivere portlet indipendenti dal portale in cui vengono pubblicati.
Per chiarire meglio, un portale JSR-168 consente di ospitare nelle proprie pagine delle portlet, ovvero delle porzioni di pagina Web autonome che implementano un servizio (news, quotazioni di borsa, ma anche un blog, un wiki o un forum).
Un esempio di portlet è questo.

Scelta la tecnologia e il portale, mi mancava ancora il framework per implementare le portlet. Liferay ha un proprio approccio, ma lo trovo pesante e di certo non orientato a produrre portlet indipendenti dal portale.

Così ho scelto Spring MVC Portlet. Non conoscevo Spring MVC, ma conosco Spring. Spring è Il Framework. E' l'infrastruttura più leggera ed elastica che abbia mai provato. Migliora in maniera drastica la produttività e la qualità del codice pur rimanendo leggero e discreto. E' come Alfred per Bruce Wayne :).

Spring MVC Portlet è stata l'ennesima conferma. Dopo una configurazione iniziale non banale, ma logica, scrivere portlet è stata un'esperienza gratificante.
Spring MVC Portlet è organizzato come Spring MVC e ne riutilizza delle parti:

L'immagine è tratta dalla documentazione di Spring MVC, ma per grandi linee descrive bene anche Spring MVC Portlet.
Il gestore di tutto è il Front Controller (chiamato DispatcherPortlet nel framework) che riceve le richieste e le smista ai Controller o alle View.
Le regole di smistamento sono gestite in maniera limpida attraverso la configurazione XML.
Uno dei problemi è stato interagire con Liferay. E' vero che esiste lo standard, ma tanti servizi, come la gestione degli utenti, la fase di autenticazione, ecc sono lasciate ai vendor. Così ho seguito lo Spring-pensiero: ho implementato una interfaccia PortalSupport con le varie richieste di servizio al portale, e poi una sua implementazione LiferaySupport, che è definita nel context della portlet:


<bean id="portalSupport" class="example.theportlet.portal.liferay.LiferayPortalSupport">
</bean>


In questo modo, una classe che deve interagire con il portale dichiara una proprietà di tipo PortalSupport:


private PortalSupport portalSupport;

public PortalSupport getPortalSupport() {
return portalSupport;
}

public void setPortalSupport(PortalSupport portalSupport) {
this.portalSupport = portalSupport;
}


e dal context posso iniettare la particolare implementazione dove serve:


<bean id="baseControllerTemplate" abstract="true">
<property name="portalSupport" ref="portalSupport"/>
</bean>


Semplice, elegante, chiaro. Che è anche l'essenza di Spring.

Infine mi sono occupato della persistenza. Nei tipi di servizi da realizzare, il dominio dei dati è molto semplice, non più di 5-6 entità, con le classiche associazioni una a molti, uno a uno, ecc.
Non mi andava di usare Hibernate, francamente troppo complesso per un problema del genere, ma neanche SQL puro con tutti i suoi problemi di dialetti, script di DDL ecc.
Così, cercando, ho trovato Beankeeper. Signori, che ne dite di una libreria a cui basta dire:


store = new Store("org.hsqldb.jdbcDriver","jdbc:hsqldb:file:testdb");

Person person = new Person();
person.setFirstName(firstName);
person.setLastName(lastName);
store.save(person);


per salvare su DB il bean Person? Nota bene, non c'è codice nascosto né operazioni a priori. Si prende un DB vuoto, si prende il primo bean che passa, lo si passa a BeanKeeper e lui crea le tabelle analizzando il bean e lo salva. Punto. Stop.
Supporta automaticamente relazioni, ereditarietà, caricamento lazy, e ha un semplice linguaggio OQL.

Non è tutto rose e fiori, ma ne scriverò in un post a parte.

Nessun commento: