fb
Nieuws 12 min

Berichttransformatie met WSO2 API Microgateway

Rajith Roshan
Rajith Roshan
Integration Consultant
mailbox blog
Scroll

Berichttransformatie en -bemiddeling is een veelvoorkomende vereiste van bedrijfsintegratieplatforms. De behoefte neemt toe naarmate het integratieplatform groeit en het aantal verschillende systemen waarmee het moet communiceren toeneemt.

In een typisch integratieplatform speelt API-beheer een sleutelrol bij het openstellen van transactie- of streamingdiensten/-data als API’s, terwijl de bedrijfsintegratielaag zorgt voor de onderlinge verbinding van verschillende systemen via berichttransformatie, protocolwisseling enz. Organisaties kunnen verschillende benaderingen kiezen als het gaat om het oplossen van het probleem van berichttransformatie. Sommigen kiezen ervoor om het probleem naar de integratie- of externe laag over te brengen, anderen geven er de voorkeur aan om het in de API-beheerlaag zelf te doen. Beide benaderingen hebben hun voor- en nadelen, afhankelijk van de gebruikssituatie.

In deze blog bekijken we een paar verschillende benaderingen voor het transformeren van berichten met WSO2 API Microgateway en hun voor- en nadelen.

WSO2 API Microgateway is een lichtgewicht, cloud-native API-gateway, die is ontworpen voor de microservices-architectuur. Het heeft de ingebouwde mogelijkheid om berichten via interceptors te transformeren. We zullen kijken naar manieren waarop interceptors kunnen worden gebruikt om de transformatie binnen de API-laag te bereiken, en hoe we de transformatie kunnen overbrengen naar een extern systeem of externe service.

Echo backend-service instellen

Laten we eerst een voorbeeld van een backend-service implementeren. In deze blog gebruik ik een eenvoudige echo Netty-server, die reageert met de payload van de aanvraag. Deze service kan hier worden gedownload[1]. Eenmaal gedownload, kunt u de jar uitvoeren met behulp van de volgende opdracht. Deze zal de Netty-echoservice starten op poort 8688.

java -jar netty-http-echo-service-0.4.5.jar

Probeer de voorbeeldservice uit met het volgende cURL-commando:

curl -k "http://localhost:8688/echo" -X POST -d '{"foo":"val1"}' -i -v -H "Content-Type: application/json"

Microgateway-project instellen

Nu gaan we een open API-schema maken, dat de API definieert die de Netty-service via microgateway openstelt. Deze API heeft één POST-resource met het pad /echo.

---
openapi: 3.0.0
servers:
- url:  "http://localhost:8688"
info:
 description: 'Dit is een voorbeeld-echoservice.'
 version: 1.0.0
 title: Echo_XML_Service
x-wso2-basePath: /transform
x-wso2-disable-security: true
paths:
 "/echo":
 post:
 summary: echoot de reactie.
 operationId: echoMethod
 responses:
        '200':
 description:  operatie geslaagd
 content:
 application/xml:{}
 application/json:{}
        '400':
 description: Ongeldige statuswaarde

Hier gebruiken we voor het gemak de extensie “x-wso2-disable-security”, omdat we met deze eigenschap de API kunnen aanroepen via microgateway zonder een veilig token.

Download vervolgens de nieuwste microgateway toolkit en runtime-versies (3.2.X) vanaf de locatie[2] en volg de instructies[3] om ze in te stellen.

Nu kunnen we het Microgateway-project initialiseren met de volgende opdracht met behulp van de toolkit. Hier is de gebruikte projectnaam “transform”

micro-gw init transform

Kopieer vervolgens het geopende API-bestand naar de map “api_definitions” in het project “transform”.

Laten we vervolgens het project bouwen en het runtime-artefact maken.

micro-gw build transform

Ten slotte kunnen we het build runtime-artefact uitvoeren met behulp van de microgateway runtime (binair) met de volgende opdracht.

./gateway <PAD_NAAR_DE_BUILD_JAR>

Nu hebben we de API zonder enige transformatie opengesteld, en deze kan worden aangeroepen met behulp van onderstaande opdracht via microgateway. Hiermee wordt dezelfde json-payload teruggegeven die we in de aanvraag van de Netty-backend hebben verzonden.

curl -k "https://localhost:9095/transform/echo" -X POST -d '{"foo":"val1"}' -i -v -H "Content-Type: application/json"

