Comunicazione tra plugin grazie al Message Bus

» Scritto da il 19 aprile 2015 in Liferay

Comunicazione tra plugin grazie al Message Bus
image_pdfimage_print

Come far comunicare tra loro due plugin differenti?

Ci sono vari modi per trasferire informazioni tra due plugin differenti. Uno di questi è lo scambio di messaggi tramite Message Bus.

Possiamo individuare due ruoli principali in questa comunicazione:

  • Message producer – Il plugin che crea il messaggio
  • Message consumer – Il plugin che riceve il messaggio

Vediamo quali sono i passi necessari per implementare questo tipo di comunicazione

Message producer – Creare la Destination

Per prima cosa occorre creare una destinazione per i nostri messaggi. Questa operazione può essere fatta nel file messaging-spring.xml ma in questo modo ogni volta che il plugin sarà deployato la destination verrà ricreata, perdendo tutti i listener eventualmente associati. Un modo per ovviare a questo problema è creare la destination tramite codice java:

private static String DESTINATION_NAME = "marcorosetti/myentity/update"
private void createDestinations()
{
   if(!MessageBusUtil.getMessageBus().hasDestination(DESTINATION_NAME)){
	BaseDestination destination = new ParallelDestination();
	destination.setName(DESTINATION_NAME);
        destination.open(); MessageBusUtil.addDestination(destination);
   }else {
        Destination destination = MessageBusUtil.getMessageBus().getDestination(DESTINATION_NAME);
        destination.open();
   }
} 

Il miglior momento in cui invocare questo metodo è all’interno del metodo di startup del plugin. Per i dettagli vedere QUI

Message producer – Inviare il messaggio

Per inviare il messaggio possiamo utilizzare in qualsiasi punto del nostro codice alcuni metodi statici messi a disposizione da Liferay. Il messaggio creato può

....
Message message = new Message();
message.put("className", MyEntity.class.getName());
message.put("classPK", myEntity.getPrimaryKey());

MessageBusUtil.sendMessage("marcorosetti/myentity/update", message);
...

Message consumer – Implementare il listener

Per prima cosa dobbiamo implementare la classe che gestirà la ricezione del messaggio. Per farlo dobbiamo estendere la classe com.liferay.portal.kernel.messaging.MessageListener: in particolare la logica di gestione del messaggio deve essere implementata nel metodo void receive(Message message):

public class MyListener extends MessageListener{
....
@Override
public void receive(Message message) throws MessageListenerException {
   String className = message.getString("className");
   String classPK =  message.getString("classPK");
   _log.debug("Message received className "+className+" and classPK "+classPK);
   ....
}

Message consumer – Agganciare il listener alla destination

Una volta implementato il listener va agganciato alla destinazione creata. Ricordiamoci di gestire anche il redeploy del plugin, quindi di controllare se è già presente un listener del tipo implementato prima di aggiungerlo. Per farlo possiamo usare codice di questo tipo:

Destination destination = MessageBusUtil.getMessageBus().getDestination(destinationName);
if(destination != null) {
Set<MessageListener> listeners = destination.getMessageListeners();
for (MessageListener messageListener : listeners) {
   if(messageListener instanceof MyListener) {
      _log.debug("Found MyListener registered to destination "+destinationName+" removing it");
      MessageBusUtil.unregisterMessageListener(destination.getName(), messageListener);
   }else if(messageListener instanceof InvokerMessageListener)
      InvokerMessageListener invoker = (InvokerMessageListener)messageListener;
      if(invoker.getMessageListener().getClass().getName().equals(MyListener.class.getName()))
         _log.debug("Found MyListener registered to destination "+destinationName+" removing it");
         MessageBusUtil.unregisterMessageListener(destination.getName(), invoker.getMessageListener());
      }
   }
}
MessageBusUtil.registerMessageListener(destinationName, new MyListener());

Non facciamoci spaventare da un codice all’apparenza più complesso del solito: si tratta di scorrere tutta la lista dei listener agganciati alla destinazione ed eventualmente sganciare il listener della classe MyListener. La complicazione nasce dal fatto che in alcuni casi viene utilizzato il proxy InvokerMessageListener per wrappare la vera classe del listener. Non ci addentriamo nei dettagli di questa scelta ma ci basta sapere come gestirla: invocando il metodo getMessageListener() sul proxy, che ci restituisce la vera istanza del listener e ci permette di verificarne la classe.

Anche in questo caso conviene fare questa operazione all’interno del codice di startup del plugin in modo da essere sicuri che venga eseguita sempre quando il plugin è presente

Approfondimenti e riferimenti

Scrivi un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>