Freitag, 29. April 2011

Camel integration trail

Apache Camel ist ein Routing und Mediation Engine. Camel unterstützt eine Vielzahl von Komponenten zur Lösung von Integrationsproblemen. Camel nutzt Domain Specific Languages (DSLs) für die Definition des Nachrichtenflusses und die Transformation von Nachrichten (Typ- und Formattransformationen). Die Architektur von Camel ist modular und erweiterbar. Camel kann als eigenständige, leichtgewichtige Laufzeitumgebung oder in ESB-Umgebungen betrieben werden. Apache Service Mix (ESB und JBI-Container) und die JBoss Enterprise SOA Platform 5.1(beinhaltet ein Camel Gateway als Technical Preview) können als Laufzeitumgebung für Camel dienen. Für andere ESB- und Laufzeitumgebungen wurden spezielle Integrationsszenarion, wie beispielsweise das Deployment des Camel Frameworks, als WAR definiert. Camel ist nicht als eigenständiger Integrationsserver oder ESB designed. Die Einbettung von Camel in  zahlreiche Plattformen (Web, Spring, Java EE, JBI Container, OSGi, etc.) hingegen ist ein primäres Ziel des Camel-Teams.

Documentation of  65 EIPs
Apache Camel basiert auf den von Gregor Hohpe und Bobby Woolf definierten  Enterprise Integration Patterns (EIPs). Die beiden Autoren haben in ihrem Fachbuch: "Enterprise Integration Patterns" die wesentlichen immer wiederkehrenden Integrationsmuster publiziert. Das Buch ist als Lektüre für Integrationsspezialisten empfehlenswert. Die EIPs sind nicht nur für die Lösung von Integrationsproblemen nützlich, sondern definieren ein einheitliches Vokabular für die Kommunikation und Notation von Integrationslösungen.

Apache Camel ist sehr einfach zu nutzen. Das Paradigma Convention over Configuration ist komfortabel für die Integrationsentwickler umgesetzt. Integrationsentwickler können sich sehr gezielt auf die Lösung eines fachlichen Integrationsproblems konzentrieren. Komplexe Konfigurationen und der Aufbau der Integrationsinfrastruktur zur Problemlösung sind nicht mehr durch den Entwickler vorzunehmen.Camel erlaubt die Lösung eines Integrationsproblems im kleinen Rahmen mit der Möglichkeit die gefundene Lösung in der Folge in eine komplexe ESB-Umgebung zu deployen. 

Best Practice: Develop single route and deploy in ESB environment

Camel beinhaltet ein umfangreiches Test-Kit (inklusive Mocks für Endpoints) und unterstützt dadurch die TDD Strategie. Ein Endpoint wird über eine URI definiert und ist mit der URI-Notation parametrierbar.  Zahlreiche Komponenten für gängige Protokolle und Schnittstellen für die Verwendung der gängigen Technologien sind bereits in Camel integriert. Typkonverter, eine einfache Beanschnittstelle, ein ausgefeiltes Fehlerhandling, DSLs (Java, Spring, Scala), Akka-Integration, Transaktionen, ein definiertes Threading-Modell und eine Expression Language sind weitere Highlights von Camel. Rasche Produktivität und zeitnahes Feedback ist bei der Anwendung von Apache Camel deshalb nicht nur ein Versprechen, sondern durch die vielfältigen Funktionalitäten bei gleichzeitiger Leichtgewichtigkeit des Frameworks garantiert.

Szenario Camel Route mit Auditfunktionalität:
Camel route with audit functionality

In dem Szenario werden aus einer Dateiquelle XML- und CSV-Dateien mit Auftragsdaten gelesen, prozessiert und über ein Wire Tap im Rahmen der Auditierung an den Service Manager 2.0 zur Visualisierung gesendet.

Szenario Camel Route Quellcode (Java DSL):

import javax.jms.ConnectionFactory;
import org.apache.activemq.ActiveMQConnectionFactory;
import org.apache.camel.CamelContext;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.builder.RouteBuilder;
import org.apache.camel.component.jms.JmsComponent;
import org.apache.camel.impl.DefaultCamelContext;
import com.service.manager.gateway.api.application.camel.audit.OrderAuditService;
import com.service.manager.gateway.api.application.camel.processor.OrderProcessorService;

public class CamelRouteXmlAndCsvOrders {
  
