Technology Blogs by Members
Explore a vibrant mix of technical expertise, industry insights, and tech buzz in member blogs covering SAP products, technology, and events. Get in the mix!
cancel
Showing results for 
Search instead for 
Did you mean: 
bhalchandraswcg
Contributor
0 Kudos

Previous – Messaging Gateway | Index | Next – Transactional Client


This week, we'll study the next pattern in the Messaging Endpoints category known as Messaging Mapper.

When do I use this pattern?


This pattern is used to map the Business Object structure to Messaging structure and Messaging structure to Business Object structure. Using a Messaging Mapper decouples the Application code from Messaging code.

Note that Messaging Mapper is implemented in the Message Endpoint and not in the middleware.

Finally, the messaging structure can be a Canonical Data Model as well. Where Canonical Data Model is used, a Message Translator could be used if the Message Endpoint cannot implement a Messaging Mapper.

Messaging Mapper in CPI


Similar to Messaging Gateway, this pattern is not meant for middleware but how Message Endpoints should design for using the Middleware.

I'll reuse the integration flow from the Messaging Gateway blog.

Messaging Mapper in Java


In this blog, we'll implement these classes/enums:

  • Temperature class represents temperature. It has a value and the unit.

  • Unit is an enum that has two units: Celcius and Fahrenheit.

  • TemperatureMapper class implements two static methods. The first method maps the Temperature business object to an XML input message. The second method maps the output XML message to Temperature business object.


Similar to the Messaging Gateway blog, these two classes are also required:

  • TemperatureGateway class that acts as a Messaging Gateway.

  • Application class that accepts temperature in degree Celcius (°C), converts it to degree Fahrenheit (°F) using TemperatureGateway and displays the temperature on both scales.


Temperature Class


Temperature is a POJO class that represents temperature by the properties value and the associated unit.
public class Temperature {

private double value;
private Unit unit;

public double getValue() {
return value;
}

public void setValue(double value) {
this.value = value;
}

public Unit getUnit() {
return unit;
}

public void setUnit(Unit unit) {
this.unit = unit;
}

public String toString() {
return value + " " + unit;
}
}

Unit Enum


Unit is an enum containing two temperature units: Celcius and Fahrenheit.
public enum Unit {
CELCIUS {
@Override
public String toString() {
return "°C";
}
},
FAHRENHEIT {
@Override
public String toString() {
return "°F";
}
}
}

TemperatureMapper Class


TemperatureMapper class has toMessageBody(Temperature) method to convert the business object to the message and toTemperature(String) method to convert the response from middleware to the business object.

As you may notice, some of the code in this class was in the TemperatureGateway class in the Messaging Gateway blog.

toMessageBody(Temperature)


This simple method creates the message body by inserting temperature value in the payload like so:
public static String toMessageBody(Temperature temperature) {
return "<ns:CelsiusToFahrenheit xmlns:ns=\"https://www.w3schools.com/xml/\"><ns:Celsius>"
+ temperature.getValue() + "</ns:Celsius></ns:CelsiusToFahrenheit>";
}

toTemperature(String)


This method creates a Temperature business object based on the response from middleware like so:
public static Temperature toTemperature(String body) throws Exception {

double value = 0;

XPath xPath = XPathFactory.newInstance().newXPath();
xPath.setNamespaceContext(new NamespaceContext() {

@Override
public Iterator<String> getPrefixes(String namespaceURI) {
return null;
}

@Override
public String getPrefix(String namespaceURI) {
return null;
}

@Override
public String getNamespaceURI(String prefix) {
switch (prefix) {
case "urn":
return "https://www.w3schools.com/xml/";
}
return null;
}
});

try {
value = (double) xPath.evaluate("/urn:CelsiusToFahrenheitResponse/urn:CelsiusToFahrenheitResult",
new InputSource(new StringReader(body)), XPathConstants.NUMBER);
} catch (XPathExpressionException e) {
e.printStackTrace();
throw new Exception("Could not convert temperature", e);
}

Temperature temperature = new Temperature();
temperature.setValue(value);
temperature.setUnit(Unit.FAHRENHEIT);

return temperature;
}

TemperatureGateway Class


With the TemperatureMapper class, the TemperatureGateway solely focuses on code that pertains to invoking the middleware and decoupling the application code from the middleware code.

The steps in the TemperatureGateway class are still the same, however, their implementation leverages the TemperatureMapper class.

Authorise the Request


This step remains the same:
HttpClient client = HttpClient.newBuilder().authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication("<username>", "<password>".toCharArray());
}
}).build();

Invoke the Service


In this step, we leverage the TemperatureMapper to convert a business object into the XML message:
HttpRequest request = HttpRequest
.newBuilder(URI.create("https://<cpi host>/http/CelciusToFahrenheit"))
.POST(BodyPublishers.ofString(TemperatureMapper.toMessageBody(temperature))).build();

HttpResponse<String> response;
try {
response = client.send(request, BodyHandlers.ofString());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
throw new Exception("Could not convert temperature", e);
}

Parse the Response


Parsing the response and converting to business object is done by TemperatureMapper class. This step simply passes the response body to TemperatureMapper to get the Temperature business object like so:
return TemperatureMapper.toTemperature(response.body());

Application Class


Application class uses the Temperature class now instead of using primitive data types like so:
Temperature input = new Temperature();
input.setValue(25);
input.setUnit(Unit.CELCIUS);
System.out.println("Input:\t" + input);

Temperature output = TemperatureGateway.celciusToFahrenheit(input);
System.out.println("Output:\t" + output);

Output


The output is as expected:
Input:	25.0 °C
Output: 77.0 °F

Conclusion


Messaging Mapper can be used in Message Endpoint code to decouple business objects from the message structure. As CPI is an IPaaS, CPI cannot implement the Messaging Mapper pattern. Instead, the systems that invoke CPI should implement the Messaging Mapper pattern where applicable.

References/Further Readings



Hope this helps,
Bala

Previous – Messaging Gateway | Index | Next – Transactional Client

Labels in this area