Apache Camel con Spring Boot

1. Panoramica

Fondamentalmente, Apache Camel è un motore di integrazione che, in poche parole, può essere utilizzato per facilitare le interazioni tra un'ampia e varia gamma di tecnologie.

Questi ponti tra servizi e tecnologie sono chiamati rotte. I percorsi sono implementati su un motore (il CamelContext ) e comunicano con i cosiddetti "messaggi di scambio".

2. Dipendenze di Maven

Per iniziare, dobbiamo includere le dipendenze per Spring Boot, Camel, Rest API con Swagger e JSON:

  org.apache.camel camel-servlet-starter ${camel.version}   org.apache.camel camel-jackson-starter ${camel.version}   org.apache.camel camel-swagger-java-starter ${camel.version}   org.apache.camel camel-spring-boot-starter ${camel.version}   org.springframework.boot spring-boot-starter-web ${spring-boot-starter.version}  

Le ultime versioni delle dipendenze di Apache Camel possono essere trovate qui.

3. La classe principale

Diamo prima creare uno Stivale Primavera Applicazione :

@SpringBootApplication @ComponentScan(basePackages="com.baeldung.camel") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

4. Configurazioni Camel per Spring Boot

Configuriamo ora la nostra applicazione con Spring, iniziando con i file di configurazione (proprietà).

Ad esempio, configuriamo un log per la nostra applicazione su un file application.properties in src / main / resources :

logging.config=classpath:logback.xml camel.springboot.name=MyCamel server.address=0.0.0.0 management.address=0.0.0.0 management.port=8081 endpoints.enabled = true endpoints.health.enabled = true

Questo esempio mostra un file application.properties che imposta anche il percorso a una configurazione Logback. Impostando l'IP su "0.0.0.0", limitiamo completamente l' accesso di amministrazione e gestione al server web fornito da Spring Boot. Inoltre, consentiamo l'accesso di rete necessario agli endpoint delle nostre applicazioni e agli endpoint di controllo dello stato.

Un altro file di configurazione è application.yml . In esso, aggiungeremo alcune proprietà per aiutarci a iniettare valori nelle nostre rotte dell'applicazione:

server: port: 8080 camel: springboot: name: ServicesRest management: port: 8081 endpoints: enabled: false health: enabled: true quickstart: generateOrderPeriod: 10s processOrderPeriod: 30s

5 . Configurazione del Camel Servlet

Un modo per iniziare a utilizzare Camel è registrarlo come servlet, in modo che possa intercettare le richieste HTTP e reindirizzarle alla nostra applicazione.

Come accennato prima, a partire dalla versione 2.18 di Camel e precedenti possiamo sfruttare il nostro application.yml , creando un parametro per il nostro URL finale. Successivamente verrà iniettato nel nostro codice Java:

baeldung: api: path: '/camel'

Tornando alla nostra classe Application , dobbiamo registrare il servlet Camel alla radice del nostro percorso di contesto, che verrà iniettato dal riferimento baeldung.api.path in application.yml all'avvio dell'applicazione:

@Value("${baeldung.api.path}") String contextPath; @Bean ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean servlet = new ServletRegistrationBean (new CamelHttpTransportServlet(), contextPath+"/*"); servlet.setName("CamelServlet"); return servlet; }

A partire dalla versione 2.19 di Camel, questa configurazione è stata abbandonata poiché CamelServlet è impostato di default su "/ camel" .

6. Costruire un percorso

Iniziamo a creare un percorso estendendo la classe RouteBuilder da Camel e impostandola come @Component in modo che la routine di scansione dei componenti possa individuarla durante l'inizializzazione del server web:

@Component class RestApi extends RouteBuilder { @Override public void configure() { CamelContext context = new DefaultCamelContext(); restConfiguration()... rest("/api/")... from("direct:remoteService")... } }

In questa classe, sovrascriviamo il metodo configure () dalla classe RouteBuilder di Camel .

Camel ha sempre bisogno di un'istanza CamelContext , il componente principale in cui vengono conservati i messaggi in entrata e in uscita.

In questo semplice esempio, DefaultCamelContext è sufficiente in quanto associa solo messaggi e route, come il servizio REST che creeremo.

6.1. Il restConfiguration () Percorso

Successivamente, creiamo una dichiarazione REST per gli endpoint che intendiamo creare nel metodo restConfiguration () :

restConfiguration() .contextPath(contextPath) .port(serverPort) .enableCORS(true) .apiContextPath("/api-doc") .apiProperty("api.title", "Test REST API") .apiProperty("api.version", "v1") .apiContextRouteId("doc-api") .component("servlet") .bindingMode(RestBindingMode.json)

Qui, registriamo il percorso del contesto con il nostro attributo inserito dal file YAML. La stessa logica è stata applicata al port della nostra applicazione. CORS è abilitato, consentendo l'uso cross-site di questo servizio web. La modalità di associazione consente e converte gli argomenti nella nostra API.

Successivamente, aggiungiamo la documentazione Swagger all'URI, al titolo e alla versione che abbiamo impostato in precedenza. Man mano che creiamo metodi / endpoint per il nostro servizio web REST, la documentazione di Swagger verrà aggiornata automaticamente.

Questo contesto Swagger è esso stesso un percorso Camel e possiamo vedere alcune informazioni tecniche su di esso nel registro del server durante il processo di avvio. La nostra documentazione di esempio viene fornita per impostazione predefinita in // localhost: 8080 / camel / api-doc.

6.2. Il resto () Route

