Vernieuw moeiteloos verouderde protocollen in de logistiek: EDIFACT naar REST API-casestudy

Soms blijven bedrijven bij verouderde technologie steken, omdat ze geloven dat de vervanging ervan te veel moeite zou kosten. We hebben een zogenaamd MVP (a Minimum Viable Product) gemaakt om te valideren dat het werkt, zodat de klant het verder kan ontwikkelen na het bewijzen van zijn effectiviteit.

Het probleem

Tijdens de uitvoering van logistieke operaties kwam onze Klant, een bedrijf  het probleem van verouderde protocollen tegen. Net als de meesten op dit gebied, gebruikte de Klant  een interactief uitwisselingsprotocol om logistieke operaties uit te voeren. Deze protocollen zijn verouderd: sommige ervan zijn uit de jaren ‘50 en ’60. Maar worden ze nog steeds gebruikt.

De klant moest al de communicatie met de partners en aannemers voeren in een verouderde EDIFACT (International standard for electronic data interchange) versie die niet naar cloud wordt geschaald. Deze verouderde protocol hield bijvoorbeeld de integratie van gegevens in een nieuwe protocol tegen. EDIFACT formaat is door militaire logistiek geïnspireerd aan het einde van de jaren veertig. Verrassend, maar het wordt tegenwoordig nog steeds gebruikt in een helemaal andere wereld.

Bij Moqod hebben we een MVP gebouwd als een bewijs van een concept van een nieuwe oplossing. Verder laten we in deze case-study zien hoe we het hebben gedaan.

De uitdaging

Met behulp van moderne cloud oplossingen moesten we een systeem bouwen waarmee de Klant EDIFACT kan omzetten in een modern formaat. Verder kan het formaat makkelijker worden opgeslagen en geanalyseerd . Bovendien moesten we dat snel en met beperkte middelen doen. Uiteindelijk hebben we ons gericht op het oplossen van het bedrijfsprobleem, in plaats van het vervangen van infrastructuur.

We kozen voor een AWS (Amazon Web Services) en open data bibliotheken. Als een alternatief zouden we:

  • Een server instellen
  • Een autorisatie- en authenticatie probleem oplossen
  • Zorgen voor monitoring
  • Zorgen voor ondersteuning en onderhoud

Met behulp van moderne cloud oplossingen kunnen we deze stappen overslaan en kosten besparen, omdat we alleen maar AWS-cloud kosten betalen.

De keuze van de oplossing

We bouwden namelijk geen nieuwe converters. In plaats ervan gebruiken we een van de open source bibliotheken om EDI naar JSON te converteren. Na enkele opties hebben we toch besloten het EDI-JSON project te gebruiken. Hoewel het gebruik van een open source bibliotheek enkele beperkingen heeft, hielden ze onze opdracht niet tegen.

Verder moesten we een van de opties kiezen om de service te bouwen:

  1. Een service bouwen met gebruik maken van Java, daarna  een webserver met deze service in een Docker-container ‘wikkelen’ en vervolgens kunnen we die op een virtuele server starten
  2. Een serverloos model kiezen en een service op een cloud deployeren

De cloudomgeving bood out of the box schaalbaarheid, beschikbaarheid en authenticatie. Dus we beschouwden optie 2 als de beste voor onze vereisten. Het enige dat we moesten doen, was een code voor het verwerken van aanvragen schrijven en deze oplossing implementeren in een cloud infrastructuur.

We kozen voor een AWS-cloud infrastructuur (een combinatie van Amazon API Gateway en AWS Lambda). We gebruikten een gratis open-source versie. Als we toch moeten opschalen kunnen we overschakelen naar de betaalde versie.

De beschrijving van de oplossing

Omdat we voor combinatie van Amazon API Gateway en AWS Lambda hebben gekozen, was onze taak om lambda-functies te schrijven voor het verwerken van verzoeken.

Het schrijven van lambda functies

