Einführung in Smooks

Einführung in Smooks

1. Überblick

In diesem Tutorial werden dieSmooks framework vorgestellt.

Wir werden beschreiben, was es ist, die wichtigsten Funktionen auflisten und schließlich lernen, wie einige der erweiterten Funktionen verwendet werden.

Lassen Sie uns zunächst kurz erklären, was mit dem Framework erreicht werden soll.

2. Smooks

Smooks ist ein Framework für Datenverarbeitungsanwendungen, das sich mit strukturierten Daten wie XML oder CSV befasst.

Es bietet sowohl APIs als auch ein Konfigurationsmodell, mit dem Transformationen zwischen vordefinierten Formaten (z. B. XML zu CSV, XML zu JSON und mehr) definiert werden können.

Wir können auch eine Reihe von Tools verwenden, um unser Mapping einzurichten - einschließlich FreeMarker- oder Groovy-Skripten.

Neben Transformationen bietet Smooks auch andere Funktionen wie Nachrichtenüberprüfungen oder Datenaufteilung.

2.1. Hauptmerkmale

Werfen wir einen Blick auf die Hauptanwendungsfälle von Smooks:

  • Nachrichtenkonvertierung - Umwandlung von Daten aus verschiedenen Quellformaten in verschiedene Ausgabeformate

  • Nachrichtenanreicherung - Füllen Sie die Nachricht mit zusätzlichen Daten aus, die von einer externen Datenquelle wie der Datenbank stammen

  • Datenaufteilung - Verarbeitung großer Dateien (GB) und Aufteilung in kleinere

  • Java-Bindung - Erstellen und Auffüllen von Java-Objekten aus Nachrichten

  • Nachrichtenüberprüfung - Durchführen von Überprüfungen wie Regex oder Erstellen eigener Überprüfungsregeln

3. Anfangskonfiguration

Beginnen wir mit der Maven-Abhängigkeit, die wir zu unserenpom.xml hinzufügen müssen:


    org.milyn
    milyn-smooks-all
    1.7.0

Die neueste Version finden Sie unterMaven Central.

4. Java-Bindung

Beginnen wir nun damit, Nachrichten an Java-Klassen zu binden. Wir werden hier eine einfache XML-zu-Java-Konvertierung durchführen.

4.1. Grundlegendes Konzept

Wir beginnen mit einem einfachen Beispiel. Betrachten Sie das folgende XML:


    771
    IN_PROGRESS

Um diese Aufgabe mit Smooks zu erfüllen, müssen wir zwei Dinge tun: die POJOs und die Smooks-Konfiguration vorbereiten.

Mal sehen, wie unser Modell aussieht:

public class Order {

    private Date creationDate;
    private Long number;
    private Status status;
    // ...
}
public enum Status {
    NEW, IN_PROGRESS, FINISHED
}

Fahren wir nun mit den Smooks-Zuordnungen fort.

Grundsätzlich handelt es sich bei den Zuordnungen um eine XML-Datei, die Transformationslogik enthält. In diesem Artikel werden drei verschiedene Arten von Regeln verwendet:

  • bean – definiert die Zuordnung eines konkreten strukturierten Abschnitts zur Java-Klasse

  • value - definiert die Zuordnung für die bestimmte Eigenschaft der Bean. Kann erweiterte Logik wie Decoder enthalten, mit denen Werte bestimmten Datentypen (wie Datums- oder Dezimalformat) zugeordnet werden.

  • Mit wiring – können wir eine Bohne mit anderen Bohnen verbinden (zum Beispiel wirdSupplier Bohne mitOrder Bohne verdrahtet).

Werfen wir einen Blick auf die Zuordnungen, die wir in unserem Fall hier verwenden:




    
        
        
        
            yyyy-MM-dd
        
    

Versuchen wir nun mit der Konfiguration zu testen, ob unser POJO korrekt aufgebaut ist.

Zuerst müssen wir ein Smooks-Objekt erstellen und Eingabe-XML als Stream übergeben:

public Order converOrderXMLToOrderObject(String path)
  throws IOException, SAXException {

    Smooks smooks = new Smooks(
      this.class.getResourceAsStream("/smooks-mapping.xml"));
    try {
        JavaResult javaResult = new JavaResult();
        smooks.filterSource(new StreamSource(this.class
          .getResourceAsStream(path)), javaResult);
        return (Order) javaResult.getBean("order");
    } finally {
        smooks.close();
    }
}

