JAXB to XML Transformation

Version: 17.07

Supported Since: 17.07

Use case description

Owl Express is a courier service that offer exchange of goods and parcels throughout the country. They recently installed a courier software in each store. When a parcel is received, a database is updated and a courier of Owl Express is informed the details of the delivery of the parcel.

Owl Express is in need of a reporting service of the orders they delivered. For this scenario, the courier software, they use has not given a report generating option. Hence they are planning to generate XML files of the orders delivered and store them. However, Owl Express cannot use the data that is retrieved from the database directly to create XML files.

<ns2:PurchaseType xmlns:ns2="http://www.adroitlogic.org/gringotts">
<billTo>testAddr4</billTo>
<items>TestItem2</items>
<orderDate>2017-07-16</orderDate>
<shipTo>testAddr3</shipTo>
</ns2:PurchaseType>

Proposed Solution

Since Owl Express cannot modify or replace their courier software, they decided to introduce an ESB to transform the retrieved data from database to the appropriate XML format.

jaxb transformation chart
For this scenario assume that the XML file generated is stored in a file system storage.

UltraStudio Configuration

UltraESB-X Configuration

Implementation of the Solution

Prerequisite

In order to implement above use case you must first select following dependencies when you are creating a new UltraStudio project.

  • Database Connector and Local File Connector from the connector list

  • Message Transformation, Flow Control and Message Logger from the processor list

If you have already created a project, you can add above dependencies via Component Registry. From Tools menu, select Ultra Studio → Component Registry and from the Connectors list and Processors list, select above dependencies.
Implementation

To implement above use case, first let’s create our integration flow named “JAXBIntervention.xcml” and then add required processing components by going through following steps in order.

  1. Add a Database Ingress Connector from the Connectors → Ingress Connectors list, to retrieve data from the database. Database Ingress Connector should be configured as given in the below table to expose database and retrieve the delivery details.

  2. Write a Custom Processing Element in order to create an object of the delivery order. Follow this guide to get started. Use the following source code when implementing the custom processing element,

/*
 * Copyright (c) 2010-2017 AdroitLogic Private Ltd. (https://www.adroitlogic.com/). All Rights Reserved.
 *
 * AdroitLogic PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package com.acme.esb;

import org.adroitlogic.x.annotation.config.OutPort;
import org.adroitlogic.x.annotation.config.Processor;
import org.adroitlogic.x.api.ExecutionResult;
import org.adroitlogic.x.api.XMessageContext;
import org.adroitlogic.x.api.config.ProcessorType;
import org.adroitlogic.x.api.processor.XProcessingElement;
import org.adroitlogic.x.base.format.ObjectFormat;
import org.adroitlogic.x.base.processor.AbstractProcessingElement;
import org.json.JSONArray;
import test.PurchaseType;

/**
 * Customer processing element to create objects using the database data and to set the created object as the message
 * payload
 *
 * @author Hasangi Thathsarani
 * @since 17.07
 */

@Processor(displayName = "Object Extractor", type = ProcessorType.CUSTOM)
public class ObjectExtractor extends AbstractProcessingElement {

    @OutPort(displayName = "Next", description = "Next processing element")
    private XProcessingElement nextElement;

    @Override
    public ExecutionResult process(XMessageContext messageContext) {
        String jsonStr = messageContext.getMessage().getPayload().readAsString(-1);
        JSONArray jsonArray = new JSONArray(jsonStr);
        for (int temp = 0; temp < jsonArray.length(); temp++) {
            PurchaseType purchaseType = new PurchaseType(jsonArray.getJSONObject(temp).getString("ShipTo"),
                    jsonArray.getJSONObject(temp).getString("BillTo"), jsonArray.getJSONObject(temp).getString("Item"),
                    jsonArray.getJSONObject(temp).getString("OrderDate"));
            messageContext.getMessage().setPayload(new ObjectFormat(purchaseType));
        }
        return nextElement.processMessage(messageContext);
    }

    public XProcessingElement getNextElement() {
        return nextElement;
    }

    public void setNextElement(XProcessingElement nextElement) {
        this.nextElement = nextElement;
    }
}
  1. Connect the Processor outport of the previously added Database Ingress Connector to the Input of this processing element.

  2. Add a JAXB to XML Transformer processing element from the Processors → Transformers list, to transform the created JAVA object to XML format. It should be configured as given in the below table to retrieve the expected XML output based on the input object. Connect the Next outport of the previously added Custom Processing Element to the Input of this processing element.

  3. Add a File Egress Connector from the connectors Connectors → Egress Connectors list, and configure as given in the below table to generate an XML file. Connect the Next outport of the previously added JAXB to XML Transformer to the Input of this egress connector.

  4. Add a Logger from the Processors → Generic list, and configure as given in the below table to catch any exceptions that could occur during the flow. Connect the on Exception outport of the previously added JAXB to XML Transformer to the Input of this processing element.

  5. Finally Add a Exceptional Flow End from the Processors → Flow Controller list, and configure as given in the below table to display any exceptions that could occur during the flow. Connect the Next outport of the previously added Logger to the Input of this processing element.

The completed integration flow should look like below.

jaxb transformation flow

Configuration for each element is as below. The numbering corresponds to the numbers shown in above diagram.

Design View

Text View

.

1. Database Ingress Connector

jaxb transformation component1

2. JAXB to XML Transformer

jaxb transformation component4

3. File Egress Connector

jaxb transformation component3

4. Logger

jaxb transformation component5

5. Exceptional Flow End

jaxb transformation component2
.

1. Database Ingress Connector

Data source

DB1-ultracp-datasource

SQL query

SELECT * FROM PurchaseType where OrderID = 2

