Guida introduttiva a Mule ESB

1. Panoramica

Mule ESB è un Enterprise Service Bus leggero basato su Java. Consente agli sviluppatori di collegare più applicazioni insieme scambiando dati in diversi formati. Trasporta i dati sotto forma di messaggio.

Gli ESB offrono potenti funzionalità fornendo una serie di servizi, come:

  • Creazione e hosting di servizi
  • Mediazione del servizio
  • Instradamento dei messaggi
  • Trasformazione dei dati

Troveremo utili gli ESB se abbiamo bisogno di integrare più applicazioni insieme o se abbiamo l'idea di aggiungere più applicazioni in futuro.

ESB viene utilizzato anche per gestire più di un tipo di protocollo di comunicazione e quando sono richieste capacità di instradamento dei messaggi.

Creiamo un progetto di esempio nella sezione 5 utilizzando AnyPoint Studio, disponibile per il download qui.

2. Mule Message Structure

In poche parole, lo scopo principale di un ESB è quello di mediare tra i servizi e instradare i messaggi a vari endpoint. Quindi deve gestire diversi tipi di contenuti o payload.

La struttura del messaggio è divisa in due parti:

  • L'intestazione, checontiene i metadati del messaggio
  • Il payload, che contiene dati specifici dell'azienda

Il messaggio è incorporato in un oggetto messaggio. Possiamo recuperare l'oggetto messaggio dal contesto. Possiamo modificarne le proprietà e il payload utilizzando componenti e trasformatori Java personalizzati all'interno di un flusso Mule.

Ogni applicazione è costituita da uno o più flussi.

In un flusso, possiamo utilizzare i componenti per accedere, filtrare o alterare un messaggio e le sue diverse proprietà.

Ad esempio, possiamo ottenere un'istanza di un messaggio utilizzando il componente Java. Questa classe componente implementa un'interfaccia Callable dal pacchetto org.mule.api.lifecycle :

public Object onCall(MuleEventContext eventContext) throws Exception { MuleMessage message = eventContext.getMessage(); message.setPayload("Message payload is changed here."); return message; }

3. Proprietà e variabili

I metadati del messaggio sono costituiti da proprietà. Le variabili rappresentano i dati su un messaggio. Il modo in cui le proprietà e le variabili vengono applicate durante il ciclo di vita del messaggio è definito dai loro ambiti. Le proprietà possono essere di due tipi, in base al loro ambito: in entrata e in uscita.

Le proprietà in ingresso contengono metadati che impediscono che i messaggi vengano codificati durante l'attraversamento dei flussi. Le proprietà in entrata non sono modificabili e non possono essere modificate dall'utente. Sono presenti solo per la durata del flusso: una volta che il messaggio esce dal flusso, le proprietà in entrata non sono più presenti.

Le proprietà in uscita possono essere impostate automaticamente da Mule oppure un utente può impostarle tramite la configurazione del flusso. Queste proprietà sono mutabili. Diventano proprietà in entrata quando un messaggio entra in un altro flusso dopo aver attraversato le barriere di trasporto.

Possiamo impostare e ottenere proprietà in uscita e in entrata rispettivamente chiamando i metodi setter e getter associati nei rispettivi ambiti:

message.setProperty( "outboundKey", "outboundpropertyvalue", PropertyScope.OUTBOUND); String inboundProp = (String) message.getInboundProperty("outboundKey");

Sono disponibili due tipi di variabili da dichiarare nelle applicazioni.

Una è la variabile di flusso che è locale a un flusso Mule e disponibile attraverso il flusso, i flussi secondari e i flussi privati.

Le variabili di sessione una volta dichiarate diventano disponibili nell'intera applicazione.

4. Barriere di trasporto e flusso-rif

Le barriere di trasporto sono connettori HTTP, VM, JMS o connettori simili che richiedono percorsi o endpoint per l'instradamento dei messaggi. Le variabili di flusso non sono disponibili attraverso le barriere di trasporto, ma le variabili di sessione sono disponibili in tutto il progetto in tutti i flussi.

Quando è necessario creare un flusso secondario o privato, è possibile fare riferimento al flusso da un flusso principale o da un altro utilizzando il componente flusso-rif . Sia le variabili di flusso che le variabili di sessione sono disponibili nei flussi secondari e nei flussi privati ​​a cui si fa riferimento utilizzando flow-ref .

5. Progetto di esempio

Creiamo un'applicazione in Anypoint Studio che contenga più flussi, che comunicano tra loro tramite connettori in entrata e in uscita.

Diamo un'occhiata al primo flusso:

Possiamo configurare un listener HTTP come:

I componenti del flusso devono trovarsi all'interno di un file etichetta. Quindi, un flusso di esempio con più componenti è:

All'interno del flusso, stiamo fornendo un riferimento a un listener HTTP configurato. Quindi teniamo un logger per registrare il payload che il listener HTTP sta ricevendo tramite il metodo POST.

