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

IPC client-side in Liferay.

Ciao a tutti.

La specifica JSR 286 ha indrodotto 2 modalità per lo scambio di informazioni tra portlet, noto come Inter-Portlet-Communication: uno basato sullo scambio di parametri (shared render parameters) e un modello ad eventi.

Il modello ad eventi è quello più interessante.

In breve, una portlet viene configurata per inviare un evento e una o più portlet vengono configurate per ricevere e consumare l'evento; la configurazione viene fatta nel file portlet.xml e un evento è un qualunque oggetto che sia serializable.

Supponiamo di avere una portlet che visualizza categorie ad albero nel modo classico: cliccando su una categoria appare il <div> che contiene le sotto categorie (stile portlet "Categories Navigation") e supponiamo di avereuna portlet che visualizza prodotti, filtrando la lettura dalla base dati tramite la categoria cliccata sull'altra (stile asset publisher).

Nel file portlet.xml,portlet che pubblica l’evento

<supported-publishing-event>
<name> catSelected </name>
</supported-publishing-event>

pe la portlet che processa l’evento

<supported-processing-event>
<name> catSelected </name>
</supported-processing-event>

Ogni portlet che riceve l'evento, implementa il metodo

@ProcessingEvent(name = “catSelected”)

public void processoCatSelected(EventRequest request, EventResponse response)

throws IOException, PortletException {

Event event = request.getEvent();

String catId = (String) event.getValue();

List <Prodotti> prodotti =readProdottiFromDb(catId);

request.getPortletSession().setAttribute(“prodotti”, prodotti);

}

L'evento viene consumato nel metodo e quindi è possibile, ad esempio, memorizzarlo nella portletSession per utilizzarlo successivamente in una pagina jsp. L'annotation serve per discriminare tra i metodi processAction che processano eventi differenti.

La portlet che invia l'evento, lo fa con l'istruzione seguente, posta in un metodo processAction

response.setEvent(“catSelected”, "123");

Viene quindi scambiato l'evento "selezionata categoria 123"

Tramite il "giro di giostra" descritto l'evento viene scambiato tra le portlet a livello server e questo implica che la pagina debba essere ricaricata interamente e che quindi dobbiamo memorizzare in qualche modo lo stato di visualizzazione delle portlet per poter ripresentare all'utente la schermata esattamente come l'ha lasciata: nel nostro caso devo ricordare quale è la categoria cliccata per poter mostrare l'albero delle categorie in modo corretto. Per portlet molto complesse questo può essere fastidioso.

Se solo si potesse utilizzare ajax...

Effettivamente possiamo fare la stessa cosa utilizzando una funzionalita di IPC messa a disposizione da LR 6.x nota come IPC client-side.

Si tratta delle funzioni javascriptLiferay.fire e Liferay.on, utilizzate rispettivamente per inviare e ricevere un evento in due portlet instanziate nella stessa pagina.

In Liferay 5.x si chiamavano Liferay.trigger e Liferay.bind; sono identiche alle rispettive attuali ma hanno cambiato nome per motivi a me oscuri.

La cosa interessante è che il tutto viene fatto a livello javascript senza dover configurare nulla nei files xml delle mie portlet e tutto il giro viene generato e consumato sulla pagina tra qualunque portlet.

Per inviare un evento:

...

jQuery(function () {
    jQuery('a.categoria_item').click(
       function(event) {
           var catId = jQuery(this).next().val();
           Liferay.fire('catSelected', {categoryId: catId});            return false;
         }
       )
     }
  );

...

<a href="#" class="categoria_item">mia categoria</a>

<input type="hidden" name="catId" value="123">

In questo esempio al click sul link viene inviato un evento "catSelected" che consiste in un JSON, perfetto in questo caso.

Nella portlet che processa l'evento:

<script type="text/javascript">
Liferay.on(
   'catSelected',
   function(event) {
  var catId = event.categoryId;
  jQuery('#prodottiWrapper').html('');
     jQuery.ajax({
         type: 'POST',
         url: '<%=setCatAction%>',
         data:"catId="+catId,
         success: function(data){
             jQuery('#prodottiWrapper').html(data);
         }
       });
    return false;
   }
 );
</script>

In sostanza l'elaborazione dell'evento consiste nella chiamata ajax ad un action della mia portlet che legge dalla base dati i prodotti che appartengono alla categoria selezionata, mostrati nel <div id="prodottiWrapper"></div>.

Il risultato è che la user experience è molto più fluida, tutte le portlet che stanno intorno ignorano tutto questo dialogo e continuano a vivere felicemente nell'ignoranza, genero meno traffico di rete e infine non mi pongo il problema di memorizzare quale categoria è stata cliccata perchè il mio albero di categorie non viene ricaricato.

Hope it helps!

Marcello

Precedente
Commenti
Aggiungi Commento
Andrea Di Giorgi
Quei metodi hanno cambiato nome xke ora si basano su AlloyUI, e più precisamente sugli eventi di YUI3, in cui ci sono i metodi on e fire ^_^
Inviato il 09/07/15 14.02.
marcello marangio
grazie per la info.
M
Inviato il 09/07/15 14.02 in risposta a Andrea Di Giorgi.