bloggers bloggers

Marco Napolitano
Messaggi: 79
Stelle: 0
Data: 17/02/22
Jader Jed Francia
Messaggi: 63
Stelle: 0
Data: 18/02/21
Paolo Gambetti
Messaggi: 2
Stelle: 0
Data: 11/11/19
Katia Pazzi
Messaggi: 1
Stelle: 0
Data: 27/06/19
Ezio Lombardi
Messaggi: 11
Stelle: 0
Data: 10/04/18
Chiara Mambretti
Messaggi: 25
Stelle: 0
Data: 27/02/17
Serena Traversi
Messaggi: 3
Stelle: 0
Data: 21/07/16
Francesco Falanga
Messaggi: 8
Stelle: 0
Data: 14/06/16
Antonio Musarra
Messaggi: 2
Stelle: 0
Data: 18/11/13
Simone Celli Marchi
Messaggi: 6
Stelle: 0
Data: 09/07/13
Indietro

Esporre un servizio REST per ottenere il count delle notifiche

Ho avuto la necessità di dover recuperare il numero delle notifiche non lette tramite un servizio rest per poterne fare il polling via Javascript. Liferay purtroppo non mette a disposizione un api rest per le notifiche, per cui ho deciso di implementarla utilizzando il template BLADE "rest" messo a disposizione da Liferay DXP.

Ho creato, da Eclipse, un nuovo progetto utilizzando il template "rest"

Per prima cosa verifichiamo che nel  build.gradle ci siano le seguenti dipendenze:

    compile group: "javax.ws.rs", name:"javax.ws.rs-api", version:"2.0.1"
    compileOnly group: "org.apache.cxf", name: "cxf-core", version: "3.0.3"
    compileOnly group: "org.apache.cxf", name: "cxf-rt-frontend-jaxrs", version: "3.0.0"
    compileOnly group: "org.apache.cxf", name: "cxf-rt-rs-extension-providers", version: "3.0.3"

Ora creaimo nella cartella resources una cartella configuration e creiamo questi due files:

  • com.liferay.portal.remote.cxf.common.configuration.CXFEndpointPublisherConfiguration-cxf.properties
  • com.liferay.portal.remote.rest.extender.configuration.RestExtenderConfiguration-rest.properties

creaimo il CXFEndpointPublisherConfiguration-cxf.properties con queste property

contextPath=/api
extensions=
authVerifierProperties=auth.verifier.PortalSessionAuthVerifier.urls.includes\=*

e il RestExtenderConfiguration-rest con queste property

contextPaths=/api
jaxRsProviderFilterStrings=
jaxRsServiceFilterStrings=
jaxRsApplicationFilterStrings=

Inserendo queste configurazioni direttamente da property potremo pubblicare i nostri servizi (in questo esempio risponderranno sul path /api) senza dover configurare nulla in control panel, a patto di aggiungere al bnd.bnd le seguenti informazioni

Liferay-Configuration-Path: /configuration
Include-Resource:configuration=src/main/resources/configuration

A questo punto passiamo all'implementazione del codice vero e proprio

Il template blade avrà creato già un OSGI component con all'interno dei metodi di esempio.

Le annotation di JAX ci permettono di recuperare alcuni parametri direttamente dal contesto, ma purtroppo i parametri recuperabili di default non sono correlati a oggetti Liferay. Nel nostro specifico caso sarebbe utile poter recuperare l'utente direttamente dal contesto, senza che questo debba essere passato come parametro.

Cercando un pò in rete ho trovato questo articolo che spiega come creare dei custom provider:

https://web.liferay.com/it/web/user.26526/blog/-/blogs/rest-custom-context-providers

Di seguito il custom provider che ho creato per recuperare l'utente loggato

@Component(immediate = true, service = UserContextProvider.class)
@Provider
public class UserContextProvider implements ContextProvider<User> {

    @Override
    public User createContext(Message message) {
        try {
            return _portal.getUser(
                (HttpServletRequest)message.getContextualProperty(
                    "HTTP.REQUEST"));
        }
        catch (PortalException pe) {
            if (_log.isWarnEnabled()) {
                _log.warn("Unable to get user", pe);
            }

            return null;
        }
    }

    private static final Log _log = LogFactoryUtil.getLog(
        UserContextProvider.class);

    @Reference
    private Portal _portal;

}

Implementata la seguente classe basterà referenziarla attraverso il metodo getSingletons() creato in automatico da blade

@Override
    public Set<Object> getSingletons() {

        Set<Object> singletons = new HashSet<>();

        singletons.add(_userContextProvider);

        singletons.add(this);
        
        return singletons;

    }

Ora non ci rimane che esporre il nostro metodo per effettuare il count delle notifiche

@GET
    @Path("/notificationCount")
    @Produces(MediaType.APPLICATION_JSON)
    public String countNotifications(@Context User user) {

        int notificationCount = _userNotificationEventLocalService.getArchivedUserNotificationEventsCount(user.getUserId(), false);

        JSONObject jsonObject = JSONFactoryUtil.createJSONObject();

        jsonObject.put("notificationCount", notificationCount);

        return jsonObject.toJSONString();

    }

Invochiamo da browser l'url che risponde sul path /o/api/<rest-path>/notificationCount e il gioco è fatto.

 

 

 

Commenti
Aggiungi Commento
Giancarlo
Ciao, seguendo la guida ho un problema con la dipendenza di HttpServletRequest come se non vedesse nel gradle il modulo javax.servlet-api. Bisogna aggiungerlo esplicitamente?
Inviato il 25/10/18 16.08.
Marco Napolitano
Sì, devi aggiungere queste dipendenze:

compileOnly group: "javax.portlet", name: "portlet-api", version: "2.0"
compileOnly group: "javax.servlet", name: "javax.servlet-api", version: "3.0.1"
Inviato il 22/05/24 9.57 in risposta a Giancarlo.