Skip to Content
Technical Articles
Author's profile photo Bhalchandra Wadekar

EIPinCPI – Messaging Mapper

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

Assigned Tags

      Be the first to leave a comment
      You must be Logged on to comment or reply to a post.