Laten we nu aannemen dat de backend Netty-service de payload in xml-formaat verwacht en dat de client de aanvraag met json-payloads verzendt. Er moet dus transformatielogica zijn die json naar xml converteert voordat het naar de backend wordt verzonden. We bekijken hoe we dit kunnen bereiken in drie verschillende benaderingen met behulp van API Microgateway.

1.   Transformeren binnen de gateway met behulp van ballerina-interceptors

We kunnen de json-naar-xml transformatie binnen de gateway schrijven met behulp van een ballerina-interceptor. Wat hier gebeurt, is dat we tijdens de aanvraagstroom aangepaste ballerinacode gebruiken om de transformatie uit te voeren.

Laten we eerst de ballerinacode schrijven die json naar xml transformeert. De ballerinavoorbeelden voor versie 1.2.x, de ondersteunde ballerina-versie in microgateway 3.2.x, zijn hier te vinden [4]. Laten we een bestand maken met de naam json_naar_xml.bal (elke gewenste naam kan worden gebruikt) en de volgende inhoud erin plaatsen.

import ballerina/http;
import ballerina/xmlutils;
import ballerina/log;

public function jsonToXML (http:Caller outboundEp, http:Request req) {
 json payload = checkpanic req.getJsonPayload();
 xml|error x1 = xmlutils:fromJSON(payload);
 if (x1 is xml) {
 req.setXmlPayload(x1);
 } else {
 log:printError("Fout bij converteren van json naar xml", x1);
    }
}

Hier kan de functienaam elke gewenste naam zijn, maar deze moet de parameters “http:Caller” en “http:Request” accepteren als de invoerparameters voor de functie, zodat die door de gateway als interceptorfunctie wordt opgepikt.

Kopieer nu het bestand json_naar_xml.bal in de map interceptors naar het “transform” project dat u eerder hebt gemaakt.

Laten we vervolgens de interceptor in de specifieke API declareren, door deze toe te voegen aan de open API met behulp van de open API-extensie “x-wso2-request-interceptors”. De functienaam moet worden opgegeven als de waarde voor de open API-extensie. Pas de open API aan, zoals hieronder getoond. (Rood gekleurde tekst toont de toegevoegde open API-extensie)

paths:
 "/echo":
 post:
 summary: echoot de reactie.
 operationId: echoMethod
 x-wso2-request-interceptor: "jsonToXML"

Laten we tot slot het project bouwen en het bouwartefact uitvoeren zoals eerder gedaan. Als we nu de API met hetzelfde curl-commando aanroepen, kunnen we zien dat we het antwoord in xml-formaat ontvangen. Wat hier gebeurt, is dat microgateway de json-payload naar xml transformeert voordat deze naar de backend wordt verzonden en dat de Netty-service zoals gewoonlijk de payload terug echoot.

Dat was best makkelijk, of niet?

Maar het belangrijkste probleem met deze benadering van het uitvoeren van zware transformatielogica bij de gateway, vooral wanneer die gateway in gedeelde modus wordt gebruikt om meerdere API’s open te stellen, is dat het zware gebruik van bronnen door één API de prestaties van alle andere API’s kan verminderen. En wanneer kleine of grote versie-upgrades van microgateway worden uitgevoerd, moet de ballerinacode voor alle API’s worden bijgewerkt om overeen te komen met de ballerinaversie die door die specifieke microgateway wordt ondersteund. Dit kan een onderhoudsnachtmerrie zijn. Leverancier-specifieke technologie lock-in is hier ook een punt van zorg.

2.   Transformeren binnen de gateway met behulp van java-interceptors

Net als bij ballerina-interceptors, kan de transformatielogica in java worden ontwikkeld en binnen de gateway zelf worden uitgevoerd. De java-code wordt geactiveerd tijdens de aanvraagstroom binnen de gateway, vergelijkbaar met ballerina-interceptors.

Maak eerst een java maven-project aan en implementeer de java-interface “org.wso2.micro.gateway.interceptor.Interceptor”, die de json-naar-xml conversie implementeert (JsonToXML.java class).

pom.xml

<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.example</groupId> <artifactId>json-to-xml-transform</artifactId> <version>1.0-SNAPSHOT</version> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>org.wso2.am.microgw</groupId> <artifactId>mgw-interceptor</artifactId> <version>3.2.0</version> </dependency> </dependencies> </project>

