There are situations where you get a response from a backend and actually need to change the response. Not so much in the backend, but more in the WSO2 Enterprise Integrator. In this blog we’ll look into how to create a new mapped response.
We created a simple database using Mockaroo, a great service for creating mock data. The great thing is that the data looks more realistic than the often used data sets ‘Jane Doe, John Doe’. For example, I created a database with a table (cars) with the following layout:
Field name | Data type |
Id | INT, |
First Name | VARCHAR(50), |
Last Name | VARCHAR(50), |
VARCHAR(50), | |
Car | VARCHAR(50), |
Year | VARCHAR(50), |
In this database I have 1000 randomly generated records that will allow multiple selections. From the simple select * from cars to select car, count(car) from cars group by car.
First of all, we’ll make this database accessible from the WSO2 Enterprise Integrator (EI) as a datasource. I’m opting for a generated datasource since that is the quickest solution for accessing the data.
This blog builds on several previous blogs and I won’t describe steps like installing WSO2 Products etc.
We have an WSO2 EI up and running and create a datasource that allows a connection to the MySQL / MariaDB database and table. This of course requires the mysql*.jar file to be deployed in the [EI-HOME]/lib directory and a restart of WSO2 Enterprise Integrator. To create the datasource I use the Management UI of the EI since the interface is better than the Developer Studio support. The open source version of WSO2 Enterprise Integrator 6.4.0 unfortunately corrupts a datasource after a restart. This is fixed in WUM updates, but these are available to customers with product support.
Datasources can be configured on the Configure tab. This is the configuration setup. I’m running MariaDB on my local machine. The database is called test and I am using the root / root credentials. However, this is not the idea when you do this in any other setting than a blog like this.
I can test the connection and when successful, save the connection. On the Main tab I can now select the Generate option under Datasource. By selecting the datasource and database name, I start generating the services.
By selecting the table(s) and selecting single service when pressing next, I end up with a Soap based.
The generation created two services:
- – insert_cars_operation;
- – select_all_car_operation.
The names are self-explanatory. When I try out the second service, I get a response with 1,000 records, the exact number of records in the database.
Furthermore, I am going to add a resource to the dataservice and make it possible to use REST calls with this service.
The dataservice now has this addition in the XML source view.
<resource method="GET" path="/cars">
<call-query href="select_all_cars_query"/>
</resource>
This allows me to do a GET on http://localhost:8280 /services/carsservices/cars in SoapUI.
However, the response is still XML based. But there is a solution for that.
Solution: change the message type
We are creating an API and call the endpoint. In the out sequence we change the messageType to ‘application/json’ so we get a true JSON response.
The setup is simple:
Or in the source
<?xml version="1.0" encoding="UTF-8"?>
<api context="/car" name="carAPI" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<send>
<endpoint>
<http method="get" uri-template="http://localhost:8280/services/carsservices/cars"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
The response is a JSON list of cars.
Let’s say that we would like a different kind of message, with only the first name, car and year.
We can of course change the dataservice to select only those fields, but there is also another way (this is often the case with WSO2).
What we’re going to do is to retrieve the message as usual and use one for each mediator with the message, creating a new message layout. We will do that in XML and only change it to JSON when the mediaton is done.
This is because XML is the native message type for the Enterprise Integrator. By setting the messageType to application/json it will be transformed to json before being sent back to the client.
So, how are we going to do that? Well, in the out sequence we will use for each mediator to change the layout of the message. For each mediator it’s a little bit different from the iterate, an aggregate mediator, and is actually meant for message mediation and change.
The source code is still very plain and simple. We don’t necessarily need to do this in the out sequence. A set up where we used the in sequence and a call mediator to call the API and then continuing in the in sequence with the for each mediation would also work. The only thing we need to do of course is to do a response mediator to send the message back to the client.
The graphical overview doesn’t say that much about what we’re actually doing in the PayloadFactory Mediator, so let’s take a look at the source code.
<?php<?xml version="1.0" encoding="UTF-8"?>
<api context="/cars2" name="carapi2" xmlns="http://ws.apache.org/ns/synapse">
<resource methods="GET">
<inSequence>
<send>
<endpoint>
<http method="get" uri-template="http://localhost:8280/services/carsservices/cars"/>
</endpoint>
</send>
</inSequence>
<outSequence>
<foreach description="" expression="$ctx:body//ns:Entries/ns:Entry" xmlns:ns="http://ws.wso2.org/dataservice"xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
<sequence>
<payloadFactory media-type="xml">
<format>
<car>
<owner>$1</owner>
<make>$2</make>
<year>$3</year>
</car>
</format>
<args>
<arg evaluator="xml" expression="$ctx:body//ns:first_name"/>
<arg evaluator="xml" expression="$ctx:body//ns:car"/>
<arg evaluator="xml" expression="$ctx:body//ns:year"/>
</args>
</payloadFactory>
</sequence>
</foreach>
<send/>
</outSequence>
<faultSequence/>
</resource>
</api>
In the out sequence we use a for each to retrieve every single entry in the response message. The message itself is part of the soap body (we use $ctx:body to reference that) and within the body it will use an XPATH statement (//Entries/Entry) to get every message. Since the for each mediator goes through the entire message in the PayloadFactory Mediator allows us to change the message, we can actually create a new message layout.
If you haven’t worked with the PayloadFactory Mediator, it’s a very simple mediation. You define the format you want to message to have, including parameters inside the format. In this case it will create a car tag with three sub- tags: owner, make and year. Each of these values and each of these tags will have the original corresponding value. It’s really as simple as that to change the format. True, this is a simple example, but this is also something that you can elaborate on and make it into something more complex.
As you can see the response is a neat XML message.
The only thing we need to do now is change it to json. The solution is simple: just add a property called messageType and set it to application/json.
<property name="messageType" scope="axis2" type="STRING" value="application/json"/>
This simple one line changes the output from XML to JSON.
{
"Entries": {
"car": [{
"owner": "Joceline",
"make": "Lexus",
"year": 2010
},
{
"owner": "Lavena",
"make": "Ford",
"year": 2002
},
{
"owner": "Rodd",
"make": "Mazda",
"year": 1995
}
]
}
}