Stellen Sie abschließend fest, ob die Konfiguration ordnungsgemäß durchgeführt wurde:

@Test
public void givenOrderXML_whenConvert_thenPOJOsConstructedCorrectly() throws Exception {
    XMLToJavaConverter xmlToJavaOrderConverter = new XMLToJavaConverter();
    Order order = xmlToJavaOrderConverter
      .converOrderXMLToOrderObject("/order.xml");

    assertThat(order.getNumber(), is(771L));
    assertThat(order.getStatus(), is(Status.IN_PROGRESS));
    assertThat(
      order.getCreationDate(),
      is(new SimpleDateFormat("yyyy-MM-dd").parse("2018-01-14"));
}

4.2. Erweiterte Bindung - Verweisen auf andere Bohnen und Listen

Erweitern wir unser vorheriges Beispiel mit den Tagssupplier undorder-items:


    771
    IN_PROGRESS
    
        Company X
        1234567
    
    
        
            1
            PX1234
            9.99
        
        
            1
            RX990
            120.32
        
    

Und jetzt aktualisieren wir unser Modell:

public class Order {
    // ..
    private Supplier supplier;
    private List items;
    // ...
}
public class Item {

    private String code;
    private Double price;
    private Integer quantity;
    // ...
}
public class Supplier {

    private String name;
    private String phoneNumber;
    // ...
}

Wir müssen auch die Konfigurationszuordnung um die Bean-Definitionensupplier unditem erweitern.

Beachten Sie, dass wir auch getrennteitems-Bean definiert haben, die alleitem-Elemente inArrayList enthält.

Schließlich werden wir das Attribut Smookswiringverwenden, um alles zusammen zu bündeln.

Sehen Sie sich an, wie die Zuordnungen in diesem Fall aussehen werden:




    
        
        
        
            yyyy-MM-dd
        
        
        
    

    
        
        
    

    
        
    
    
        
        
        
    

Abschließend fügen wir unserem vorherigen Test einige Aussagen hinzu:

assertThat(
  order.getSupplier(),
  is(new Supplier("Company X", "1234567")));
assertThat(order.getItems(), containsInAnyOrder(
  new Item("PX1234", 9.99,1),
  new Item("RX990", 120.32,1)));

5. Nachrichtenüberprüfung

Smooks wird mit einem auf Regeln basierenden Validierungsmechanismus ausgeliefert. Werfen wir einen Blick darauf, wie sie verwendet werden.

Die Definition der Regeln wird in der Konfigurationsdatei gespeichert, die im TagruleBases verschachtelt ist und vieleruleBase-Elemente enthalten kann.

JedesruleBase-Element muss die folgenden Eigenschaften haben:

  • name – eindeutiger Name, der nur als Referenz verwendet wird

  • src – Pfad zur Regelquelldatei

  • provider - Vollqualifizierter Klassenname, der die Schnittstelle vonRuleProviderimplementiert

Smooks wird mit zwei sofort einsatzbereiten Anbietern geliefert:RegexProvider undMVELProvider.

Der erste wird verwendet, um einzelne Felder in einem regulären Stil zu validieren.

Der zweite wird verwendet, um eine kompliziertere Validierung im globalen Bereich des Dokuments durchzuführen. Lassen Sie uns sie in Aktion sehen.

5.1. RegexProvider

Verwenden SieRegexProvider, um zwei Dinge zu überprüfen: das Format des Kundennamens und die Telefonnummer. RegexProvider als Quelle erfordert eine Java-Eigenschaftendatei, dieshould contain regex validation in key-value fashion.

Um unsere Anforderungen zu erfüllen, verwenden wir das folgende Setup:

supplierName=[A-Za-z0-9]*
supplierPhone=^[0-9\\-\\+]{9,15}$

5.2. MVELProvider

Wir werdenMVELProvider verwenden, um zu überprüfen, ob der Gesamtpreis für jedesorder-item weniger als 200 beträgt. Als Quelle bereiten wir eine CSV-Datei mit zwei Spalten vor: Regelname und MVEL-Ausdruck.

Um zu überprüfen, ob der Preis korrekt ist, benötigen wir den folgenden Eintrag:

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

5.3. Validierungskonfiguration

Sobald wir die Quelldateien fürruleBasesvorbereitet haben, werden wir mit der Implementierung konkreter Validierungen fortfahren.

Eine Validierung ist ein weiteres Tag in der Smooks-Konfiguration, das die folgenden Attribute enthält:

  • executeOn - Pfad zum validierten Element

  • name - Verweis aufruleBase

  • onFail - Gibt an, welche Aktion ausgeführt wird, wenn die Validierung fehlschlägt

Wenden wir Validierungsregeln auf unsere Smooks-Konfigurationsdatei an und überprüfen, wie sie aussieht (note that if we want to use the MVELProvider, we’re forced to use Java binding, so that’s why we’ve imported previous Smooks configuration):




    

    
        
        
    

    
    
    

Versuchen Sie nun mit der Konfiguration zu testen, ob die Validierung der Telefonnummer des Lieferanten fehlschlägt.

Wieder müssen wir das Objekt vonSmookskonstruieren und Eingabe-XML als Stream übergeben:

public ValidationResult validate(String path)
  throws IOException, SAXException {
    Smooks smooks = new Smooks(OrderValidator.class
      .getResourceAsStream("/smooks/smooks-validation.xml"));
    try {
        StringResult xmlResult = new StringResult();
        JavaResult javaResult = new JavaResult();
        ValidationResult validationResult = new ValidationResult();
        smooks.filterSource(new StreamSource(OrderValidator.class
          .getResourceAsStream(path)), xmlResult, javaResult, validationResult);
        return validationResult;
    } finally {
        smooks.close();
    }
}

Und zum Schluss, falls ein Validierungsfehler aufgetreten ist:

@Test
public void givenIncorrectOrderXML_whenValidate_thenExpectValidationErrors() throws Exception {
    OrderValidator orderValidator = new OrderValidator();
    ValidationResult validationResult = orderValidator
      .validate("/smooks/order.xml");

    assertThat(validationResult.getErrors(), hasSize(1));
    assertThat(
      validationResult.getErrors().get(0).getFailRuleResult().getRuleName(),
      is("supplierPhone"));
}

6. Nachrichtenkonvertierung

Als nächstes möchten wir die Nachricht von einem Format in ein anderes konvertieren.

In Smooks, this technique is also called templating und es unterstützt:

  • FreeMarker (bevorzugte Option)

  • XSL

  • String Vorlage

In unserem Beispiel verwenden wir die FreeMarker-Engine, um XML-Nachrichten in eine EDIFACT-ähnliche Nachricht zu konvertieren und sogar eine Vorlage für die E-Mail-Nachricht basierend auf der XML-Reihenfolge vorzubereiten.

Lassen Sie uns sehen, wie Sie eine Vorlage für EDIFACT vorbereiten:

UNA:+.? '
UNH+${order.number}+${order.status}+${order.creationDate?date}'
CTA+${supplier.name}+${supplier.phoneNumber}'
<#list items as item>
LIN+${item.quantity}+${item.code}+${item.price}'

Und für die E-Mail-Nachricht:

Hi,
Order number #${order.number} created on ${order.creationDate?date} is currently in ${order.status} status.
Consider contacting the supplier "${supplier.name}" with phone number: "${supplier.phoneNumber}".
Order items:
<#list items as item>
${item.quantity} X ${item.code} (total price ${item.price * item.quantity})

Die Smooks-Konfiguration ist diesmal sehr einfach (denken Sie daran, die vorherige Konfiguration zu importieren, um Java-Bindungseinstellungen zu importieren):




    

    
        /path/to/template.ftl
    

Dieses Mal müssen wir nur einStringResult an die Smooks-Engine übergeben:

Smooks smooks = new Smooks(config);
StringResult stringResult = new StringResult();
smooks.filterSource(new StreamSource(OrderConverter.class
  .getResourceAsStream(path)), stringResult);
return stringResult.toString();

Und wir können es natürlich testen:

@Test
public void givenOrderXML_whenApplyEDITemplate_thenConvertedToEDIFACT()
  throws Exception {
    OrderConverter orderConverter = new OrderConverter();
    String edifact = orderConverter.convertOrderXMLtoEDIFACT(
      "/smooks/order.xml");

   assertThat(edifact,is(EDIFACT_MESSAGE));
}

7. Fazit

In diesem Tutorial haben wir uns darauf konzentriert, wie Nachrichten in verschiedene Formate konvertiert oder mithilfe von Smooks in Java-Objekte umgewandelt werden können. Wir haben auch gesehen, wie Validierungen basierend auf Regex- oder Geschäftslogikregeln durchgeführt werden.

Wie immer befindet sich der gesamte hier verwendete Code inover on GitHub.