    public static void main(String args[]) throws Exception {

        final CamelContext context = new DefaultCamelContext();
        final OrderProcessorService processorService = OrderProcessorService.newInstance();
      
        final ConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost");
        context.addComponent("jms", JmsComponent.jmsComponentAutoAcknowledge(connectionFactory));

        context.addRoutes(new RouteBuilder() {

            @Override
            public void configure() {

                from("file:data?noop=true").to("jms:incomingChannel");

                from("jms:incomingChannel").
                    wireTap("jms:serviceManagerAuditChannel").

                        choice().
                            when(header("CamelFileName").endsWith(".xml")).
                                to("jms:xmlDataChannel").
                            when(header("CamelFileName").regex("^.*(csv|csl)$")).                      
                                to("jms:csvDataChannel").
                            otherwise().
                                to("jms:badDataChannel");
              
                from("jms:xmlDataChannel").process(new Processor() {
                  
                    public void process(Exchange exchange) throws Exception {
                  
                        processorService.processXmlData(exchange.getIn().getBody());
                    }                  
                });  
              
                from("jms:csvDataChannel").process(new Processor() {
                  
                    public void process(Exchange exchange) throws Exception {
                  
                        processorService.processCsvData(exchange.getIn().getBody());
                    }
                  
                });  
              
                from("jms:serviceManagerAuditChannel").
                     bean(OrderAuditService.class, "auditOrderMessage");
            }
        });

        context.start();
        Thread.sleep(2000);
        context.stop();
    }
}

Der Aufruf der Methode bean(OrderAuditService.class, "auditOrderMessage") delegiert die Verarbeitung der Audit-Message zu dem Audit-Service. Das Service Activator Pattern ist dabei die Grundlage für den Service-Aufruf. Der Service Activator dient als Mediator zwischen einem Requester und einem Service. Das Service Activator Pattern wird in Java EE Applikationen häufig in Message Driven Beans (MDBs) genutzt. Die Anwendung des Patterns in nicht Messaging-Szenarien ist allerdings ebenso möglich.

Szenario Camel Route Audit Service:

import org.apache.log4j.Logger;
import com.service.manager.api.gateway.annotation.ServiceManagerGateway;
import com.service.manager.api.gateway.context.ServiceManagerGatewayContext;
import com.service.manager.gateway.api.application.camel.helper.DataConverterHelper;

@ServiceManagerGateway(servicePlanId="SERVICEPLAN:12f9d7f03a413639340c8172e32354246e1",
                                        serviceNodeId="SERVICE:12f9d8074be1363e84b43082e32351810c22")
public class OrderAuditService {

    static {
      
        ServiceManagerGatewayContext.newContext(OrderAuditService.class);
    }
  
    private static Logger log = Logger.getLogger(OrderAuditService.class);

    public void auditOrderMessage(final String body) {
      
        final DataConverterHelper dataConverter = DataConverterHelper.newInstance();
      
        if(dataConverter.isXml(body)) {
          
            log.info(dataConverter.convertXmlMessage(body));
        }
        else {
      
            log.info(dataConverter.convertCsvMessage(body));
        }
    }
}

Der Camel Route Audit Service sendet die Audit-Messages über das Service Manager 2.0 Gateway zu der Servicemanagementanwendung zur Visualisierung. Der Service Manager 2.0 eignet sich perfekt für die Anzeige von Audit- und Alarmmeldungen in SOA-Infrastrukturen, die mittels Camel und/oder ESBs betrieben werden.

Visualisation of audit-messages in Service Manager 2.0

Der Service Manager 2.0 erlaubt es, Camel Routing-Schemata abzubilden und über einen eindeutigen Identifier zu verknüpfen, sodass jeder einzelne Schritt im Routing-Prozess tracebar ist. Spezielle Camel Event Notifier zur Übermittlung von Camel Routing und Transformationsdaten können registriert und mit dem Service Manager 2.0 verbunden werden. Alarmfälle, die durch Fehler verursacht werden, sind dabei zeitnah visualisierbar und unterstützen schnelle Reaktionszeiten des Support-Teams zur Einhaltung der Service Level Agreements (SLAs) während der Betriebszeit einer service-orientierten Applikation.


Der Rechtshinweis des Java Blog für Clean Code Developer ist bei der Verwendung und Weiterentwicklung des Quellcodes des Blogeintrages zu beachten.