DataWeave Tip #8: The write Function
Learn about the 'write' function in Mule and how to apply it to allow your applications to properly communicate with various HTTP endpoints.
Join the DZone community and get the full member experience.
Join For FreeOriginally published February 26, 2019
Recently I have been working on a really simple case. When an HTTP server returned an error and a non-empty body, I needed to embed this body into an error structure. Although this is a simple case, I got a problem with implementing it in Mule 4. In the previous Mule edition, it was a little bit simpler. So let's see what it is all about.
Case
First, we have a look at the case that I have to implement. I have a mule application that is calling an external HTTP server via an HTTP request component. When the server responds with an error like 4xx, 5xx, and the returned body will is not empty, we would like to forward that response to the calling application.
In the diagram below, I have depicted a situation where an HTTP server sent a 400 Bad request response back to our application. Then I attach returned the body to my custom error response structure that will be returned to the calling application.
{
"errors": [
{
"status": "400",
"title": "Invalid Attribute",
"detail": "First name must contain at least three characters."
}
]
}
500 Internal Server Error:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><myErrorEnvelope>
<internalCode>123</internalCode>
<description>error details</description>
</myErrorEnvelope>
404 Not Found:
"Not Found"
I would like to return to my client following response:
{
"code": "{{my custom title}}",
"description": "{{detailed description}}",
"content": "{{response body returned by the HTTP server}}"
}
Design
Simple Assignment
I could simply assign the returned content like in the script below. As you can see, the field content
will have a returned payload. Exceptions are packed into an error
object. The response that the HTTP request component received will be packed into the errorMesage
property of the error object.
%dw 2.0
output application/json
---
{
code: error.errorMessage.attributes.statusCode,
description: "Description",
content: error.errorMessage.payload
}
This solution is a simple one, however, the DataWeave transform component will translate the error response into a JSON format. If we do not care to see the original response, this may be a good solution. In my case, I need to see the exact response in the format returned by the server. That is how I found out about the write
funtion.
Write Function
The write function is designed to convert an incoming object into a text string. The function's signature is as follows:
write(object: Any, format: String, conf: Object): String
Arguments:
object
to write. Any type is acceptable. It may be an xml document, json, plain text etc.- Output
format
. Only types supported by DataWeave. By default, application/dw is used. - Additional configuration:
conf
.
In the diagram below, you can find three sample cases. In all cases, we would like to have a written payload in XML. In the first case, we have an XML document as an input. The write function takes it and transforms it into an XML string.
The second case has a JSON input with one root property. The write function takes it and transforms it into an XML string. Transformation works here because JSON has one root property and XML expects that.
The third case has a JSON input with two properties on the root level. The write function tries to transform it, however, it would result in a malformed XML document. Therefore it throws an error.
%dw 2.0
output application/json
---
{
code: error.errorMessage.attributes.statusCode,
description: "Description",
content: write(error.errorMessage.payload, "application/xml")
}
The write function does expect that the supplied object is XML. Here is a sample output of that transformation.
{
"code": 400,
"description": "Description",
"content": "<?xml version='1.0' encoding='windows-1252'?>\n<root>\n <message>Bad request</message>\n</root>"
}
Okay, but I forgot to tell you earlier that I can expect different payload types. What can I do?
How about changing the type to text/plain? It would be the most generic option. But, sadly, it won't work. DataWeave will return an error, for example, the application/json object can't be transformed into text/plain.
In order to fix this, we need to place a component, such as Set Payload or Set Variable, and set its mimeType
attribute to the value's text/plain. After that it will work smoothly.
%dw 2.0
output application/json
---
{
code: error.errorMessage.attributes.statusCode,
description: "Description",
content: write(payload, "text/plain")
}
Summary
Thewrite
function is very helpful and I found out that it may be useful in a variety of places during application design. I found it a bit problematic that it performs also validation so when I have received invalid data this function will throw an error.
Published at DZone with permission of Patryk Bandurski, DZone MVB. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments