Introduktion til Smooks

1. Oversigt

I denne vejledning introducerer vi Smooks-rammen.

Vi beskriver, hvad det er, viser dets nøglefunktioner og lærer til sidst, hvordan man bruger nogle af dens mere avancerede funktioner.

Lad os først og fremmest forklare, hvad rammen er beregnet til at opnå.

2. Smooks

Smooks er en ramme for databehandlingsapplikationer - håndtering af strukturerede data som XML eller CSV.

Det giver både API'er og en konfigurationsmodel, der giver os mulighed for at definere transformationer mellem foruddefinerede formater (for eksempel XML til CSV, XML til JSON og mere).

Vi kan også bruge et antal værktøjer til at konfigurere vores kortlægning - inklusive FreeMarker eller Groovy-scripts.

Udover transformationer leverer Smooks også andre funktioner som meddelelsesvalidering eller datadeling.

2.1. Nøglefunktioner

Lad os se på Smooks 'vigtigste brugssager:

  • Beskedkonvertering - transformation af data fra forskellige kildeformater til forskellige outputformater
  • Beskedberigelse - udfyld meddelelsen med yderligere data, der kommer fra ekstern datakilde som database
  • Opdeling af data - behandling af store filer (GB'er) og opdeling i mindre
  • Java-binding - konstruktion og udfyldning af Java-objekter fra meddelelser
  • Beskedvalidering - udfør valideringer som regex eller endda oprettelse af dine egne valideringsregler

3. Indledende konfiguration

Lad os starte med den Maven-afhængighed, vi skal tilføje til vores pom.xml:

 org.milyn milyn-smooks-all 1.7.0 

Den seneste version kan findes på Maven Central.

4. Java-binding

Lad os nu starte med at fokusere på at binde beskeder til Java-klasser. Vi gennemgår en simpel XML til Java-konvertering her.

4.1. Basale koncepter

Vi starter med et simpelt eksempel. Overvej følgende XML:

 771 IN_PROGRESS 

For at udføre denne opgave med Smooks er vi nødt til at gøre to ting: forberede POJO'erne og Smooks-konfigurationen.

Lad os se, hvordan vores model ser ud:

public class Order {private Date creationDate; privat Langt nummer; privat status status // ...} 
offentlig enum Status {NEW, IN_PROGRESS, FERDIGET}

Lad os nu gå videre til Smooks-kortlægninger.

Grundlæggende er kortlægningerne en XML-fil, der indeholder transformationslogik. I denne artikel bruger vi tre forskellige typer regler:

  • bønne - definerer kortlægning af en konkret struktureret sektion til Java-klasse
  • værdi - definerer kortlægningen for bønnens særlige egenskab. Kan indeholde mere avanceret logik som dekodere, der bruges til at kortlægge værdier til nogle datatyper (som dato eller decimalformat)
  • wiring - giver os mulighed for at tilslutte en bønne til andre bønner (f.eks Leverandør bønne vil blive kablet til Bestille bønne)

Lad os se på de kortlægninger, vi bruger i vores tilfælde her:

      åååå-MM-dd 

Lad os nu, når konfigurationen er klar, prøve at teste, om vores POJO er konstrueret korrekt.

Først skal vi konstruere et Smooks-objekt og videregive input XML som en stream:

offentlig ordre converOrderXMLToOrderObject (streng sti) kaster IOException, SAXException {Smooks smooks = nye Smooks (this.class.getResourceAsStream ("/ smooks-mapping.xml")); prøv {JavaResult javaResult = ny JavaResult (); smooks.filterSource (ny StreamSource (denne.klasse .getResourceAsStream (sti)), javaResult); returner (Bestilling) javaResult.getBean ("ordre"); } endelig {smooks.close (); }}

Og endelig, hævde, om konfigurationen udføres korrekt:

@Test offentlig ugyldighed givenOrderXML_whenConvert_thenPOJOsConstructedCorrectly () kaster Undtagelse {XMLToJavaConverter xmlToJavaOrderConverter = ny XMLToJavaConverter (); Ordreordre = xmlToJavaOrderConverter .converOrderXMLToOrderObject ("/ order.xml"); assertThat (order.getNumber (), er (771L)); assertThat (order.getStatus (), er (Status.IN_PROGRESS)); assertThat (order.getCreationDate (), er (ny SimpleDateFormat ("åååå-MM-dd"). parse ("2018-01-14"));}

4.2. Avanceret binding - Henvisning til andre bønner og lister

Lad os udvide vores tidligere eksempel med leverandør og ordre-varer tags:

 771 IN_PROGRESS Company X 1234567 1 PX1234 9.99   1 RX990 120.32   

Og lad os nu opdatere vores model:

offentlig klasse Orden {// .. privat leverandør leverandør; private Liste emner; // ...}
public class Item {private String code; privat dobbelt pris; privat heltalsmængde; // ...} 
offentlig klasse leverandør {privat strengnavn; private String-telefonnummer; // ...}

Vi er også nødt til at udvide konfigurationskortlægningen med leverandør og vare definitioner af bønner.

Bemærk, at vi også har defineret adskilt genstande bønne, som holder alle vare elementer i ArrayList.

Endelig bruger vi Smooks ledningsføring attribut, at pakke det hele sammen.

Se på, hvordan kortlægninger vil se ud i dette tilfælde:

      åååå-MM-dd 

Endelig vil vi tilføje et par påstande til vores tidligere test:

assertThat (order.getSupplier (), er (ny leverandør ("Company X", "1234567")); assertThat (order.getItems (), indeholderInAnyOrder (ny vare ("PX1234", 9.99,1), ny vare ("RX990", 120.32,1));

5. Validering af meddelelser

Smooks leveres med valideringsmekanisme baseret på regler. Lad os se på, hvordan de bruges.

Definitionen af ​​reglerne gemmes i konfigurationsfilen, indlejret i ruleBases tag, som kan indeholde mange ruleBase elementer.

Hver ruleBase elementet skal have følgende egenskaber:

  • navn - unikt navn, der kun bruges som reference
  • src - sti til regelkildefilen
  • udbyder - fuldt kvalificeret klassenavn, der implementeres RuleProvider interface

Smooks leveres med to udbydere ud af kassen: RegexProvider og MVELProvider.

Den første bruges til at validere individuelle felter i regex-lignende stil.

Den anden bruges til at udføre mere kompliceret validering i dokumentets globale omfang. Lad os se dem i aktion.

5.1. RegexProvider

Lad os bruge RegexProvider for at validere to ting: formatet på kundenavn og telefonnummer. RegexProvider som kilde kræver en Java-egenskabsfil, som skal indeholde regex-validering på nøgleværdimåde.

For at opfylde vores krav bruger vi følgende opsætning:

leverandørnavn = [A-Za-z0-9] * leverandørPhone = ^ [0-9 \ - \ +] {9,15} $

5.2. MVELProvider

Vi bruger MVELProvider for at validere, hvis den samlede pris for hver ordre-vare er mindre end 200. Som kilde forbereder vi en CSV-fil med to kolonner: regelnavn og MVEL-udtryk.

For at kontrollere, om prisen er korrekt, har vi brug for følgende indtastning:

"max_total", "orderItem.quantity * orderItem.price <200.00"

5.3. Valideringskonfiguration

Når vi har forberedt kildefilerne til ruleBases, vi går videre til implementering af konkrete valideringer.

En validering er et andet tag i Smooks-konfiguration, som indeholder følgende attributter:

  • executeOn - sti til det validerede element
  • navn - henvisning til ruleBase
  • onFail - specificerer, hvilken handling der skal foretages, når valideringen mislykkes

Lad os anvende valideringsregler til vores Smooks-konfigurationsfil og kontrollere, hvordan det ser ud (bemærk, at hvis vi vil bruge MVELProvider, vi er tvunget til at bruge Java-binding, så det er derfor, vi har importeret tidligere Smooks-konfiguration):

Lad os nu, når konfigurationen er klar, prøve at teste, om validering mislykkes på leverandørens telefonnummer.

Igen er vi nødt til at konstruere Smooks objekt og videregive input XML som en stream:

offentlig ValidationResult validering (streng sti) kaster IOException, SAXException {Smooks smooks = nye Smooks (OrderValidator.class .getResourceAsStream ("/ smooks / smooks-validation.xml")); prøv {StringResult xmlResult = ny StringResult (); JavaResult javaResult = ny JavaResult (); ValidationResult validationResult = new ValidationResult (); smooks.filterSource (ny StreamSource (OrderValidator.class .getResourceAsStream (sti)), xmlResult, javaResult, validationResult); return validationResult; } endelig {smooks.close (); }} 

Og endelig hævde, hvis der opstod en valideringsfejl:

@Test offentlig ugyldighed givenIncorrectOrderXML_whenValidate_thenExpectValidationErrors () kaster undtagelse {OrderValidator orderValidator = ny OrderValidator (); ValidationResult validationResult = orderValidator .validate ("/ smooks / order.xml"); assertThat (validationResult.getErrors (), hasSize (1)); assertThat (validationResult.getErrors (). get (0) .getFailRuleResult (). getRuleName (), er ("providerPhone")); }

6. Konvertering af meddelelser

Den næste ting, vi vil gøre, er at konvertere beskeden fra et format til et andet.

I Smooks kaldes denne teknik også skabeloner og det understøtter:

  • FreeMarker (foretrukken mulighed)
  • XSL
  • Snor skabelon

I vores eksempel bruger vi FreeMarker-motoren til at konvertere XML-beskeder til noget, der ligner EDIFACT, og endda forberede en skabelon til e-mail-beskeden baseret på XML-rækkefølge.

Lad os se, hvordan man forbereder en skabelon til EDIFACT:

UNA: +.? 'UNH + $ {order.number} + $ {order.status} + $ {order.creationDate? Date}' CTA + $ {provider.name} + $ {provider.phoneNumber} 'LIN + $ {item.quantity} + $ { item.code} + $ {item.price} ' 

Og til e-mail-beskeden:

Hej, ordrenummer # $ {order.number} oprettet på $ {order.creationDate? Date} er i øjeblikket i $ {order.status} status. Overvej at kontakte leverandøren "$ {provider.name}" med telefonnummeret: "$ {provider.phoneNumber}". Bestil varer: $ {item.quantity} X $ {item.code} (samlet pris $ {item.price * item.quantity}) 

Smooks-konfigurationen er meget grundlæggende denne gang (husk bare at importere den tidligere konfiguration for at importere Java-bindingsindstillinger):

    / sti / til / skabelon.ftl 

Denne gang skal vi bare passere en StringResult til Smooks-motor:

Smooks smooks = nye Smooks (config); StringResult stringResult = ny StringResult (); smooks.filterSource (ny StreamSource (OrderConverter.class .getResourceAsStream (sti)), stringResult); returnere stringResult.toString ();

Og vi kan selvfølgelig teste det:

@Test offentlig ugyldighed givenOrderXML_whenApplyEDITemplate_thenConvertedToEDIFACT () kaster undtagelse {OrderConverter orderConverter = ny OrderConverter (); Streng edifact = orderConverter.convertOrderXMLtoEDIFACT ("/smooks/order.xml"); assertThat (edifact, er (EDIFACT_MESSAGE)); }

7. Konklusion

I denne vejledning fokuserede vi på, hvordan man konverterer meddelelser til forskellige formater eller omdanner dem til Java-objekter ved hjælp af Smooks. Vi så også, hvordan man udfører valideringer baseret på regex eller forretningslogikregler.

Som altid kan al den kode, der bruges her, findes på GitHub.