2. JAXB to XML Transformer

Root Element

PurchaseType

URI

3. File Egress Connector

File Path

/home/hasangi/projects/samples-x/jaxb-transformation/src/main/resources

File Name

purchaseType.xml

4. Logger

Log Template

@{message.payload}

Log Level

DEBUG

5. Exceptional Flow End

Exception Message

Flow action failed

.

Now you can run the Ultra Project and check the functionality of the integration flow. Create an UltraESB Server run configuration and start it.

Property Configuration

When running the sample in the UltraESB-X distribution, you need to override the following properties in-order for the sample to work. The properties file is located at $ULTRA_HOME/conf/projects/jaxb-transformation/default.properties

Refer to Managing Project Properties documentation on how to override properties.

ultracp.driver=com.mysql.jdbc.Driver

The database driver to be used

ultracp.url

Url of the database

ultracp.pool

The name of the database connection pool

ultracp.username

Database username

ultracp.password

Database password

ultracp.minSize

Minimum size of the database pool

ultracp.maxTotal

Maximum total number of connections of database pool

ultracp.initialSize

Initial number of connections to be created

You will also have to add the mysql-connector-java-5.1.38.jar dependency (downloadable from here) to $ULTRA_HOME/lib/custom directory.

After that navigate to $ULTRA_HOME/bin directory. Next you can run the UltraESB-X distribution with following command to start the engine with this sample project deployed.

./ultraesbx.sh -sample jaxb-tranformation

Testing the Integration Project

Setting up the Database

As a privileged MySQL user, execute the following DBScript.sh script inside src/main/resources.

#!/bin/bash
mysql -u root -p <<EOF
CREATE DATABASE dbConnection;
USE dbConnection;
CREATE TABLE PurchaseType (
    OrderID int,
    ShipTo varchar(255),
    BillTo varchar(255),
    Item varchar(255),
    OrderDate DATE
);
SHOW tables;
INSERT INTO PurchaseType (
    OrderID,
    ShipTo,
    BillTo,
    Item,
    OrderDate)
VALUES (1,"testAddr1", "testAddr2", "TestItem", now());
INSERT INTO PurchaseType (
    OrderID,
    ShipTo,
    BillTo,
    Item,
    OrderDate)
VALUES (2,"testAddr3", "testAddr4", "TestItem2", now());
EOF

The script creates the dbConnection database with a PurchaseType table`. After creating the database, a Datasource is created as in the link [create Datasource]. You will also have to add the mysql-connector-java-5.1.38.jar dependency (downloadable from here) to lib folder.

Running the sample

Create a folder src/main/test and add the files ObjectFactory.java and PurchaseType.java into the test folder.

/*
 * Copyright (c) 2010-2017 AdroitLogic Private Ltd. (https://www.adroitlogic.org). All Rights Reserved.
 *
 * AdroitLogic PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package test;

import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlElementDecl;
import javax.xml.bind.annotation.XmlRegistry;
import javax.xml.namespace.QName;


/**
 * This object contains factory methods for each
 * Java content interface and Java element interface
 * generated in the test package.
 * <p>An ObjectFactory allows you to programatically
 * construct new instances of the Java representation
 * for XML content. The Java representation of XML
 * content can consist of schema derived interfaces
 * and classes representing the binding of schema
 * type definitions, element declarations and model
 * groups.  Factory methods for each of these are
 * provided in this class.
 *
 */
@XmlRegistry
public class ObjectFactory {

    private final static QName _PurchaseOrder_QNAME = new QName("", "purchaseType");
    private final static QName _Comment_QNAME = new QName("", "comment");

    /**
     * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: test
     *
     */
    public ObjectFactory() {
    }


    public PurchaseType createPurchaseOrderType() {
        return new PurchaseType();
    }


    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link PurchaseType }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "", name = "purchaseOrder")
    public JAXBElement<PurchaseType> createPurchaseOrder(PurchaseType value) {
        return new JAXBElement<PurchaseType>(_PurchaseOrder_QNAME, PurchaseType.class, null, value);
    }

    /**
     * Create an instance of {@link JAXBElement }{@code <}{@link String }{@code >}}
     *
     */
    @XmlElementDecl(namespace = "", name = "comment")
    public JAXBElement<String> createComment(String value) {
        return new JAXBElement<String>(_Comment_QNAME, String.class, null, value);
    }

}
/*
 * Copyright (c) 2010-2017 AdroitLogic Private Ltd. (https://www.adroitlogic.com/). All Rights Reserved.
 *
 * AdroitLogic PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 */

package test;

import javax.xml.bind.annotation.XmlRootElement;

/**
 * Java class to create objects
 *
 * @author Hasangi Thathsarani
 * @since 17.07
 */

@XmlRootElement(namespace = "", name = "comment")
public class PurchaseType {

    protected String shipTo;
    protected String billTo;
    protected String items;
    protected String orderDate;

    public PurchaseType() {
    }

    public PurchaseType(String shipTo, String billTo, String items, String orderDate) {
        this.shipTo = shipTo;
        this.billTo = billTo;
        this.items = items;
        this.orderDate = orderDate;
    }

    public String getShipTo() {
        return shipTo;
    }

    public void setShipTo(String shipTo) {
        this.shipTo = shipTo;
    }

    public String getBillTo() {
        return billTo;
    }

    public void setBillTo(String billTo) {
        this.billTo = billTo;
    }

    public String getItems() {
        return items;
    }

    public void setItems(String items) {
        this.items = items;
    }

    public String getOrderDate() {
        return orderDate;
    }

    public void setOrderDate(String orderDate) {
        this.orderDate = orderDate;
    }
}

Now you are ready to test the sample.

In this topic
In this topic
Contact Us