JsonToXML.java

package org.mgw.transform; import org.json.JSONObject; import org.json.XML; import org.wso2.micro.gateway.interceptor.Caller; import org.wso2.micro.gateway.interceptor.Interceptor; import org.wso2.micro.gateway.interceptor.InterceptorException; import org.wso2.micro.gateway.interceptor.Request; import org.wso2.micro.gateway.interceptor.Response; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.nio.charset.StandardCharsets; public class JsonToXML implements Interceptor { private static final Logger log = LoggerFactory.getLogger("ballerina"); public boolean interceptRequest(Caller caller, Request request) { try { JSONObject payload = request.getJsonPayload(); String xml = XML.toString(payload); request.setBinaryPayload(xml.getBytes(StandardCharsets.UTF_8)); request.setContentType("application/xml"); } catch (InterceptorException e) { log.error("Error while getting json payload from request", e); } return true; } public boolean interceptResponse(Caller caller, Response response) { return true; } }

Bouw het maven-project met “mvn clean install” en kopieer de build-jar naar de map lib van het “transform” project.

Bewerk vervolgens het open API-bestand van het transformatieproject om de java-interceptorklasse op te geven in plaats van de functienaam van de ballerina. De extensiewaarde moet de indeling “java:<Full_Qualified _Class_Name>” hebben (zie de roodgekleurde tekst in het onderstaande voorbeeld).

paths:  "/echo":  post:  summary: echoot de reactie.  operationId: echoMethod  x-wso2-request-interceptor: java:org.mgw.transform.JsonToXML  

Bouw ten slotte het project en voer het build-artefact uit met behulp van de gateway-runtime zoals eerder gedaan. Wanneer u de json-aanvraagbody met het cURL-commando verzendt, zal het nu ook met de xml-payload antwoorden.

Net als bij de ballerina-interceptors is de zorg bij deze aanpak het uitvoeren van zware transformatielogica bij de gateway wanneer die in de gedeelde modus wordt gebruikt (meerdere API’s openstellen). Een probleem met één API kan van invloed zijn op alle andere API’s. De thread voor de verwerking van aanvragen kan veel verwerkingstijd in beslag nemen voor de transformatie, waardoor de thread bezig blijft en API-aanvragen niet worden afgehandeld.

Ook moet rekening worden gehouden met de verwerking van transformatielogica bij het schalen van de gateways. Dit kan abnormaal schaalgedrag veroorzaken bij implementatie op platforms die automatisch schalen bieden, zoals Kubernetes.

3.   De transformatielogica extern maken

Bij deze aanpak richten we ons op het uitvoeren van de transformatielogica via een externe service. Dit kan elke gewenste externe service zijn, zoals Spring, Netty, CXF op tomcat of een enterprise integrator die is ontworpen voor dit soort transformaties.

In deze blog gebruik ik WSO2 Micro Integrator (4.0.0), een enterprise integrator die specifiek is ontworpen voor transformaties, bemiddeling en andere integratievereisten.

Download de micro-integrator MI 4.0.0 en integratiestudio (low-code tool om integraties te ontwikkelen)[5].

micro integrator
micro integrator

Laten we in de ontwikkelaarsstudio een eenvoudige proxyservice ontwikkelen, die json naar xml zal transformeren. Documentatie over hoe u een proxyservice kunt maken met behulp van de integratiestudio en deze kunt implementeren in micro-integrator vindt u hier[6].

Hier vindt u de voorbeeld configuratie van de proxyservice en de reeks instructies die met de integratiestudio is gemaakt om de json-naar-xml conversie uit te voeren.

Proxyservice

<?xml version="1.0" encoding="UTF-8"?>
<proxy name="jsontoxml" startOnLoad="true" transports="http https" xmlns="http://ws.apache.org/ns/synapse">
 <target inSequence="convert_json_to_xml">
 <outSequence />
 <faultSequence/>
 </target>
</proxy>

In Sequence

<?xml version="1.0" encoding="UTF-8"?>
<sequence name="convert_json_to_xml" trace="disable" xmlns="http://ws.apache.org/ns/synapse">
 <log level="full"/>
 <property name="messageType" scope="axis2" type="STRING" value="application/xml"/>
 <enrich>
 < source clone="false" xpath="$body/jsonObject/*"/>
 <target type="body"/>
 </enrich>
 <respond/>