Het EDI-JSON project bevat al vooraf geschreven EdiToJsonDriver. Dat geeft ons mogelijkheid om een EDI-bestand naar JSON-bestand te converteren. Maar, omdat het onze taak was om een lambda-functie te schrijven, hadden we een module nodig die met strings zou werken in plaats van met bestanden. Daarom gebruikten we EdiToJson-klasse (gecompileerde klasse bevindt zich in een edireader-json-basic-5.5.19.jar-archief dat wordt gebruikt in EdiToJsonDriver).

Verder schreven we een EdiToJsonConverter. Hij implementeert een RequestHandler interface met de handleRequest methode, die een JSON-object ontvangt met een veld “data” (een rij met data in EDI-formaat) en geeft een JSON-object dat werd ontvangen tijdens het converteren van EDI naar JSON weer. Dit zijn de instructies die we gebruikten om een Lambda functie te schrijven:

  1. https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html
  2. https://docs.aws.amazon.com/lambda/latest/dg/java-handler-io-type-pojo.html

Het samenstellen van een zip-archief voor implementatie

Zip-archief van Lambda functies voor het deployeren is gemaakt volgens deze handleiding.

Het gemaakte zip-archief kan worden geüpload naar AWS Lambda via een AWS-console.

Het uploaden van zip-archief naar AWS Lambda via een AWS-console.

API Gateway Maken en Instellen

Met behulp van de AWS documentatie hebben we REST API gemaakt met POST-methode / edifact-json en met eerder gemaakte Lambda-functie voor het verwerken van verzoeken.

Het maken van REST API met POST methode / edifact json.

We kozen voor een mechanisme met een API Sleutel voor authenticatie.

API Sleutel voor authenticatie.

Het maken van een Gebruiksplan en een API Sleutel.

Om een API Sleutel in REST API te gebruiken, moeten we een gebruiksplan en API Sleutel maken volgens de instructie:

  1. https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-api-usage-plans.html
Het maken van Gebruiksplan en API Sleutel.
Het maken van Gebruiksplan en API Sleutel 2.

Query voorbeeld:

Query(gebruik maken van cURL)
curl -X POST \
https://.execute-api.eu-central-1.amazonaws.com/testing/edifact-json/ \
-H 'Content-Type: application/json' \
-H 'cache-control: no-cache' \
-H 'x-api-key: **' \
-d '{
"data": "UNB+UNOA:1+01010000253001+O0013000093SCHA-Z59+991006:1902+PAYO0012101221'\''\nUNH+1+INVOIC:D:97A:UN'\''\nBGM+381+1060113800026+9'\''\nDTM+137:199910060000:102'\''\nNAD+BT+VAUXHALL MOTORS LTD::91'\''\nRFF+VA:382324067'\''\nNAD+SU+2002993::92'\''\nRFF+VA:123844750'\''\nCUX+2:EUR'\''\nPAT+1'\''\nDTM+140:19991031:102'\''\nLIN+++090346642:IN'\''\nQTY+12:54:PCE'\''\nMOA+203:1960.29'\''\nPRI+AAA:3630.1724::NTP:100:C62'\''\nRFF+SI:165480'\''\nDTM+11:199909280000:102'\''\nRFF+ON:X18V00003'\''\nRFF+TN:AB1'\''\nTAX+7+VAT+++:::0'\''\nNAD+ST+023::92'\''\nUNS+S'\''\nMOA+77:1960.29'\''\nTAX+7+VAT'\''\nUNT+24+1'\''\nUNZ+1+PAYO0012101221'\''"
}

Antwoord:

