Gehversuche mit Mule

12 Juli, 2009 - 19:26

Die Integration unterschiedlicher Softwaresysteme in einer heterogenen Systemlandschaft ist bis heute für viele IT-Architekten eine der anspruchsvollsten Aufgaben, sowohl aus technischer als auch aus betriebswirtschaftlicher Sicht. In der Vergangenheit wurden daher viele unterschiedliche Integrationslösungen entwickelt, die sich mehr oder weniger gut in der Praxis bewährt haben. Das unermüdliche Streben nach einer idealen Lösung, um der steigenden Komplexität gerecht zu werden, hat uns heute letztendlich neben dem SOA Paradigma den Enterprise Service Bus (ESB) beschert.

Was ist ein ESB?

Ein ESB ist eine standardisierte Integrationsplattform für verteilte Systeme, welche unterschiedlichen Diensten (engl. Services) erlaubt, mit Hilfe von definierten End-Punkten, über einen Kommunikationsbus Nachrichten (engl. Messages) auszutauschen.

Zu den wichtigsten Aufgaben eines ESB gehören:

  • Das Routing von Nachrichten
  • Das Transformieren von Nachrichten
  • Das Bereitstellen von unterschiedlichen Protokollen (Technologien)
  • Sicherstellung von Quality of Service
  • Die Unterstützung von unterschiedlichen Enterprise Integration Pattern (EIP)


Man findet heute bei fast allen großen Software Unternehmen, die Systemintegrationslösungen anbieten, kommerzielle ESB Produkte im Portfolio wie z.B. Oracle ESB, Sonic ESB, IBM WebSphere ESB. Es existieren aber auch eine Vielzahl von Open-Source-Produkten wie Mule, Apache Service Mix oder Open ESB. Das Mule Projekt kann mittlerweile mehr als 1 Millionen Downloads verzeichnen und hat sicherlich damit ein besonderes Augenmerk verdient.

Der Open-Source ESB Mule

Mule ist ein Java basierter Open-Souce ESB, der sich einer immer größer werdenden Beliebtheit erfreut und sich in der Praxis sehr bewährt hat. Mule steht unter der Common Public Attribution License (CPAL) und wird von der stetig größer werdenden Community permanent weiterentwickelt, was ein wichtiger Faktor bei der Wahl bzw. für die Entscheidung eines Open-Source Produktes ist.

Eine gute Kurzbeschreibung von Mule ist auf der Internetseite  „www.mulesource.org“ zu finden:

Mule is a lightweight integration platform and service container that allows you to quickly and easily connect your applications together. Mule provides a robust, secure and scalable platform to build enterprise applications offering an array of transports such as JMS, HTTP, E-mail, FTP, JDBC and many more. It also offers rich set of features for web services, message routing, mediation, transformation and transaction management. Designed around the ESB (Enterprise Service Bus) concpet, Mule ist the most widely used open source integration platform.

