Over a million developers have joined DZone.

Externalize Scripts

DZone 's Guide to

Externalize Scripts

In this article, compare assets that Mule gives as to achieve externalization of such things in Mule 3 and Mule 4.

· Integration Zone ·
Free Resource

I like the idea of clean easily read XML configuration in my Mule projects. Therefore, I externalize DataWeave transformations, SQL queries, and other content. In this article, I will compare assets that Mule gives as to achieve externalization of such things in Mule 3 and Mule 4.

Mule 3

It is up to the component if we can load content from the resource or not. The most obvious example is DataWeave Transform Message component that allows that. We have such possibility for Database component using Template query.

Externalize SQL script using Template Query
Externalize SQL script using Template Query
Externalize DataWeave script
Externalize DataWeave script

As a result, we got a clear XML configuration as depicted below:

<sub-flow name="get-partner-db-subflow">
  <db:select config-ref="DB" target="#[flowVars.partner]" doc:name="get Partner">
    <db:template-query-ref name="getPartner.sql"/>
      <db:in-param name="id" value="#[flowVars.id]"/>
    <dw:set-payload resource="classpath:templates/dwl/transformToPartner.dwl"/>

It is much more readable just by looking at XML we may infer what the code does on the high level. If we want to get know better transformation we have a path to the file that we can examine.

Mule 4

First, I was not aware of the new functionality delivered with this Mule version. I had a case to rewrite the application to the new runtime. The application makes a couple of database calls.

When I drop Select operation on canvas, I could not find any way to externalize my SQL statement. In Anypoint Studio I had a field called SQL Query Text only. Below, you can find the XML snippet.

<db:select doc:name="Select records"config-ref="Database_Config">
    WHERE age > 19

File Placeholder Syntax

Then, I found out that Mule has introduced new syntax to load content from the files:

${file:: path-to-the-file/ filename}

We have three parts. The first one, file::, implies that the engine should load the file specified after the double colon. Next, you write the file name and path to it. The address is relative to the resources folder.

As you may remember, we use similar syntax to load properties like ${http.port}. Mule will try to resolve property http.port before project startup. If property is missing, the project won't start. If property is present, placeholder ${} will be replaced with the loaded value for example 8091.

File placeholder syntax is pretty much the same. Mule will look for the file just before startup and won't start if the file is missing. After the content will be loaded, it will be put in place of the placeholder ${}.


This functionality is not only dedicated to load DataWeave files. We may load any file that we want. However, when we would like to load DataWeave, we need to remember to embrace our call within expression brackets #[]. Otherwise, we may get the text of our transformation :).


Static SQL Statement

File: src/main/resources/sql/select-records.sql

<db:select doc:name="Select records" config-ref="Database_Config">

Brief description: SQL statement from the file select-records.sql will be put between <db:sql> tags.

Choice Logic

File: src/main/resources/dwl/rule.dwl

Content: sizeOf(payload) > 15

Brief description: content from the file rule.dwl will be put in expression attribute.


I guess that externalizing choice logic may be useful only if the expression is really complicated and long. For other cases do not use it in order to maintain greater readability.

Mock Response

File: src/test/resources/test_data/system-response.dwl


Why did I put the response in the dwl file instead of, for example, JSON? The answer is really simple. Using DataWeave, I can transform and infer metadata for next event processors.
Often, I have a case that the input should be a Java object, but I have its JSON representation. Therefore, I use the dwl file with output set to application/java but in the body, having a JSON object.

Brief description: As you may see, I enclosed a file placeholder with expression brackets #[]. I used this because the content of the dwl file is a DataWeave script, and it needs to be evaluated at runtime. If I would omit the expression brackets, my mock component would return string having transformation text.


File: src/test/resources/test_data/record-to-compare.json

<choice doc:name="Choice">
  <when expression="${file::dwl/rule.dwl}">
    <logger level="INFO" doc:name="Logger" />
  <otherwise >
    <set-payload value="#[payload]" doc:name="Set Payload" doc:id="ddd0085c-1d3b-4428-bc6d-fa73598ee812" />

Brief description: I could provide inline object to compare in equalTo function. However, I decided to externalize all examples. We may use file placeholder even in the middle of DataWeave as in the example above.


In Anypoint Studio 7.3, using file placeholder, you may have errors like this one:
Description Resource Path Location Type
Invalid input '{', expected ~ (line 1, column 2):

For the time being, just ignore it. You will be able to run and build your project without any problems. That is an issue with Studio.


I think that file placeholder is a really great feature that gives more flexibility than we have seen before in Mule 3. Now, we may use this wherever we like even in the middle of a DataWeave transformation. It makes XML configuration files more concise and readable. A small drawback that I see currently is a problem with Anypoint Studio that misinforms you.

Let me know what you think in the comments section. 

integration ,database ,mule ,tutorial ,mule tutorial ,integration tutorial ,database tutorial ,externalize scripts

Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}