How to: Esempio pratico di una orchestrazione di microservizi con Apache Camel.

Andrea Cavallo
5 min readApr 3, 2023

Per cominciare, cerchiamo di visualizzare graficamente l’implementazione dell’orchestrazione.

@AndreaCavallo

In questo modo, potremo avere un’idea più chiara e precisa del flusso di lavoro all’interno dell’orchestrazione e delle interazioni con i μs convolti e delle API esposte.

L’orchestrazione riceve in input un JSON :

Input Example

L’input contiene

  • informazioni sul cliente: (firstName e lastName);
  • informazioni sul prodotto richiesto: (productName) e sulla quantità: (quantity).

In base al nome del prodotto richiesto e alla quantità, l’orchestrazione chiama gli endpoint esposti dal secondo microservizio per processare e persistere l’ordine.

Se il prodotto richiesto dall’utente è disponibile, allora viene creato un ordine e le informazioni sull’ordine vengono salvate su MongoDB,

e quindi l’output dell’orchestrazione sarà:

Order Created

Il messaggio contiene le informazioni sull’ordine, le informazioni sul cliente e le informazioni sul prodotto.

L’oggetto output contiene lo stato dell’ordine (orderStatus), le informazioni sull’ordine (orderInfo), le informazioni sul cliente (userInfo) e le informazioni sul prodotto (productInfo).

In caso di eventuali errori durante l’elaborazione, tali errori verranno segnalati nell’oggetto errorMessages dell’output JSON.

Nel caso in cui il prodotto richiesto non sia disponibile, l’ordine verrà rifiutato e l’attributo orderStatus dell’output JSON sarà : “Rejected”.

Order Rejected

In questa situazione, l’ordine non verrà persistito, ovvero non verrà salvato su mongoDB.

È importante sottolineare che questa scelta può essere considerata appropriata in alcuni casi, in cui gli ordini rifiutati non sono considerati validi o non è necessario tener traccia di essi.

Tuttavia, in altri contesti potrebbe essere utile mantenere un registro degli ordini rifiutati per analizzare le cause dei problemi e migliorare il processo di gestione degli ordini.

In ogni caso, la scelta dipende dalle specifiche esigenze dell’applicazione e dalla sua architettura.

Facciamo uso dei diversi componenti offerti da Apache Camel per gestire la logica di business.

In particolare, da ora in avanti ci concentreremo su RouteBuilder e Processor, due componenti fondamentali che ci consentono di creare e gestire con efficacia i flussi di integrazione e le trasformazioni dei dati nel contesto dell’orchestrazione. 🛠️💼

RouteBuilder è uno dei principali strumenti offerti da Camel per la definizione delle rotte.

Con il RouteBuilder, si può definire l’origine e la destinazione dei messaggi e specificare le eventuali operazioni da effettuare durante il percorso del messaggio.

Nel nostro caso, la classe UserRouteBuilder estende RouteBuilder.

Nota: L’annotazione @Component viene utilizzata per indicare a Spring che UserRouteBuilder deve essere gestito come un componente Spring all’interno dell’applicazione.

UserRouteBuilder class

Questa logica rappresenta il cuore dell’orchestrazione in Apache Camel:

  1. La logica inizia con il componente from(DIRECT_CREATE_USER), che indica l'origine dei messaggi in ingresso e avvia il flusso di integrazione.
  2. Successivamente, viene eseguito il processore headerGetMapperProcessor che elabora gli header del messaggio in particolare settiamo HTTPmethod: GET.
  3. Il processore getProductInfoProcessor si occupa di recuperare le informazioni sul prodotto, in base al name passato dalla userRequest.
  4. Segue il processore headerPostMapperProcessor che modifica nuovamente gli header del messaggio cambiandolo in POST.
  5. Il processore bodyRequestProcessor elabora il corpo del messaggio, preparandolo per la fase successiva.
  6. La logica prosegue con un blocco choice(), che permette di effettuare una scelta condizionale tra due o più rami di elaborazione: a. Se la condizione CHECK_AVAILIBILITY="${bodyorderStatus}=='PROCESSING'" è vera, il sistema elabora l'ordine: createOrderProcessor per creare l'ordine, registra un altro messaggio di log per mostrare l'ordine creato e, infine, esegue il processore responseProcessor.Altrimenti, se la condizione non è vera, il sistema rifiuta l'ordine a causa della mancanza di disponibilità del prodotto in magazzino.
  7. La logica termina con il comando end() che indica la fine del blocco condizionale.

Inoltre, Apache Camel offre anche la possibilità di creare propri processori personalizzati per effettuare operazioni specifiche sui messaggi.

Nel nostro esempio, abbiamo creato una classe SendToEndpoint che ha il compito di richiamare gli endpoint esposti dal secondo microservizio per la gestione degli ordini.

In particolare soffermiamoci sul component sendToEndpoint:

sendToEndpoint Processor

Abbiamo creato una istanza dell’oggetto ProducerTemplate utilizzando il CamelContext dell’oggetto Exchange.

L’istanza producerTemplate verrà poi automaticamente chiusa grazie all’utilizzo della sintassi try-with-resources.

L’oggetto Exchange send = createProducerTemplate.send(someUri, exchange); utilizza il producerTemplate per inviare all’uri di destinazione un certo corpo del messaggio.

Il risultato di questo invio viene infine salvato in una nuova istanza di Exchange chiamata send.

E infine impostiamo il corpo del messaggio dell’oggetto exchange corrente con il corpo del messaggio dell’oggetto send precedentemente creato.

Processor : OrderProcessor, che ha il compito di trasformare, creare un vero e proprio Ordine in base all’input dell’utente (UserRequest) e l’output della fetchProductByName “productFound”.

Riassumendo in questa orchestrazione abbiamo utilizzato:

Camel Contextper creare ProducerTemplate;

EndpointsAbbiamo customizzato e creato la nostra Classe SendToEndpoint ;

RoutesUserRouteBuilder;

Processors OrderProcessor;

Messages and Exchange → l’oggetto che ci passiamo da un process all’altro.

Per testare questa applicazione bisogna clonare entrambi i progetti in locale.

e scaricare la versione Community MongodB per il proprio sistema operativo.

Una volta clonati entrambi i progetti, preparato l’ambiente consiglio di scaricare da github la collection postman, e leggere il README.md per ulteriori dettagli.

Consiglio di aprire in un unico workspace l’orchestratore e il product-ms per una visualizzazione più comoda: ( Nota io ho utilizzato come IDE STS4 )

Come prima bisogna creare sul db almeno un prodotto:

verifichiamo la presenza del prodotto sul nostro db:

e infine possiamo testare l’orchestrazione:

Come ulteriore spunto, sarebbe interessante esplorare l’aggiunta del Circuit Breaker o del saga per gestire in modo più efficace situazioni di errore o scenari complessi.

Queste funzionalità possono migliorare ulteriormente la resilienza e l’affidabilità del sistema di integrazione.

--

--