Mule ist insofern leichtgewichtig, dass seit der Verion 2.0 die Mule Plattform komplett auf dem Spring Framework basiert. Dies erleichtert einerseits die Einarbeitung für all diejenigen, die sich bereits mit Spring auskennen und erlaubt gleichzeitig alle Servicekomponenten in Mule als Plain Old Java Objects (POJO's) zu implementieren. Mule kann damit ohne einen Enterprise Application Server betrieben und ohne größere Aufwände in bestehende Software-Architekturen integriert werden.

Mule Architektur und Programmiermodell

Da die Mule Plattform auf dem SOA Konzept basiert, ist es nicht verwunderlich, dass Services eine zentrale Rolle im Mule Framework spielen. Interne und externe Service-Komponenten tauschen über Message Channels Informationen aus. Diese Services werden in Mule wiederum zu einem Modul zusammengefasst. Wie bei vielen anderen ESBs geschieht der Nachrichtenaustausch über einen JMS Message Broker. Mule gibt dabei aber selbst keine Implementierung vor. Stattdessen können unterschiedliche JMS Systeme wie beispielsweise Apache Active MQ, IBM MQSeries oder Oracle EMS integriert werden. Bei den Nachrichten, die über die Channels ausgetauscht werden, muss es sich aber nicht zwingend um XML-Dokumente handeln. So können beispielsweise auch beliebige Java Objekte transportiert werden.

Ein Service besteht in Mule aus der Service-Komponente, welche die Businesslogik für die Datenverarbeitung beinhaltet, und ihren Endpunkten (Adressen und Protokoll). Die Service-Komponente kann dabei ein einfaches POJO sein aber auch ein Servlet oder ein Web Service. Das Programmiermodell von Mule ist sehr einfach und sieht drei Phasen vor:

  1. Inbound Flow Stage
  2. Componente Flow Stage
  3. Outbound Flow Stage

Im Inbound Flow Stage werden mehrere Eingangs-Endpunkte (Einstiegsmöglichkeiten) für die Service-Komponente defieniert. So kann beispielsweise eine Service-Komponente bei einer eingehenden JMS Message, E-Mail oder das Kopieren einer XML-Datei in ein Verzeichnis gestartet werden. Wie bereits erwähnt sind mehrere Einstiegspunkte für eine Service-Komponente denkbar. Im Inbound Flow Stage lassen sich nun auch sogenannte Message Router und Transformer definieren, die z.B. im Vorfeld bestimmte Nachrichten ausfiltern (Filtering-Router) und transformieren.

Der Component Flow Stage führt nun die eigentliche Businesslogik durch und gibt das Ergebnis der Komponente an den optionalen Outbound Flow Stage weiter.

Im Outbound Flow Stage können ebenfalls mehrere Endpunkte definiert werden. Durch entsprechende Router und Transformer kann die Ausgangsnachricht nochmals manipuliert und durch die gewünschten Endpunkte verschickt werden (siehe Abb. 1).

Mule unterstützt von Haus aus eine ganze Palette von Protokollen, Routern, Filtern und Transformatoren, so dass sich der Implementierungsaufwand nahezu auf die Businesslogik in den Service-Komponenten und das Schreiben von eigenen Transformatoren beschränkt.

Service Komponente in Mule

Beispielanwendung: Hello ESB

Traditionell wollen wir mit einem Hello ESB Beispiel beginnen, wozu folgendes benötigt wird:

  • Maven 2.0.9
  • Mule 2.2.1
  • Apache Active MQ 5.2
  • Ein Jabber Client (z.B. Pidgin, Spark)
  • und ein Jabber Account (http://jabber.org)
  • Optional eine Java IDE (Eclipse Platform, Jetbrains IDEA)

Mule selbst muss nicht heruntergeladen und installiert werden, dies übernimmt Maven für uns. Wer sich nicht mit Maven auskennt, findet eine kurze Einführung in unserem Einstiegstutorial zu Maven. Der Beispielcode ist als Zip-Archive hier zu finden. Nachdem wir den Beispielcode entpackt haben, finden wir im Root-Verzeichnis eine „pom.xml“ File (Konfigurationsdatei für Maven) und ein „src“ Verzeichnis, in dem sich die Mule Konfigurationsdatei und die restlichen Java Sourcen befinden.

  • MuleHelloESBTutorial
    • src
      • main
        • java
          • com
            • soabpmn
              • tutorial
                • mule
                  • service
                    • impl
                      • SendMessageImpl.java
                    • MessageType.java
                    • SendMessage.java
                  • transformer
                    • InputMessageTransformer.java
                    • MessagingSystemTransformer.java
                  • xmpp
                    • MessagingComponent.java
                  • StartHelloESB.java
        • resources
          • hello-esb-config.xml
          • hello-esb-config.xml~
          • log4j.properties
    • pom.xml

Um unsere Hello ESB Anwendung zu kompilieren, reicht es, im Root-Verzeichnis Maven zu starten:

mvn

Maven kompiliert damit den Source-Code und läd alle benötigten Bibliotheken automatisch aus dem Internet und kopiert diese ins Maven Repository (per defautl: userhomer/.m2).

Um die Arbeit mit unserer Beispielanwendung etwas komfortabler zu gestalten, wollen wir nun unsere Anwendung in einer Java IDE öffnen. Auch hier nimmt uns Maven die Arbeit ab. Je nachdem ob wir nun Eclipse oder IDEA verwenden, können wir uns mit Maven ein Projektfile für unsere IDE erzeugen lassen.

mvn idea:idea

oder

mvn eclipse:eclipse

Das von Maven erzeugte Projektfile können wir jetzt in unserer IDE öffnen. Falls Eclipse verwendet wird, muss unter Preferences/Java/Build Path/Classpath Variables/ eine Umgebungsvariable mit dem Namen „M2_REPO“, welche auf das Maven Repository (userhome/.m2/repository) verweist, angelegt werden.

Bevor wir nun unsere Beispielanwendung starten können, muss zuerst noch Active MQ gestartet werden. Dazu muss lediglich im „bin“ Verzeichnis von Active MQ das Startskript ausgeführt werden:

apache-activemq-5.2.0/bin$ ./activemq

Um die Beispielanwendung letztendlich zu starten, führen wir die Main-Methode in com.soabpmn.tutorial.mule.StartHelloESB aus.

Was macht nun unsere Hello ESB Anwendung?

Unsere Beispielanwendung soll einen Service zum Verschicken von Nachrichten realisieren. Dazu soll ein Web Service bereitgestellt werden, welcher die zu versendenden Nachrichten entgegennimmt. Anschließend soll anhand des Nachrichtentyps entschieden werden, ob die Nachricht lediglich auf der Konsole ausgegeben werden soll oder an einen XMPP (Jabber) Client verschickt wird.

Die Anwendung definiert dazu zwei Mule Services: SendMessage und JabberSystem.

Der „SendMessage“ Service stellt mit Hilfe des Apache CXF Framework einen Webservice bereit, der die Eingangsnachricht entgegennimmt. Anschließend wird über einen Filter-Router anhand des Nachrichtentyps entschieden, ob die Nachricht auf der Konsole ausgegeben oder in eine JMS Message-Queue „xmppMessageQueue“ abgelegt wird.

Der „JabberSystem“ Service wartet darauf, dass Nachrichten in die JMS Message-Queue „xmppMessageQueue“ eingehen. Liegt eine Nachricht in der Queue vor, wird zunächst von der Service-Komponente der XMPP Empfänger der Nachricht ermittelt. Ein Transformator extrahiert anschließend den eigentlichen Nachrichtentext, bevor die Nachricht letztendlich über den Mule XMPP Transporter verschickt wird.

Hier die Mule Konfiguration:

    <!-- ActiveMQ message broker -->
    <jms:activemq-connector name="activeMqJmsConnector" brokerURL="tcp://localhost:61616" />
        
    <!-- Transformers -->    
    <jms:jmsmessage-to-object-transformer  name="JMSMessageToObject"/>
    <jms:object-to-jmsmessage-transformer name="ObjectToJMSMessage"/>
    <custom-transformer name="InputMessageTransformer" class="com.soabpmn.tutorial.mule.transformer.InputMessageTransformer"/>
    <custom-transformer name="JabberTransformer" class="org.mule.transport.xmpp.transformers.ObjectToXmppPacket"/>
    <custom-transformer name="MessagingSystemTransformer" class="com.soabpmn.tutorial.mule.transformer.MessagingSystemTransformer" />
        
    
    <!-- Global endpoints  -->
    <jms:endpoint name="statusTopic" topic="flight.status"/>
    <jms:endpoint name="xmppMessageQueue" queue="xmppMessageQueue"/>


    <model name="HelloESB">

        <service name="SendMessage">
            <inbound>
                <cxf:inbound-endpoint address="http://localhost:65082/services/SendMessage" />
            </inbound>
            
            <component>
                <singleton-object class="com.soabpmn.tutorial.mule.service.impl.SendMessageImpl" />
            </component>
            
            <outbound>
                <filtering-router transformer-refs="InputMessageTransformer">
                    <jms:outbound-endpoint ref="xmppMessageQueue" transformer-refs="ObjectToJMSMessage"/>
                    <message-property-filter pattern="messageType=xmpp"/>
                </filtering-router>

                <filtering-router transformer-refs="InputMessageTransformer">
                    <stdio:outbound-endpoint system="OUT" transformer-refs="MessagingSystemTransformer" />
                    <message-property-filter pattern="messageType=stdio"/>
                </filtering-router>
            </outbound>
        </service>

        <service name="JabberSystem">
            <inbound>
                <jms:inbound-endpoint ref="xmppMessageQueue"/>
                <vm:inbound-endpoint path="jabberSystem"/>
            </inbound>
            
            <component class="com.soabpmn.tutorial.mule.xmpp.MessagingComponent"/>
            
            <outbound >
                <pass-through-router>
                    <xmpp:outbound-endpoint host="jabber.com"
                                            recipient=""
                                            user="AUser" password="ThePassword" port="5222"
                                            transformer-refs="MessagingSystemTransformer JabberTransformer"/>
                </pass-through-router>
            </outbound>
        </service>      

Um unsere Beispielanwendung zu testen, benötigen wir einen Webservice Client wie beispielsweise soapUI. SoapUI ist ein Webservice Testing Tool, das sowohl standalone als auch in Eclipse integriert werden kann. Nachdem wir unsere Beispielanwendung gestartet haben, sollten wir unter http://localhost:65082/services/SendMessage?wsdl unseren Webservice finden. Um den Service mit soapUI zu testen legen wir ein neues soapUI Projekt an und geben dort die Service-Adresse ein.

New soapUI Project

SoapUI erzeugt nun für uns eine Request-Message, in der wir unsere Service-Parameter eingeben und anschließend unsere Nachricht verschicken können.

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ser="http://service.mule.tutorial.soabpmn.com/">
   <soapenv:Header/>
   <soapenv:Body>
      <ser:sendMessage>
         <!--Optional:-->
         <message>HelloESB</message>
         <!--Optional:-->
         <recipient>user@jabber.com</recipient>
         <!--Optional:-->
         <messageType>xmpp</messageType>
      </ser:sendMessage>
   </soapenv:Body>
</soapenv:Envelope>

Wenn wir nun nirgendwo gestolpert sind, sollte unser Jabber Client uns mit „HelloESB“ begrüßen.

AnhangGröße
MuleHelloESBTutorial.zip10.79 KB