Ora implementiamo la chiamata al metodo rest () dal metodo configure () sopra elencato:

rest("/api/") .id("api-route") .consumes("application/json") .post("/bean") .bindingMode(RestBindingMode.json_xml) .type(MyBean.class) .to("direct:remoteService");

Questo metodo è abbastanza semplice per chi ha familiarità con le API. L' id è l'identificazione del percorso all'interno del CamelContext . La riga successiva definisce il tipo MIME. La modalità di associazione è definita qui per mostrare che è possibile impostare una modalità su restConfiguration () .

Il metodo post () aggiunge un'operazione all'API, generando un endpoint " POST / bean ", mentre MyBean (un normale bean Java con un id Integer e un nome String ) definisce i parametri previsti.

Allo stesso modo, le azioni HTTP come GET, PUT e DELETE sono tutte disponibili anche sotto forma di get () , put () , delete () .

Infine, il metodo to () crea un ponte verso un'altra rotta. Qui dice a Camel di cercare all'interno del suo contesto / motore verso un'altra rotta che stiamo per creare - che è denominata e rilevata dal valore / id " direct:… ", corrispondente alla rotta definita nel metodo from () .

6.3. Il from () Instrada con transform ()

Quando si lavora con Camel, una rotta riceve i parametri e quindi converte, trasforma ed elabora questi parametri. Successivamente, invia questi parametri a un'altra route che inoltra il risultato all'output desiderato (un file, un database, un server SMTP o una risposta API REST).

In questo articolo, creiamo solo un altro percorso all'interno del metodo configure () che stiamo sovrascrivendo. Sarà il percorso di destinazione per il nostro ultimo percorso to () :

from("direct:remoteService") .routeId("direct-route") .tracing() .log(">>> ${body.id}") .log(">>> ${body.name}") .transform().simple("Hello ${in.body.name}") .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

Il metodo from () segue gli stessi principi e ha molti degli stessi metodi del metodo rest () , tranne per il fatto che utilizza i messaggi di contesto Camel. Questo è il motivo per il parametro " direct-route ", che crea un collegamento al metodo summenzionato rest (). To () .

Sono disponibili molte altre conversioni , inclusa l'estrazione come primitive (o oggetti) Java e l'invio a un livello di persistenza. Si noti che le rotte leggono sempre dai messaggi in arrivo, in modo che le rotte concatenate ignoreranno i messaggi in uscita.

Il nostro esempio è pronto e possiamo provarlo:

  • Esegui il comando prompt: mvn spring-boot: run
  • Esegui una richiesta POST a // localhost: 8080 / camel / api / bean con parametri di intestazione: Content-Type: application / json e un payload {"id": 1, "name": "World"}
  • Dovremmo ricevere un codice di ritorno 201 e la risposta: Hello, World

6.4. Il SEMPLICE linguaggio di scripting

L'esempio restituisce la registrazione utilizzando il metodo tracing () . Notare che abbiamo utilizzato i segnaposto $ {} ; questi fanno parte di un linguaggio di scripting che appartiene a Camel chiamato SIMPLE. Viene applicato ai messaggi scambiati lungo il percorso, come il corpo del messaggio in entrata.

Nel nostro esempio, stiamo usando SIMPLE per inviare al log gli attributi del bean che si trovano all'interno del corpo del messaggio Camel.

Possiamo anche usarlo per fare semplici trasformazioni, come è stato mostrato con il metodo transform () .

6.5. Il processo from () Instrada con ()

Facciamo qualcosa di più significativo, come chiamare un livello di servizio per restituire i dati elaborati. SIMPLE non è pensato per l'elaborazione di dati pesanti, quindi sostituiamo transform () con un metodo process () :

from("direct:remoteService") .routeId("direct-route") .tracing() .log(">>> ${body.id}") .log(">>> ${body.name}") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { MyBean bodyIn = (MyBean) exchange.getIn().getBody(); ExampleServices.example(bodyIn); exchange.getIn().setBody(bodyIn); } }) .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

Questo ci permette di estrarre i dati in un bean, lo stesso precedentemente definito nel metodo type () , e di elaborarlo nel nostro layer ExampleServices .

Poiché in precedenza abbiamo impostato bindingMode () su JSON, la risposta è già in un formato JSON appropriato, generato in base al nostro POJO. Ciò implica che per una classe ExampleServices :

public class ExampleServices { public static void example(MyBean bodyIn) { bodyIn.setName( "Hello, " + bodyIn.getName() ); bodyIn.setId(bodyIn.getId() * 10); } }

La stessa richiesta HTTP viene ora restituita con un codice di risposta 201 e corpo: {"id": 10, "name": "Hello, World"} .

7. Conclusione

Con poche righe di codice siamo riusciti a creare un'applicazione relativamente completa. Tutte le dipendenze vengono create, gestite ed eseguite automaticamente con un unico comando. Inoltre, possiamo creare API che collegano insieme tutti i tipi di tecnologie.

Questo approccio è anche molto compatibile con i contenitori, risultando in un ambiente server molto snello che può essere facilmente replicato su richiesta. Le possibilità di configurazione aggiuntive possono essere facilmente incorporate in un file di configurazione del modello di contenitore.

Questo esempio REST può essere trovato su GitHub.

Infine, oltre alle API filter () , process () , transform () e marshall () , in Camel sono disponibili molti altri modelli di integrazione e manipolazioni dei dati:

  • Modelli di integrazione del cammello
  • Guida per l'utente del cammello
  • Camel SIMPLE Language