</sequence>

Hier kan de json naar xml-conversie eenvoudig worden bereikt door de eigenschap messgeType in te stellen op “application/xml“. WSO2 MI bevat de geconverteerde xml in de bovenliggende xml-tag <jsonObject>. Enrich mediator wordt gebruikt om die bovenliggende xml-tag te verwijderen.

Zodra de artefacten klaar zijn, maakt u het CAR-bestand met behulp van integratiestudio en implementeert u het CAR-bestand in de micro-integrator. Eenmaal geïmplementeerd, kan de proxyservice worden aangeroepen met elke gewenste json-payload, waarna deze zal reageren met een antwoord in het geconverteerde xml-formaat.

curl -k "https://localhost:8253/services/jsontoxml" -X POST -d '{"foo":"val1"}' -i -v -H "Content-Type: application/json"

Nu onze transformatielogica op een externe server draait, gaan we gewoon een ballerinacode schrijven om dit externe eindpunt aan te roepen en de logica in te schakelen als een ballerina-interceptor, vergelijkbaar met die in benadering 1.

Hieronder vindt u een codefragment van een ballerina-interceptor die de externe proxyservice aanroept die op de micro-integrator draait.

import ballerina/http;
import ballerina/log;

http:Client clientEP = new ("http://localhost:8290/services/jsontoxml");

public function callMI (http:Caller outboundEp, http:Request req) {
 http:Response|error resp = clientEP->forward("/", req);
 if (resp is http:Response) {
 xml|error x1 = resp.getXmlPayload();
 if (x1 is xml) {
 req.setXmlPayload(validate(x1));
 } else {
 log:printError("Fout bij het ophalen van de xml-payload van externe transformatieservice", x1);
        }
    }
}

function validate(xml input) returns @untainted xml {
 return input;
}

Volgens deze logica stuurt microgateway de aanvraag door naar de micro-integrator proxyservice, die draait op “localhost:8290/services/jsontoxml”. Deze aanroep gebeurt op een niet-blokkerende manier, waarbij de aanvraag-thread wordt vrijgegeven zodra de aanroep naar het externe eindpunt is gedaan.

Laten we, net als bij benadering 1, deze interceptor definiëren in de open API-definitie, zodat deze als een ballerina-interceptor zal werken.

paths:  "/echo":  post:  summary: echoot de reactie.  operationId: echoMethod  x-wso2-request-interceptor: "callMI"  

Tot slot bouwen we het microgateway-project en voeren we het uit met behulp van de microgateway runtime.

Wanneer het wordt aangeroepen met een json-payload met behulp van cURL, zal het reageren met een xml-payload (de geconverteerde json-payload).

Deze aanpak is meer geschikt voor een architectuur die uitgebreide berichttransformaties vereist. De prestaties van de gateway en alle andere API’s die door de gateway worden opengesteld blijven constant, omdat de transformatielogica geen gateway CPU-cycli nodig heeft. De architectuur is meer toekomstbestendig, omdat deze de flexibiliteit biedt om de implementatie van de transformatielogica zelf te onderhouden en u niet gebonden bent aan een bepaalde leverancier of technologie. Als de organisatie besluit om een grote upgrade van de API gateway-laag uit te voeren, of van de ene leverancier naar een andere overstapt, kan de bestaande transformatielogica nog steeds worden gebruikt.

Conclusie

In deze blog heb ik geprobeerd een eenvoudige transformatievereiste zoals json naar xml-conversie als voorbeeld te gebruiken om de voor- en nadelen te bespreken van drie verschillende architectuurpatronen die vaak worden gebruikt met WSO2 Microgateway. Ik hoop dat dit artikel u zal helpen de meest geschikte en toekomstbestendige aanpak te bepalen die het best past bij de eisen van uw organisatie.

[1] – https://search.maven.org/artifact/org.wso2.performance.common/netty-http-echo-service/0.4.5/jar

[2] – https://wso2.com/api-manager/api-microgateway/

[3] – https://mg.docs.wso2.com/en/latest/install-and-setup/install-on-vm/

[4] – https://ballerina.io/1.2/learn/by-example/

[5] – https://wso2.com/integration/micro-integrator/

[6] – https://ei.docs.wso2.com/en/7.2.0/micro-integrator/develop/creating-artifacts/creating-a-proxy-service/