1. Creazione di una REST API in Liferay portal
Introduzione
In questo periodo ho letto alcuni post molto interessanti sulla creazione di REST API nel portale Liferay. I
servizi si possono creare essenzialmente in due modi: utilizzando il supporto built-in di Liferay, o utilizzando
framework come Spring o Jersey. In questo tutorial espongo come integrare Jersey in Liferay in modo
flessibile e relativamente veloce. Il software che ho utilizzato è il seguente:
• Apache Maven 3.2.3
• JDK 1.7
• liferay-portal-6.2-ce-ga4
• Jersey 2.22.1
• SoapUI 5.0.0
• Windows 7
Prerequisiti
Quando si utilizza un framework esterno a Liferay, occorre scrivere un po’ di codice per l’integrazione col
sistema di sicurezza di Liferay. In sintesi occorre autenticare l’utente e inizializzare il sistema di permessi
così come fa il filtro com.liferay.portal.servlet.filters.secure.SecureFilter. Ho creato la
classe com.sample.rest.liferay.AuthenticationFilter basandomi su tale filtro.
Tipicamente, in caso di successo, i servizi rest restituiscono i seguenti stati HTTP:
• 200 - OK per i metodi GET
• 201 - Created per i metodi POST
• 204 - No Content per i metodi PUT e DELETE
Per aderire a questa convenzione, ho creato l’annotation Status e la classe StatusFilter che
sostituisce lo stato HTTP con quello contenuto in Status.
AuthenticationFilter, Status e StatusFilter si trovano nel progetto com-sample-rest
disponibile al seguente indirizzo: http://www.webalice.it/nmastrapasqua/sources/com-sample-rest.zip.
Eseguiamo il download, e dopo aver decompresso l’archivio, digitiamo il comando mvn install.
Creazione del progetto liferay-jersey-portlet
Nella directory c:progettirest creiamo il progetto maven in modo interattivo:
mvn archetype:generate
quando richiesto, digitiamo il filtro liferay:portlet
2. scegliamo 1, che corrisponde a liferay
Subito dopo, ci viene richiesto di scegliere la versione del modello; nel mio caso
versione 6.2.0-ga1.
Infine impostiamo i parametri groupId
Lavoriamo ora nella directory c:progetti
Figura 1 - Generazione del progetto
liferay-portlet-archetype
Subito dopo, ci viene richiesto di scegliere la versione del modello; nel mio caso
groupId, artifactId, version e confermiamo con
Figura 2 - Scelta della versione
progettirestliferay-jersey-portlet
23 che corrisponde alla
e confermiamo con Y.
3. Modifica del file pom.xml
Aggiungiamo la sezione profile per definire il nostro ambiente di lavoro e le dipendenze da jersey
Jackson e com-sample-rest
Figura 3 - pom.xml
Service Builder
Nella directory src/main/webapp/WEB-INF creiamo il file service.xml
Figura 4 - service.xml
Generiamo l’entità e le CRUD col commando mvn liferay:build-service -P dev. Modifichiamo la
classe ProductImpl aggiungendo il costruttore che riceve in input l’oggetto ProductSoap :
4. Figura 5 - ProductImpl.java
Modifichiamo la classe ProductLocalServiceImpl aggiungendo i metodi che ci occorrono; ho
sovrascritto il metodo addProduct per generare una chiave automatica e ho aggiunto il metodo
updateExistentProduct che aggiorna un prodotto già presente nel database.
Figura 6 - ProductLocalServiceImpl.java
Per questo progetto ho voluto utilizzare un database diverso da quello di default; a tal scopo ho creato il
file ext-spring.xml nella directory srcmainresourcesMETA-INF per la definizione del bean
externalDataSource. Ho definito le coordinate del database nel file portal-ext.properties (occorre
un restart di Liferay) e aggiornato il file service.xml per l’utilizzo della sorgente dati externalDataSource.
Infine ho creato la tabella nmastra_product nel database liferayrestdb.
Figura 7 - portal-ext.properties
Aggiorniamo le interfacce col comando: mvn liferay:build-service -P dev
5. Creazione del servizio REST
La classe che implementa il servizio è ProductRestServices; essa contiene cinque metodi:
• addProduct: metodo POST, consuma e produce dati in formato JSON, restituisce 201 in caso di
successo
• getProduct: metodo GET, produce dati in formato JSON, restituisce 200 in caso di successo
• getProducts: metodo GET, produce dati in formato JSON, restituisce 200 in caso di successo
• deleteProduct: metodo DELETE, restituisce 204 in caso di successo
• updateExistentProduct: metodo PUT, consuma dati in formato JSON, restituisce 204 in caso di
successo
A parte deleteProduct, tutti i metodi utilizzano come parametro la classe ProductSoap generata dal
Service Builder. Tale classe è pensata per la creazione di servizi remoti e ci eviterà problemi di
serializzazione/deserializzazione.
Figura 8 - ProductRestService
La gestione delle eccezioni è fatta via ExceptionMapper; la classe NoSuchProductMapper (annotata con
@Provider) associa l’eccezione NoSuchProductException allo stato HTTP 404 - Not Found.
6. Figura 9 - NoSuchProductMapper.java
Nel file web.xml agganciamo il motore Jersey. Il parametro
jersey.config.server.provider.packages indica alla servlet quali package contengono i provider:
nel nostro caso com.liferay.jersey.rest che contiene ProductRestServices e
NoSuchProductMapper, e com.sample.rest che contiene StatusFilter. Se vogliamo utilizzare la
sicurezza, configuriamo il filtro AuthenticationFilter indicando il tipo di autenticazione.
Figura 10 - web.xml
Assicuriamoci che Liferay sia attivo e deployamo la portlet con il commando:
mvn package liferay:deploy -P dev
7. Test
Per il test del servizio ho utilizzato SoapUI; la figura seguente mostra il progetto:
Figura 11 - Progetto SoapUI
Se abbiamo attivato AuthenticationFilter, su SoapUI dobbiamo impostare Username e Password:
Figura 12 - Autorizzazione
8. POST
Creiamo un prodotto utilizzando la richiesta Request 1 del metodo ADD_PRODUCT:
Figura 13 - Creazione di un prodotto
Ora proviamo ad inviare una richiesta priva di autorizzazione: utilizziamo la richiesta Not Authorized:
Figura 14 - Esempio HTTP Status 401
9. PUT
Aggiorniamo il prezzo del prodotto identificato dall’id 1501 utilizzando la Request 1 del metodo
UPDATE_PRODUCT:
Figura 15 - Aggiornamento di in prodotto
GET
Recuperiamo i dettagli del prodotto 1501; utilizziamo la richiesta OK sotto GET_PRODUCT_BY_ID:
Figura 16 - Recupero prodotto
10. Proviamo ora a cercare un prodotto che non esiste:
Figura 17 - HTTP Status 404
DELETE
Bye bye 1501: utilizziamo Request 1 sotto DELETE_PRODUCT_BY_ID:
Figura 18 - Cancellazione di un prodotto
Nella sezione Link è riportato l'url al quale scaricare il progetto liferay-jersey-portlet. Buona divertimento!
11. Documentazione
La documentazione interattiva (generata con Swagger) è disponibile all’indirizzo :
http://localhost:8080/liferay-jersey-portlet/docs.html
Figura 19 - Documentazione generata da Swagger
Link
https://www.liferay.com/it/
https://jersey.java.net/
http://www.liferaysavvy.com/2012/12/liferay-jersey-restful-web-services.html
https://www.liferay.com/it/web/vitor.silva/blog/-/blogs/using-restful-services-with-liferay
http://cosenonjaviste.it/liferay-esporre-web-services-custom/
http://rlopezblogs.blogspot.it/2014/11/access-multiple-datasources-in-liferay.html
http://www.webalice.it/nmastrapasqua/sources/liferay-jersey-portlet.zip
http://www.webalice.it/nmastrapasqua/sources/REST-Project-1-soapui-project.xml
https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5