Successivamente, viene inserita una classe di trasformatore Java personalizzata, che trasforma il payload dopo aver ricevuto il messaggio:

public Object transformMessage( MuleMessage message, String outputEncoding) throws TransformerException { message.setPayload("Payload is transferred here."); message.setProperty( "outboundKey", "outboundpropertyvalue", PropertyScope.OUTBOUND); return message; }

La classe del trasformatore deve estendere AbstractMessageTransformer . Stiamo anche impostando una proprietà in uscita all'interno della classe.

Ora, abbiamo già convertito il payload all'interno dell'oggetto messaggio e lo abbiamo registrato nella console utilizzando logger. Stiamo impostando una variabile di flusso e una variabile di sessione.

Infine, stiamo inviando il nostro payload tramite il connettore VM in uscita. Il percorso nel connettore VM determina l'endpoint ricevente:

Il messaggio trasportato e trasformato dal flusso iniziale raggiunge Flow1 tramite un endpoint VM in ingresso.

Il componente Java recupera le proprietà in uscita impostate dal primo flusso e restituisce l'oggetto che diventa il payload del messaggio.

Il metodo transformMessage () per questa attività:

public Object transformMessage( MuleMessage message, String outputEncoding) throws TransformerException { return (String) message.getInboundProperty("outboundKey"); }

Quindi, le variabili di flusso e di sessione vengono impostate sul secondo flusso. Dopodiché, abbiamo un riferimento a Flow2 utilizzando il componente flow-ref .

In Flow2, abbiamo trasformato il messaggio utilizzando la classe del componente Java e lo abbiamo registrato nella console. Abbiamo anche impostato una variabile di flusso F3 .

Dopo aver chiamato Flow2 utilizzando flow-ref, Flow1 attenderà che il messaggio venga elaborato in Flow2 .

Qualsiasi variabile di flusso impostata in Flow1 e Flow2 sarà disponibile in entrambi i flussi poiché questi flussi non sono separati da alcuna barriera di trasporto.

Infine, il messaggio viene rispedito al richiedente HTTP tramite le VM. Abbiamo configurato tutte le VM come richiesta-risposta.

Possiamo richiamare questa applicazione da qualsiasi client REST inserendo qualsiasi dato JSON nel corpo. L'URL sarà localhost: 8081 come configurato nel listener HTTP.

6. Maven Archetype

We can build a Mule ESB project using Mulesoft's Maven archetype.

In Maven's settings.xml file, we first need to add the org.mule.tools plugin group:

 org.mule.tools 

Then, we need to add a profile tag that says where Maven should look for Mulesoft artifacts:

 Mule Org  true    mulesoft-releases MuleSoft Repository //repository-master.mulesoft.org/releases/ default   

Finally, we can create the project using mule-project-archetype:create:

mvn mule-project-archetype:create -DartifactId=muleesb -DmuleVersion=3.9.0

After configuring our project, we can create a deployable archive using mvn package.

After that, we'd deploy the archive into the apps folder of any standalone Mule server.

7. A Standalone Mule Server via MuleSoft's Maven Repository

As just noted, the project we just created requires a standalone Mule server.

If we don't already have one, we can edit our pom.xml to pull one from MuleSoft's Maven repository:

 org.mule.tools.maven mule-maven-plugin 2.2.1  standalone 3.9.0    deploy deploy  deploy    

8. Conclusion

In this article, we've gone through different necessary concepts of building as ESB application in Mule. We've created a sample project illustrating all the described concepts.

We can now start creating ESB application using Anypoint Studio to meet our various needs.

As usual, the complete project can be found over on GitHub.

1. Overview

Mule ESB is a lightweight Java-based Enterprise Service Bus. It allows developers to connect multiple applications together by exchanging data in different formats. It carries data in the form of a message.

ESBs offer powerful capabilities by providing a number of services, such as:

  • Service creation and hosting
  • Service mediation
  • Message routing
  • Data transformation

We'll find ESBs useful if we need to integrate multiple applications together, or if we have the notion of adding more applications in the future.

ESB is also used for dealing with more than one type of communication protocol and when message routing capabilities are required.

Let's create a sample project in Section 5 using AnyPoint Studio which is available for download here.

2. Mule Message Structure

Simply put, the primary purpose of an ESB is to mediate between services and route messages to various endpoints. So it needs to deal with different types of content or payload.

The message structure is divided into two parts:

  • The header, whichcontains message metadata
  • The payload, which contains business-specific data

The message is embedded within a message object. We can retrieve the message object from the context. We can change its properties and payload using custom Java components and transformers inside a Mule flow.

Each application consists of one or more flows.

In a flow, we can use components to access, filter or alter a message and its different properties.

For example, we can obtain an instance of a message using Java component. This component class implements a Callable interface from org.mule.api.lifecycle package:

public Object onCall(MuleEventContext eventContext) throws Exception { MuleMessage message = eventContext.getMessage(); message.setPayload("Message payload is changed here."); return message; }

