Wstęp do integracji systemów w oparciu o Mule ESB (część 2)

Paweł Pietrasz, 9 kwietnia 2018

W poprzednim wpisie omówiłem czym jest integracja oraz przedstawiłem jeden z realnych scenariuszy, który możemy napotkać podczas wdrażania ESB w przedsiębiorstwie. W ramach tego wpisu omówimy krok po kroku na przykładzie Mule ESB realizację tego, co było omówione w poprzednim wpisie. Celem tego wpisu jest przedstawienie i omówienie realizacji usług na Mule w oparciu o trójwarstwową architekturę, którą omówiliśmy w poprzednim wpisie.

sap-channel

Pierwsza aplikacja kanałowa sap-channel, jak wcześniej wspomniałem jest to stary interfejs oparty o SOAP, ponieważ takie było wymaganie projektu — zachowanie SOAP API dla systemu SAP.

To co istotne dla nas to model danych zdefiniowany w pliku WSDL:

<wsdl:types>
<xsd:schema targetNamespace="http://Example.org" elementFormDefault="qualified" >
<xsd:element name="GetAccount">
<xsd:complexType>
  <xsd:sequence>
    <xsd:element minOccurs="0" name="account_id" type="xsd:string" />
  </xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="GetAccountResponse">
<xsd:complexType>
  <xsd:sequence>
    <xsd:element minOccurs="0" name="account_id" type="xsd:string" />
    <xsd:element minOccurs="0" name="account_name" type="xsd:string" />
    <xsd:element minOccurs="0" name="account_phone" type="xsd:string" />
  </xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</wsdl:types>

Model ten różni się od naszego kanonicznego konwencją nazewniczą oraz tym, że jest oparty o XML. Zgodnie z diagramem, istotnym punktem w implementacji naszej warstwy kanałowej będzie nie tylko wywołanie usługi na warstwie business ale także poprawny mapping odpowiedzi.

Rysunek 1.

Powyższy screen prezentuje realizację w Mule ESB przepływu dla sap-channel. Poniżej omówimy najważniejsze jego części:

Api-main to przepływ odpowiedzialny za publikację interfejsu SOAP opartego o plik WSDL. To co istotne, to komponent SOAP Router odpowiedzialny za przekierowywanie w zależności od wywołanej operacji na właściwy przepływ z implementacją. W naszym przypadku jest to operacja GetAccount zdefiniowana poniżej:

<wsdl:message name="IAccount_GetAccount_InputMessage">
	<wsdl:part name="parameters" element="tns:GetAccount" />
  </wsdl:message>
  <wsdl:message name="IAccount_GetAccount_OutputMessage">
	<wsdl:part name="parameters" element="tns:GetAccountResponse" />
  </wsdl:message>

  <wsdl:portType name="IAccount">
	<wsdl:operation name="GetAccount">
  	<wsdl:input wsaw:Action="http://Example.org/IAccount/GetAccount" message="tns:IAccount_GetAccount_InputMessage" />
  	<wsdl:output wsaw:Action="http://Example.org/IAccount/GetAccountResponse" message="tns:IAccount_GetAccount_OutputMessage" />
	</wsdl:operation>
  </wsdl:portType>

  <wsdl:binding name="DefaultBinding_IAccount" type="tns:IAccount">
	<soap:binding transport="http://schemas.xmlsoap.org/soap/http" />
	<wsdl:operation name="GetAccount">
  	<soap:operation soapAction="http://Example.org/IAccount/GetAccount" style="document" />
  	<wsdl:input>
    	<soap:body use="literal" />
  	</wsdl:input>
  	<wsdl:output>
    	<soap:body use="literal" />
  	</wsdl:output>
	</wsdl:operation>

  </wsdl:binding>
  <wsdl:service name="AccountService">
    	<wsdl:port name="IAccount" binding="tns:DefaultBinding_IAccount">
        	<soap:address location="http://Example.org/IAccount" />
    	</wsdl:port>
  </wsdl:service>

W samej uproszczonej implementacji mamy 3 kroki:

set account id — odpowiada za przypisanie do payload-u komunikatu wartości account_id. Krok realizowany za pomocą Data Weave.

Rysunek 2.

/account — wywołanie REST-owej usługi w ramach aplikacji business-account.

Rysunek 3.

Response-mapping — transformacja odpowiedzi z business-account do XML zgodnego z WSDL.

Rysunek 4.

webapp-channel

Druga aplikacja webapp będzie korzystać z naszego nowego API REST opartego o kanoniczny model w JSON-ie.

Usługi zostały zdefiniowane w ramach pliku RAML i opublikowane w ramach aplikacji webapp-channel. Poniżej jej uproszczona definicja a także realizacja w ramach Mule ESB.

#%RAML 1.0
title: Webapp API

types:
  Account:
    type: object
    properties:
      name: string
      phone:  string
      id: string

