Every MuleSoft project starts the same way: you write a camelize function. Then a mask function. Then a date formatter. Then the same collection helpers you wrote on the last three projects.
I got tired of rewriting the same DataWeave utilities, so I built seven reusable modules and published them on Anypoint Exchange. Together they provide 96 production-ready functions backed by 213 MUnit tests — and you can import them into any Mule project with a single Maven dependency.
Here's what's inside and how to use them.
Installation
Add the dependency to your Mule project's pom.xml:
<dependency>
<groupId>{YOUR_ORG_ID}</groupId>
<artifactId>dw-string-utils</artifactId>
<version>1.0.0</version>
<classifier>dw-library</classifier>
</dependency>
Replace {YOUR_ORG_ID} with your Anypoint Organization ID. Repeat for each module you want to use (dw-date-utils, dw-collection-utils, dw-error-handler, dw-xml-helpers, dw-validation-utils, dw-api-utils).
Then import in your DataWeave:
import * from dw::StringUtils
That's it. All functions are immediately available.
Module 1: dw-string-utils (19 functions)
The string module handles case conversion, validation, masking, and formatting — the bread and butter of data transformation.
Highlights
camelize — Convert snake_case or kebab-case to camelCase:
import camelize from dw::StringUtils
---
camelize("user_first_name")
// Output: "userFirstName"
slugify — Generate URL-friendly slugs:
import slugify from dw::StringUtils
---
slugify("Hello World! This is a Test")
// Output: "hello-world-this-is-a-test"
mask — Mask sensitive data, showing only the last N characters:
import mask from dw::StringUtils
---
mask("4111111111111234", 4)
// Output: "************1234"
All 19 Functions
| Function | Description | Example |
|---|---|---|
camelize(s) |
To camelCase |
"hello_world" -> "helloWorld"
|
snakeCase(s) |
To snake_case |
"helloWorld" -> "hello_world"
|
titleCase(s) |
To Title Case |
"hello world" -> "Hello World"
|
truncate(s, len) |
Truncate with "..." |
truncate("Hello World", 8) -> "Hello..."
|
padLeft(s, len, char) |
Left-pad |
padLeft("42", 5, "0") -> "00042"
|
padRight(s, len, char) |
Right-pad |
padRight("42", 5, "0") -> "42000"
|
slugify(s) |
URL slug |
"Hello World!" -> "hello-world"
|
mask(s, visible) |
Mask characters |
mask("1234567890", 4) -> "******7890"
|
isBlank(s) |
Null/empty/whitespace check |
isBlank(" ") -> true
|
isEmail(s) |
Email validation |
isEmail("a@b.com") -> true
|
isNumeric(s) |
Digit-only check |
isNumeric("123") -> true
|
capitalize(s) |
Capitalize first char |
"hello" -> "Hello"
|
removeWhitespace(s) |
Strip all whitespace |
"a b c" -> "abc"
|
reverse(s) |
Reverse string |
"hello" -> "olleh"
|
countOccurrences(s, sub) |
Count substrings |
countOccurrences("banana", "an") -> 2
|
substringBefore(s, sep) |
Text before first separator |
substringBefore("foo:bar", ":") -> "foo"
|
substringAfter(s, sep) |
Text after first separator |
substringAfter("foo:bar", ":") -> "bar"
|
wrap(s, prefix, suffix) |
Wrap with prefix/suffix |
wrap("hi", "[", "]") -> "[hi]"
|
initials(s) |
Extract initials |
initials("John Doe") -> "JD"
|
Module 2: dw-date-utils (14 functions)
Date manipulation in DataWeave is powerful but verbose. This module wraps the most common operations into clean, named functions.
Highlights
addDays — Date arithmetic without period literals:
import addDays from dw::DateUtils
---
addDays(|2026-02-15|, 10)
// Output: |2026-02-25|
diffDays — Calculate the difference between two dates:
import diffDays from dw::DateUtils
---
diffDays(|2026-02-10|, |2026-02-15|)
// Output: 5
toEpoch / fromEpoch — Unix timestamp conversion:
import toEpoch, fromEpoch from dw::DateUtils
---
{
epoch: toEpoch(|2026-02-15T00:00:00Z|),
back: fromEpoch(1771200000)
}
All 14 Functions
| Function | Description |
|---|---|
toISO(d) |
DateTime to ISO 8601 string |
toEpoch(d) |
DateTime to Unix epoch seconds |
fromEpoch(n) |
Unix epoch seconds to DateTime |
addDays(d, n) |
Add/subtract N days |
addMonths(d, n) |
Add/subtract N months |
diffDays(d1, d2) |
Days between two dates |
formatDate(d, fmt) |
Custom date formatting |
isWeekend(d) |
Saturday/Sunday check |
startOfMonth(d) |
First day of the month |
endOfMonth(d) |
Last day of the month |
isLeapYear(y) |
Leap year check |
quarter(d) |
Calendar quarter (1-4) |
toBusinessDay(d) |
Advance to next business day if weekend |
daysBetweenBusiness(d1, d2) |
Count business days between dates |
Module 3: dw-collection-utils (19 functions)
Arrays and objects are the core data structures in every integration. This module adds the operations DataWeave doesn't have built-in.
Highlights
chunk — Split arrays into fixed-size batches:
import chunk from dw::CollectionUtils
---
chunk([1, 2, 3, 4, 5, 6, 7], 3)
// Output: [[1, 2, 3], [4, 5, 6], [7]]
Perfect for batch processing — split a payload of 10,000 records into chunks of 200 before sending to a rate-limited API.
deepMerge — Recursively merge objects (not just top-level):
import deepMerge from dw::CollectionUtils
---
deepMerge(
{name: "Acme", address: {city: "NYC", zip: "10001"}},
{address: {city: "LA"}, active: true}
)
// Output: {name: "Acme", address: {city: "LA", zip: "10001"}, active: true}
pick / omit — Select or exclude object keys:
import pick, omit from dw::CollectionUtils
---
{
selected: pick({a: 1, b: 2, c: 3, d: 4}, ["a", "c"]),
excluded: omit({a: 1, b: 2, c: 3, d: 4}, ["b", "d"])
}
// Both output: {a: 1, c: 3}
All 19 Functions
| Function | Description |
|---|---|
chunk(arr, size) |
Split array into chunks |
compact(arr) |
Remove nulls and empty strings |
intersection(a, b) |
Elements in both arrays |
difference(a, b) |
Elements in A not in B |
union(a, b) |
Combine and deduplicate |
pick(obj, keys) |
Keep only specified keys |
omit(obj, keys) |
Remove specified keys |
deepMerge(a, b) |
Recursive object merge |
pivot(arr) |
Rows to columns |
unpivot(obj) |
Columns to rows |
flattenKeys(obj, sep) |
Flatten to dot-notation |
unique(arr) |
Remove duplicates |
partition(arr, fn) |
Split by predicate |
indexBy(arr, key) |
Array to lookup map |
countBy(arr, fn) |
Group and count |
zip(a, b) |
Zip two arrays into pairs |
sortByKey(obj) |
Sort object keys alphabetically |
frequencies(arr) |
Count occurrences of each element |
mapValues(obj, fn) |
Apply function to every object value |
Module 4: dw-error-handler (10 functions)
Standardized error handling across all your Mule APIs. Build consistent error responses, classify errors for retry logic, and sanitize sensitive data before logging.
Highlights
classifyError — Map Mule error types to categories:
import classifyError from dw::ErrorHandler
---
classifyError(error)
// Returns: "VALIDATION", "AUTHENTICATION", "TIMEOUT", "CONNECTIVITY", etc.
isRetryable — Should this error trigger a retry?
import isRetryable from dw::ErrorHandler
---
isRetryable(error)
// Returns true for: TIMEOUT, CONNECTIVITY, 429, 502, 503, 504
buildErrorResponse — Consistent JSON error format:
import buildErrorResponse from dw::ErrorHandler
---
buildErrorResponse(404, "Not Found", "Customer ID 12345 does not exist")
// Output: { error: { code: 404, message: "Not Found", detail: "...", timestamp: "..." } }
All 10 Functions
| Function | Description |
|---|---|
buildErrorResponse(code, msg, detail) |
Standardized JSON error |
classifyError(error) |
Categorize Mule errors |
isRetryable(error) |
Check if transient/retryable |
errorToLog(error) |
Single-line log string |
sanitizeError(error) |
Strip sensitive data |
wrapWithCorrelation(error, id) |
Add correlation ID |
httpStatusFromError(type) |
Map error to HTTP status |
buildFaultResponse(code, msg) |
SOAP fault format |
aggregateErrors(errors) |
Combine multiple errors into one response |
toAlertPayload(error, channel) |
Format error as alert/notification payload |
Module 5: dw-xml-helpers (12 functions)
XML is everywhere in enterprise integrations — SOAP services, B2B feeds, legacy systems. This module handles the messy parts: namespaces, CDATA, attributes, and structural transformations.
Highlights
stripNamespaces — Remove all namespace prefixes:
import stripNamespaces from dw::XmlHelpers
---
stripNamespaces(payload)
// Converts {"ns0:Order": {"ns0:Item": ...}} to {"Order": {"Item": ...}}
xpathLike — Navigate XML structures with dot-path syntax:
import xpathLike from dw::XmlHelpers
---
xpathLike(payload, "root.customers.customer")
// Returns the nested element without chained null-checks
validateStructure — Verify XML has expected elements before processing:
import validateStructure from dw::XmlHelpers
---
validateStructure(payload, {root: {header: {}, items: {}}})
// Output: { valid: true, missing: [], extra: [] }
All 12 Functions
| Function | Description |
|---|---|
nsAware(xml, uri, prefix) |
Apply namespace prefix |
stripNamespaces(xml) |
Remove all namespace prefixes |
extractAttributes(xml, elem) |
Get @ attributes |
cdataWrap(value) |
Wrap as CDATA |
cdataUnwrap(cdata) |
Extract from CDATA |
xmlToFlat(xml, sep) |
Flatten to dot-notation |
flatToXml(obj, sep) |
Dot-notation to nested XML |
mergeXmlNodes(a, b) |
Deep merge XML trees |
xpathLike(xml, path) |
Dot-path selector |
validateStructure(xml, schema) |
Validate expected keys |
soapEnvelope(body, header) |
Build SOAP 1.1 envelope structure |
xmlToString(xml) |
Serialize object to XML-like string |
Module 6: dw-validation-utils (12 functions)
Input validation is the first line of defence in any API. This module provides composable validators that return consistent {valid, error} results you can chain together.
Highlights
validateAll — Validate an entire payload against a rules object in one pass:
import validateAll from dw::ValidationUtils
---
validateAll(payload, {
name: { required: true, minLength: 2, maxLength: 50 },
email: { required: true, pattern: "^[^@]+@[^@]+\\.[^@]+$" },
age: { min: 1, max: 150 }
})
// Output: { valid: false, errors: [{field: "email", error: "..."}] }
All 12 Functions
| Function | Description |
|---|---|
isRequired(val, field) |
Non-null, non-empty check |
minLength(s, min, field) |
Minimum string length |
maxLength(s, max, field) |
Maximum string length |
inRange(n, min, max, field) |
Numeric range (inclusive) |
matchesPattern(s, regex, field) |
Regex validation |
isValidDate(s, fmt, field) |
Date format validation |
isOneOf(val, allowed, field) |
Allowed-set check |
isUUID(s) |
UUID v4 format check |
isURL(s) |
URL format check |
isPhone(s) |
E.164 phone format check |
validateAll(obj, rules) |
Bulk validate against rules |
hasRequiredFields(obj, fields) |
Check all required fields present |
Module 7: dw-api-utils (10 functions)
REST API plumbing — pagination envelopes, query string parsing, HATEOAS links, field projection, and rate-limit headers.
Highlights
paginate — Wrap results in a standard pagination envelope:
import paginate from dw::ApiUtils
---
paginate(payload.results, 1, 20)
// Output: { data: [...], page: 1, pageSize: 20, totalPages: 5 }
All 10 Functions
| Function | Description |
|---|---|
paginate(data, page, size) |
Pagination envelope |
toQueryString(obj) |
Object to URL query string |
fromQueryString(qs) |
Query string to object |
buildLink(base, rel) |
Single HATEOAS link |
buildHateoas(base, rels) |
Full HATEOAS links map |
sortBy(arr, field, dir) |
Sort array of objects |
fieldSelect(data, fields) |
Sparse fieldset projection |
toCSV(arr, headers) |
Array to CSV string |
rateLimitInfo(headers) |
Extract rate-limit metadata |
apiResponse(data, meta) |
Standard API envelope |
Testing
Every function is backed by MUnit tests. Across all 7 modules: 96 functions, 213 tests.
You can run them locally if you clone the repo:
cd modules/dw-string-utils
mvn test
Get Started
- Browse the source — github.com/shakarbisetty/mulesoft-cookbook/tree/main/modules
-
Add the Maven dependency to your
pom.xml -
Import and use —
import * from dw::StringUtils
These modules are designed to be lightweight, well-tested, and easy to extend. If you find a bug or want to add a function, PRs are welcome.
Which utility functions do you rewrite on every MuleSoft project? Let me know in the comments — if it's useful enough, I'll add it to the modules.
Top comments (0)