3. Properties and Variables

Message metadata consists of properties. Variables represent data about a message. How properties and variables are applied across the message's life-cycle is defined by their scopes. Properties can be of two types, based on their scope: inbound and outbound.

Inbound properties contain metadata that prevents messages to become scrambled while traversing across flows. Inbound properties are immutable and cannot be altered by the user. They're present only for the duration of the flow – once the message exits the flow, inbound properties are no longer there.

Outbound properties can be set automatically by Mule, or a user can set them through flow configuration. These properties are mutable. They become inbound properties when a message enters another flow after crossing transport-barriers.

We can set and get outbound and inbound properties respectively by calling associated setter and getter methods in their respective scopes:

message.setProperty( "outboundKey", "outboundpropertyvalue", PropertyScope.OUTBOUND); String inboundProp = (String) message.getInboundProperty("outboundKey");

There are two types of variables available to declare in applications.

One is flow variable which is local to a Mule flow and available across the flow, sub-flows and private flows.

Session variables once declared become available across the entire application.

4. Transport Barriers and flow-ref

Transport barriers are HTTP-connectors, VMs, JMS or similar connectors that require paths or endpoints for messages to be routed. Flow variables aren't available across transport barriers, but session variables are available across the project in all flows.

When we need to create sub-flow or private flow, we can refer to the flow from a parent or another flow using flow-ref component. Both flow variables and session variables are available in sub-flows and private flows referred to using flow-ref.

5. Example Project

Let's create an application in Anypoint Studio that contains multiple flows, which communicate between themselves through inbound and outbound connectors.

Let's look at the first flow:

We can configure an HTTP listener as:

Flow components must be inside a tag. So, an example flow with multiple components is:

Inside the flow, we're providing a reference to a configured HTTP listener. Then we're keeping a logger to log the payload that HTTP listener is receiving through POST method.

After that, a custom Java transformer class is placed, that transforms the payload after receiving the message:

public Object transformMessage( MuleMessage message, String outputEncoding) throws TransformerException { message.setPayload("Payload is transferred here."); message.setProperty( "outboundKey", "outboundpropertyvalue", PropertyScope.OUTBOUND); return message; }

The transformer class must extend AbstractMessageTransformer. We're also setting an outbound property inside the class.

Now, we have already converted payload inside the message object, and have logged that in the console using logger. We're setting a flow variable and a session variable.

Finally, we are sending our payload through outbound VM connector. The path in VM connector determines the receiving endpoint:

The message carried and transformed by the initial flow reaches Flow1 through an inbound VM endpoint.

The Java component retrieves outbound properties set by the first flow and returns the object which becomes the message payload.

The transformMessage() method for this task:

public Object transformMessage( MuleMessage message, String outputEncoding) throws TransformerException { return (String) message.getInboundProperty("outboundKey"); }

Then, flow and session variables are set to the second flow. After that, we've got a reference to Flow2 using flow-ref component.

In Flow2, we've transformed the message using Java component class and logged it in the console. We've also set a flow variable F3.

After calling Flow2 using flow-ref, Flow1 will wait for the message to be processed in Flow2.

Any flow variable set in Flow1 and Flow2 will be available in both flows since these flows aren't separated by any transport barriers.

Finally, the message is sent back to the HTTP requester through VMs. We configured all VMs as request-response.

We can invoke this application from any REST client by posting any JSON data in the body. The URL will be localhost:8081 as configured in HTTP listener.

6. Maven Archetype

We can build a Mule ESB project using Mulesoft's Maven archetype.

In Maven's settings.xml file, we first need to add the org.mule.tools plugin group:

 org.mule.tools 

Then, we need to add a profile tag that says where Maven should look for Mulesoft artifacts:

 Mule Org  true    mulesoft-releases MuleSoft Repository //repository-master.mulesoft.org/releases/ default   

Finally, we can create the project using mule-project-archetype:create:

mvn mule-project-archetype:create -DartifactId=muleesb -DmuleVersion=3.9.0

After configuring our project, we can create a deployable archive using mvn package.

After that, we'd deploy the archive into the apps folder of any standalone Mule server.

7. A Standalone Mule Server via MuleSoft's Maven Repository

As just noted, the project we just created requires a standalone Mule server.

Se non ne abbiamo già uno, possiamo modificare il nostro pom.xml per estrarne uno dal repository Maven di MuleSoft:

 org.mule.tools.maven mule-maven-plugin 2.2.1  standalone 3.9.0    deploy deploy  deploy    

8. Conclusione

In questo articolo, abbiamo esaminato diversi concetti necessari per creare come applicazione ESB in Mule. Abbiamo creato un progetto di esempio che illustra tutti i concetti descritti.

Ora possiamo iniziare a creare un'applicazione ESB utilizzando Anypoint Studio per soddisfare le nostre diverse esigenze.

Come al solito, il progetto completo può essere trovato su GitHub.