Come spesso accade con le nuove versioni, gli aggiornamenti importanti, le novità tecnologiche, anche Java EE 7, ormai rilasciato da poco più di un anno, non ha trovato immediatamente una larghissima adozione: ne ha rallentato l’impiego un certo spirito di ‘conservazione’ e pigrizia, ma soprattutto il fatto che alcune tecnologie a supporto non fossero ancora pronte. Con il rilascio di Application Server pienamente compatibili, però, è il caso di usare Java EE 7 e di scoprire le sue nuove potenzialità.
Introduzione
L’aggiornamento alla versione 7 della piattaforma Java Enterprise ha spento da poco la sua prima candelina. Molti di voi forse già lo usano, ma molti altri non hanno intrapreso la migrazione fin da subito, aspettando che gli Application Server che implementano la nuova specifica fossero maturi. A giugno, Red Hat ha rilasciato la versione 8.1 di WildFly (vale a dire JBoss AS 8): è giunto quindi il momento di sfruttare le nuove potenzialità di Java EE7.
Lo stack EE aggiornato
La piattaforma Java Enterprise non è altro che un agglomerato di specifiche: la versione 7 è composta da aggiornamenti di precedenti specifiche a cui si aggiunge qualcosa di nuovo.
Figura 1 – Lo stack della piattaforma EE: in arancione le nuove aggiunte.
Non sarebbe possibile (e nemmeno leggibile) elencare tutte le novità: l’idea è quindi quella di raccontare quelle più interessanti e di dare dei riferimenti per ulteriori approfondimenti. Diciamo che con questa “lista della spesa” possiamo farci un’idea di cosa Java EE 7 ci porta di nuovo, così da poter approfondire quello che serve.
Partiamo quindi dalle specifiche più popolari, ossi quelle che servono per implementare una applicazione web.
Java Server Faces (JSF) 2.2
Su J-Development [1] è disponibile un esauriente post con tutte le novità (che non son poche). Le principali sono:
- supporto a HTML 5;
- multi-templating (chiamata Resource Library Contracts): permette di definire più template Facelets per una stessa pagina;
- Faces Flows: standardizzazione di Spring Web Flow e ADF Task Flows che richiede la dipendenza da CDI;
- viste stateless: si può scegliere di non salvare lo stato delle viste sul server così da guadagnare in scalabilità; va da sè che uno scope come viewScoped non può essere usato!
- file upload (basato sul multipart di Servlet 3.0): finalmente è possibile fare upload di file senza ricorrere a framework esterni o servlet;
- injection in tutti gli artefatti JSF: purtroppo fino adesso non era possibile eseguire l’injection CDI nei validatori e nei convertitori, cosa invece possibile nel backing bean;
- supporto del view scope anche per i bean CDI: JSF si sta buttando sempre di più tra le braccia di CDI (il che credo faccia piacere a tutti); all’uscita di JSF 2, avevamo affrontato l’argomento su CoseNonJaviste [2].
- Window Id: aggiunta la possibilità di aprire due finestre nello stesso browser per lo stesso utente.
Perchè usare da subito JSF 2.2 quindi? Tra le ragioni più interessanti a mio avviso c’è il supporto ad HTML 5. Possiamo finalmente limitare l’uso dei tag JSF allo stretto necessario (e in particolare il malefico panelGrid!) e usare tag HTML, con qualche accorgimento, come se fossero tag JSF.
Enterprise Java Bean (EJB) 3.2
La nuova minor release della specifica EJB ci porta a casa non molte novità: sembra che questa versione sia servita più a consolidare quanto già ottenuto negli ultimi rilasci e soprattutto a ripulire “rami morti” dello sviluppo passato, ossia una serie di funzionalità legate a EJB 2.1 probabilmente non più usate e rese “opzionali” dalla nuova specifica. Le migliorie introdotte sono:
- la possiblità di usare EJB asincroni e EJB Timers non persistenti in EJB Lite [3];
- la possiblità di non “passivare” i session bean stateful (prima esistevano soluzioni “vendor”, ossia legate all’implementazione di EJB);
- possibilità di conoscere tutti i timer attivi in un modulo EJB.
Java Persistence API (JPA) 2.1
JPA 2.1 standardizza qualche soluzione finora disponibile solo da certe implementazioni particolari di persistenza, e ognuna a modo suo, il che ne limitava la portabilità. Con questa nuova versione si è proprio voluto allargare allo standard una serie di funzionalità che esistevano ma che non erano disponibili in tutte le implementazioni. In particolare mi riferisco a:
- conversione dei tipi tra oggetti e database: quelli che in Hibernate si chiamano UserType e in Eclipselink Converter; sembra che una soluzione simile a quest’ultima sia entrata nella specifica. Da adesso è possibile quindi implementare un AttributeConverter, molto simile ai converter del JSF, tra l’altro, per avere una soluzione portabile;
- la generazione automatica del database (DDL) adesso è standard;
- adesso è possibile costruire chiamate a stored procedures direttamente dall’entiry manager;
- è possibile specificare sull’entità quali colonne avranno indici aggiuntivi (utile per la DDL);
- direttamente da JPQL è possibile chiamare funzioni specifiche del database, cosa che finora si poteva fare solo tramite Criteria API;
- CDI scende su JPA! Con questa nuova integrazione possiamo usare dei bean CDI per implementare gli entity listener (pre–destroy, post–persist, …) portando la logica dei listener fuori dall’entità; prima non era il massimo del design…
- aggiunta la possibilità di creare named query dinamicamente a runtime.
Perchè quindi JPA 2.1? Tra le novità credo che non potremo più fare a meno degli entity listener gestiti da CDI e, inoltre, la chiamata a stored procedure finalmente è standard: in ambienti legacy/enterprise è difficile prescinderne…
Context and Dependency Injection (CDI) 1.1
CDI ha rivoluzionato e semplificato la gestione delle Dependency Injection (DI) in Java Enterprise. Fino a Java EE 5, i contesti EJB e JSF erano gerarchicamente separati: il secondo poteva accedere al primo. L’unica possibilità di avere DI lato “business” era grazie agli EJB. Con CDI la situazione si è notevolmente alleggerita: in Java EE 6, CDI si propone come unico e solo contesto di DI, anche se non ancora perfetto, sia lato JSF (mancava il view scoped) che lato EJB (leggi integrazione con JTA).
Come già si può intuire dai paragrafi precedenti, CDI pervade tutto lo stack Java EE 7 integrandone e semplificandone diverse parti, da JSF a JPA, da JMS alla Bean Validation!
Tra le numerose piccole migliorie possiamo elencare:
- @AroundConstruct: per intercettare il costruttore delle classi;
- controllo più fine sul meccanismo di discovery dei bean CDI: occhio quindi all’attributo bean-discovery-mode del bean.xml…
- EventMetadata: per conoscere il contesto di partenza di un evento osservato;
- tramite la nuova classe Unmanaged è possibile ottenere istanze di oggetti CDI in contesti non gestiti da CDI (in Java EE 6 piuttosto frequente…).
Maggiori dettagli su tutte le novità possono essere trovate sul blog “In Relation To…” [4].
BeanValidation (BV) 1.1
Questa specifica nasce per validare il modello dei dati in modo dichiarativo, in particolare, per poterlo rendere coerente con i vincoli del modello relazionale che il modello a oggetti mappa. Nel tempo la BV è stata integrata con JSF, in modo da validare gli input utente, e con la nuova versione 1.1 si integra perfettamente con i servizi REST, permettendo di validare i dati in input a qualsiasi metodo Java. Questo è possibile principalmente grazie alle seguenti novità:
- è possibile applicare la bean validation anche agli argomenti di un metodo (chiamata method validation), sia di input che di output;
- l’injection di CDI è disponibile anche nei validatori personalizzati;
- si integra nativamente con JAX-RS;
- è possibile usare l’expression language nei messaggi di errore.
Perchè quindi dovrei usare la BV 1.1? Principalmente per l’integrazione con JAX-RS e la validazione dei dati in ingresso. Per maggiori approfondimenti su questo aspetto vi rimando a un mio post su CoseNonJaviste [5].
JAX-RS 2.0
Le grandi novità della specifica stanno sul lato client: JAX-RS 1.0 definiva infatti l’architettura standard dei servizi RESTful in Java Enterprise lato server, ma mancava completamente di definire il client. Sia Jersey che RESTEasy (due implementazioni di JAX-RS) definivano il loro modo di creare i client. L’idea dell’interfaccia fluida di Jersey Client (stile builder pattern) è stata quella vincente e adesso è diventata parte della specifica JAX-RS 2.0. Chi era abituato all’implementazione di Jersey 1.x non avrà grossi problemi ad abituarsi alla versione 2, anche se non è retrocompatibile. Perchè però dovremmo passare a JAX-RS 2?
- per il supporto alla gestione delle chiamate asincrone, sia lato client client che lato server; il concetto di asincrono lato server è mutuato dal contesto asincrono di Servlet 3.0 (quindi non è veramente asincrono per l’utente finale, ma è utile solo per una questione di risorse), mentre quello lato client è veramente asincrono e la risposta è gestita tramite callback o oggetti Future;
- è stato standardizzato il sistema di marshall/unmarshall del body delle richieste HTTP tramite interceptors (ReaderInterceptor/WriterInterceptor), dandoci più controllo in fase di serializzazione/deserializzazione del payload HTTP.
Batch 1.0
L’architettura dei batch è stata definita e implementata qualche anno fa da Spring con il progetto Spring Batch. Secondo questa architettura, un batch è composto da un certo numero di passi (step), ognuno dei quali è fatto da lettura (ItemReader), elaborazione (ItemProcessor) e scrittura (ItemWriter) di un dato da una sorgente a una destinazione. Qualche riassunto concettuale lo trovate in un mio post [6] su CoseNonJaviste.
Java EE riprende l’architettura proposta da Spring e standardizza gran parte di questi concetti in una nuova specifica. Sicuramente da prendere in considerazione per i prossimi vostri batch all’interno della piattaforma Java EE: facile schedularli con EJB Timer [7], no?
Concurrency 1.0
È altamente sconsigliato gestire manualmente thread in una applicazione Java EE. L’application server ha un suo gestore di thread e “uscire dal seminato” può provocare situazioni inattese. L’esecuzione di operazioni su un thread diverso da quello della richiesta principale in Java EE è sempre stato un po’ difficile: con gli EJB asincroni sicuramente si è risolta gran parte dei problemi, ma per avere il controllo dei thread e mettere le mani al thread pool dell’application server bisognava ricorrere a soluzioni proprietarie, inficiando la portabilità.
Java EE 7, con la nuova specifica Concurrency Utilities 1.0 ci permette di staccare tutti i thread che vogliamo a patto di usare il ManagedExecutorService o la ManagedThreadFactory. Ovviamente, come l’ExecutorService di Java SE, sono disponibili tutti i metodi per schedulare e gestire i thread creati in modo managed. Maggiori approfondimenti sono disponibili sul sito Oracle [8].
WebSocket 1.0
E finalmente quello che tutti attendevamo con impazienza: comunicazione inversa dal server al client! Quando si sviluppano applicazioni che richiedono grande interattività con gli eventi che vengono dal server, il modello richiesta/risposta dell’HTTP non è sufficiente. Con le websocket è possibile instaurare un canale bidirezionale tramite client e server: occhio che, una volta aperto il canale, la comunicazione non è HTTP!
I dati che si possono scambiare sono infatti in formato binario o testuale (JSON, XML…), e la specifica ci semplifica le cose aiutandoci a convertire i messaggi in POJO tramite opportuni encoder e decoder. La documentazione Oracle [9] è un buon punto di partenza per prendere confidenza con questa nuova piattaforma.
Conclusioni
Come già accennato, l’intento di questo articolo non è una trattazione completa degli argomenti, cosa che sarebbe impossibile, ma è di presentare un “indice” delle novità, per far venire un po’ di “appetito” verso questi nuovi strumenti. I link forniti nei riferimenti possono fungere da primo approfondimento.
Per concludere, non c’è un singolo motivo per passare a Java EE 7: essendo una costellazione di specifiche, sicuramente c’è qualcosa che fa al caso vostro, magari perchè adesso risolve in maniera semplice un problema che negli anni passati avevamo dovuto affrontare con soluzioni personalizzate o, peggio, arrangiate. Usiamo allora con fiducia le novità di Java EE 7 e non reinventiamoci la ruota presumendo che la nostra verrà più tonda!
Riferimenti
[1] Arjan Tijms, “What’s new in JSF 2.2?”, J-Development
http://jdevelopment.nl/jsf-22/
[2] Andrea Como, “CDI ViewScoped: abbandoniamo i backing bean JSF!”, CoseNonJaviste
[3] Giovanni Puliti, “EJB 3.1: l’evoluzione della specie – III parte: Risorse per l’alleggerimento”, MokaByte 137, febbraio 2009
https://www.mokabyte.it/cms/article.run?articleId=2XH-R7K-JOT-C13_7f000001_10911033_616a20f6
[4] Pete Muir, “CDI 1.1 available :-)”, In Relation To…
http://in.relation.to/Bloggers/CDI11Available
[5] Andrea Como, “BeanValidation e JAX-RS”, CoseNonJaviste
http://www.cosenonjaviste.it/beanvalidation-e-jax-rs/
[6] Andrea Como, “Primi passi con Spring Batch”, CoseNonJaviste
http://www.cosenonjaviste.it/primi-passi-con-spring-batch/
[7] Andrea Como, “EJB 3.1 Timer Services: cosa bolle di nuovo in pentola?”, CoseNonJaviste
http://www.cosenonjaviste.it/ejb-3-1-timer-servicesècosa-bolle-di-nuovo-in-pentola/
[8] Concurrency Utilities for Java EE
http://docs.oracle.com/javaee/7/tutorial/doc/concurrency-utilities.htm
[9] Java API for WebSocket