{
"interchanges": [
{
"UNB_01_SyntaxIdentifier": {
"UNB_01_01_SyntaxIdentifier": "UNOA",
"UNB_01_02_SyntaxVersionNumber": "1"
},
"UNB_02_InterchangeSender": {
"UNB_02_01_InterchangeSenderIdentification": "01010000253001",
"UNB_02_02_IdentificationCodeQualifier": ""
},
"UNB_03_InterchangeReceiver": {
"UNB_03_01_InterchangeReceiverIdentification": "O0013000093SCHA-Z59",
"UNB_03_02_IdentificationCodeQualifier": ""
},
"UNB_04_DateAndTimeOfPreparation": {
"UNB_04_01_Date": "991006",
"UNB_04_02_Time": "1902"
},
"UNB_05_InterchangeControlReference": "PAYO0012101221",
"transactions": [
{
"UNH_01_MessageReferenceNumber": "1",
"UNH_02_MessageIdentifier": {
"UNH_02_01_MessageType": "INVOIC",
"UNH_02_02_MessageVersionNumber": "D",
"UNH_02_03_MessageReleaseNumber": "97A",
"UNH_02_04_ControllingAgency": "UN"
},
"segments": [
{
"BGM_01": "381",
"BGM_02": "1060113800026",
"BGM_03": "9"
},
{
"DTM_01": {
"DTM_01_01": "137",
"DTM_01_02": "199910060000",
"DTM_01_03": "102"
}
},
{
"NAD_01": "BT",
"NAD_02": {
"NAD_02_01": "VAUXHALL MOTORS LTD",
"NAD_02_03": "91"
}
},
{
"RFF_01": {
"RFF_01_01": "VA",
"RFF_01_02": "382324067"
}
},
{
"NAD_01": "SU",
"NAD_02": {
"NAD_02_01": "2002993",
"NAD_02_03": "92"
}
},
{
"RFF_01": {
"RFF_01_01": "VA",
"RFF_01_02": "123844750"
}
},
{
"CUX_01": {
"CUX_01_01": "2",
"CUX_01_02": "EUR"
}
},
{
"PAT_01": "1"
},
{
"DTM_01": {
"DTM_01_01": "140",
"DTM_01_02": "19991031",
"DTM_01_03": "102"
}
},
{
"LIN_03": {
"LIN_03_01": "090346642",
"LIN_03_02": "IN"
}
},
{
"QTY_01": {
"QTY_01_01": "12",
"QTY_01_02": "54",
"QTY_01_03": "PCE"
}
},
{
"MOA_01": {
"MOA_01_01": "203",
"MOA_01_02": "1960.29"
}
},
{
"PRI_01": {
"PRI_01_01": "AAA",
"PRI_01_02": "3630.1724",
"PRI_01_04": "NTP",
"PRI_01_05": "100",
"PRI_01_06": "C62"
}
},
{
"RFF_01": {
"RFF_01_01": "SI",
"RFF_01_02": "165480"
}
},
{
"DTM_01": {
"DTM_01_01": "11",
"DTM_01_02": "199909280000",
"DTM_01_03": "102"
}
},
{
"RFF_01": {
"RFF_01_01": "ON",
"RFF_01_02": "X18V00003"
}
},
{
"RFF_01": {
"RFF_01_01": "TN",
"RFF_01_02": "AB1"
}
},
{
"TAX_01": "7",
"TAX_02": "VAT",
"TAX_05": {
"TAX_05_04": "0"
}
},
{
"NAD_01": "ST",
"NAD_02": {
"NAD_02_01": "023",
"NAD_02_03": "92"
}
},
{
"UNS_01": "S"
},
{
"MOA_01": {
"MOA_01_01": "77",
"MOA_01_02": "1960.29"
}
},
{
"TAX_01": "7",
"TAX_02": "VAT"
}
]
}
]
}
]
}

Project tijdlijn

De oplossing werd relatief snel geïmplementeerd. Het kostte ons maximaal twee dagen om onderzoek uit te voeren en slechts één dag om te implementeren.

Conclusie

De Klant heeft ons proof-of-concept goedgekeurd. Daardoor bespaarde hij tijd en budget en maakte niet alleen snelle maar ook pijnloze overgang naar nieuwe logistieke protocollen.