/account/{id}:
  get:
    responses:
      200:
        body:
          application/json:
            type: Account

Rysunek 5.

Analogicznie jak w przypadku aplikacji sap-channel mamy HTTP input odpowiedzialny za wystawienie usługi GET /account/{id} oraz APIkit za właściwy routing na przepływ realizujący implementację. W naszym scenariuszu zakładamy, że webapp operuje na modelu kanonicznym w JSON, gdzie nie ma potrzeby wykonywania mappingu pomiędzy modelami stąd implementacja polegająca na wywołaniu operacji GET /account{id} z aplikacji business-account bez mapowania zwrotnego.

business-account

Aplikacja business-account zgodnie z założeniami ma wystawiać kanoniczny interfejs oraz realizować jedynie orkiestrację usług.

Rysunek 6.

Aplikacja odbiera HTTP GET, wykonuje wywołanie usługi pobrania danych o koncie z systemu salesforce za pomocą aplikacji salesforce-adapter. Następnie w ramach kroku “check status” sprawdzamy czy dane o koncie zostały zwrócone. Jeśli tak, zwracamy odpowiedź, w przeciwnym razie pobieramy dane o koncie z systemu bazodanowego.

Rysunek 7.

salesforce-adapter

Pierwsza z dwóch aplikacji odpowiedzialnych za integrację z systemami domenowymi. Zadaniem tej aplikacji jest odebranie operacji HTTP GET z warstwy business, zbudowanie requestu wyjściowego do systemu Salesforce oraz przetworzenie odpowiedzi do modelu kanonicznego w JSON.

Rysunek 8.

Pierwszym ważnym krokiem w przepływie jest wykonanie operacji SELECT w systemie Salesforce. Realizujemy to za pomocą wbudowanego konektora. Dzięki wbudowanemu mechanizmowi DataSense pobieramy metadane obiektów z Salesforce na których będziemy pracować. Pobranie tych danych daje nam możliwość budowania zapytań za pomocą narzędzia Query Builder oraz możliwość łatwego mapowania w kroku “map to json” ponieważ mamy zaimportowany model danych obiektu zwrotnego z Salesforce.

Rysunek 9.

Następny krok to weryfikacja czy Salesforce zwrócił odpowiedź. W przypadku pobrania danych, dokonujemy mapowania z obiektu Account zwracanego przez Salesforce do odpowiedzi kanonicznej w JSON.

Rysunek 10.

W przeciwnym razie, za pomocą komponentu Groovy możemy wygenerować wyjątek, który spowoduje nam zwrócenie HTTP 404 Resource not found.

throw new org.mule.module.apikit.exception.NotFoundException()

Wygenerowanie tego wyjątku spowoduje zwrócenie do business-account statusu 404 na bazie którego przepływ zdecyduje o wywołaniu dodatkowo aplikacji database-adapter.

database-adapter

Druga z dwóch aplikacji domenowych. Jej zadanie jest identyczne jak w salesforce-adapter. Aplikacja ma na bazie przekazanego id pobrać z bazy danych informacje o koncie oraz wygenerować odpowiedź w modelu kanonicznym w JSON.

Rysunek 11.

Podobnie jak w przypadku Salesforce, tak tu mamy możliwość skorzystać z wbudowanego konektora, który wykorzystuje DataSeanse w celu pobrania modelu danych.

Rysunek 12. Rysunek 13.

Omówiliśmy jeden z bardzo typowych scenariuszy integracyjnych, z którymi można spotkać się na projekcie wdrożenia ESB. W modelowym wdrożeniu interfejs usług publikowanych na ESB byłby przedstawiony systemom klienckim (konsumentom API) podczas etapu analizy i cała późniejsza realizacja byłaby skupiona na implementacji katalogu usług oraz integracji Mule z systemami domenowymi. Takie projekty się zdarzają, sam miałem przyjemność brać udział w dwóch takich, jednak większość decyzji o wdrożeniu warstwy integracyjnej zapada w realiach, w których systemy w przedsiębiorstwie istnieją od wielu lat i ESB ma za zadanie pewne rzeczy poprawić, inne uporządkować, wprowadzić pewną przewidywalność w projektowaniu przyszłych zmian i funkcjonalności. W takich warunkach nie jesteśmy wstanie zrobić modelowego wdrożenia omawianego często na konferencjach, ale możemy za pomocą ESB znacznie uporządkować rzeczywistość, z jaką zmagają się osoby odpowiedzialne za rozwój IT w przedsiębiorstwie.

Wszystkie posty z tego cyklu:

  1. Wstęp do integracji systemów w oparciu o Mule ESB
  2. Wstęp do integracji systemów w oparciu o Mule ESB (część 2)

Tematy: integracjamule esb
Napisano w: Technologie
Zapisz się przez RSS
comments powered by Disqus