DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • JavaScript Type Conversion and Coercion
  • Adding Two Hours in DataWeave: Mule 4
  • Secrets in Code: Understanding Secret Detection and Its Blind Spots
  • From Zero to Meme Hero: How I Built an AI-Powered Meme Generator in React

Trending

  • DevOps and Platform Engineering Readiness Checklist: Everything Needed for a Scalable, Secure, High-Velocity Delivery Platform
  • Liquibase: Database Change Management and Automated Deployments
  • Spec-Driven Integration: Turning API Sprawl Into a Governed Capability Fleet for AI
  • Engineering LLMOps: Building Robust CI/CD Pipelines for LLM Applications on Google Cloud
  1. DZone
  2. Coding
  3. JavaScript
  4. What's New in Mule 4.4 - With Example

What's New in Mule 4.4 - With Example

This blog covers the new features of Mule 4.4 including Enhancements on Logging mechanism, Correlation ID Management, Dataweave (v2.4.0), and Flagging mechanism.

By 
Ankur Bhuyan user avatar
Ankur Bhuyan
·
Nov. 24, 21 · Code Snippet
Likes (3)
Comment
Save
Tweet
Share
22.9K Views

Join the DZone community and get the full member experience.

Join For Free

Introduction

Mule 4.4 version was released on November 2021. This version includes:

  • Enhancements on Logging mechanism
  • Correlation ID Management
  • Dataweave (v2.4.0)
    • New properties for data formats
    • New function modules and features
  • Flagging mechanism

Logging Mechanism

In Mule 4.4 logging mechanism is enhanced with MDC (Mapped Diagnostic Context). The MDC concept is introduced to maintain the complex distributed application logs, which means multiple client logs can be simplified for auditing using MDC. To know more about the concept you can follow here.

  • To achieve the MDC logging feature you have to enable using log4j2.xml as like below:
XML
 
<Appenders>
	<Console name="Console" target="SYSTEM_OUT">
		<PatternLayout pattern="%-5p %d [%t] [%MDC] %c: %m%n" />
	</Console>
</Appenders>


  • MDC logging introduces three operations and these operations are included as part of the tracing module.
  1. set-logging-variable
  2. remove-logging-variable
  3. clear-logging-variables
XML
 
<sub-flow name="set-logging-variables-subFlow" doc:id="f6c40d92-bb0d-4761-a8f7-c3032cae8135">
	<tracing:set-logging-variable doc:name="Set full name" doc:id="2b959c68-71eb-4181-b7c1-e2402b80734e" variableName="registerName" value='#[payload.firstName ++ " " ++ payload.lastName]'/>
	<tracing:set-logging-variable doc:name="Set email" doc:id="b0a675f8-bbac-49d5-af92-376aaec4e556" variableName="registerEmail" value='#[payload.email]'/>
</sub-flow>

<sub-flow name="remove-logging-variables-subFlow" doc:id="f295e9a7-2688-4ed4-8803-3c0273457f35">
	<tracing:remove-logging-variable doc:name="Remove full name" doc:id="e9b7d7cb-c3e7-44ce-821a-67c80d290ed9" variableName="registerName"/>
	<tracing:remove-logging-variable doc:name="Remove email" doc:id="4e6f8fa0-1fea-40e7-b97f-b5c2c42fae54" variableName="registerEmail"/>
</sub-flow>
    
<sub-flow name="clear-all-logging-variables-subFlow" doc:id="68ff8a46-ffe4-41a2-80f0-4839191159d4">
	<tracing:clear-logging-variables doc:name="Clear all logging variables" doc:id="dcd7021d-9bd9-4038-983a-805f68a699a0" />
</sub-flow>


  • Output

SystemVerilog
 
INFO  2021-11-19 03:26:18,911 [[MuleRuntime].uber.02: [mule-4.4.0-api].post:\mdc\settingAndRemovingVariables:mule-4.4.0-config.CPU_LITE @3a5f9a3] [{correlationId=01c79e99_f64b_414d_a08a_e55e85538c67, processorPath=post:\mdc\settingAndRemovingVariables:mule-4.4.0-config/processors/1, [email protected], registerName=Ankur Bhuyan}] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: After SETTING logging variables : {
    "firstName": "Ankur",
    "lastName": "Bhuyan",
    "email": "[email protected]"
}
INFO  2021-11-19 03:26:19,237 [[MuleRuntime].uber.05: [mule-4.4.0-api].post:\mdc\settingAndRemovingVariables:mule-4.4.0-config.CPU_INTENSIVE @3d9d1ec2] [{correlationId=01c79e99_f64b_414d_a08a_e55e85538c67, processorPath=post:\mdc\settingAndRemovingVariables:mule-4.4.0-config/processors/3, [email protected], registerName=Ankur Bhuyan}] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: After payload modified : {
  "message": "Request processed successfully for settingAndRemovingVariables"
}
INFO  2021-11-19 03:26:19,240 [[MuleRuntime].uber.05: [mule-4.4.0-api].post:\mdc\settingAndRemovingVariables:mule-4.4.0-config.CPU_INTENSIVE @3d9d1ec2] [{correlationId=01c79e99_f64b_414d_a08a_e55e85538c67, processorPath=post:\mdc\settingAndRemovingVariables:mule-4.4.0-config/processors/5}] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: After REMOVING logging variables : {
  "message": "Request processed successfully for settingAndRemovingVariables"
}


Correlation ID Management 

  • We can generate our required pattern of correlation ID using configuration
XML
 
<configuration doc:name="Configuration" doc:id="71116c74-fd1e-4630-948a-c6fd634ad536" correlationIdGeneratorExpression="#[uuid() replace /-/ with('_')]" />


  • Correlation ID can be managed with a tracing module, with which we can define our strategy to maintain the Correlation ID logging in each flow.
XML
 
<tracing:with-correlation-id doc:name="With CorrelationID" doc:id="8b9d6c3c-250b-457e-9c2d-a3dd498c3b85" correlationId="#[correlationId ++ '_' ++ Mule::lookup('prepare-endpoint', attributes.relativePath)]">
	<logger level="INFO" doc:name="Log payload inside tracing:with-correlation-id" doc:id="086ce669-b0fb-4a7e-87b3-3ec40dedcc0c" message="Logging inside tracing:with-correlation-id"/>
</tracing:with-correlation-id>


  • Output

SystemVerilog
 
INFO  2021-11-19 02:47:44,809 [[MuleRuntime].uber.05: [mule-4.4.0-api].post:\mdc\loggingWithCorrelationId:mule-4.4.0-config.CPU_LITE @5c1ab984] [{correlationId=65735d9f_3369_458c_aa3e_155b289570a5_loggingWithCorrelationId, processorPath=post:\mdc\loggingWithCorrelationId:mule-4.4.0-config/processors/0/processors/0}] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: Logging inside tracing:with-correlation-id


Dataweave 2.4.0

  • New properties for data formats: Four new properties for data formats provided, to know more you can follow here.
  • New dataweave modules: There are four new dataweave modules added in version 2.4.0.
  1. dw::core::Dates
  2. dw::util::Coercions
  3. dw::util::Math
  4. dw::util::Periods 
  • Enhancement On Existing Modules

a. dw::core::Strings 

  • collapse: It is used for converting each string(including whitespaces) into an array. 
JSON
 
%dw 2.0
import collapse from dw::core::Strings
output application/json
---
{
  "collapseWithoutSpace": collapse("ankur"),
  "collapseWithSpace": collapse("a n kur"),
  "collapseNull": collapse(null)
}

========= OUTPUT =========
{
 "collapseWithoutSpace": ["a","n","k","u","r"],
 "collapseWithSpace": ["a"," ","n"," ","k","u","r"],
 "collapseNull": null
}


  • countCharactersBy: It uses to count the number of characters with a given condition.
JavaScript
 
%dw 2.0
import countCharactersBy,isNumeric from dw::core::Strings
output application/json
---
{
 "countCharactersBy_isNumeric_12345" : "12345" countCharactersBy isNumeric($),
 "countCharactersBy_isNumeric_a1b2c3d4" : "a1b2c3d4" countCharactersBy isNumeric($),
 "countCharactersBy_isEven_567" : "567" countCharactersBy isEven($),
 "countCharactersBy_isOdd_567" : "567" countCharactersBy isOdd($)
}

========= OUTPUT =========
{
  "countCharactersBy_isNumeric_12345": 5,
  "countCharactersBy_isNumeric_a1b2c3d4": 4,
  "countCharactersBy_isEven_567": 1,
  "countCharactersBy_isOdd_567": 2
}


  • countMatches: Its return the count of matching record (string, number, special character, etc)
JavaScript
 
%dw 2.0
import countMatches from dw::core::Strings
output application/json
---
{
 "countMatches_for_no_word" : "ankur jyoti bhuyan" countMatches "xyz",
 "countMatches_for_single_word" : "ankur jyoti bhuyan" countMatches "ankur",
 "countMatches_for_multiple_word" : "ankur jyoti ankur" countMatches "ankur",
 "countMatches_for_number" : "ankur123ankur12" countMatches "123",
 "countMatches_for_character" : "~ankur~ankur12" countMatches "~"
}

========= OUTPUT =========
{
  "countMatches_for_no_word": 0,
  "countMatches_for_single_word": 1,
  "countMatches_for_multiple_word": 2,
  "countMatches_for_number": 1,
  "countMatches_for_character": 2
}


  • everyCharacter: It checks the given condition for each character 
JavaScript
 
%dw 2.0
import everyCharacter, isNumeric from dw::core::Strings
output application/json
---
{
 "everyCharacter_is_numeric" : "123456" everyCharacter isNumeric($),
 "everyCharacter_is_not_numeric" : "123xyz456" everyCharacter isNumeric($),
 "everyCharacter_is_equal_to_A" : "AAA" everyCharacter $ == "A",
 "everyCharacter_is_equal_to_3" : "333" everyCharacter $ == "3"
}

========= OUTPUT =========
{
  "everyCharacter_is_numeric": true,
  "everyCharacter_is_not_numeric": false,
  "everyCharacter_is_equal_to_A": true,
  "everyCharacter_is_equal_to_3": true
}


  • first: Its return first provided characters including whitespaces
JavaScript
 
%dw 2.0
import first from dw::core::Strings
output application/json
---
{
 "first_5_character" : "Ankur Jyoti Bhuyan" first 5,
 "first_11_character" : "Ankur123 Jyoti Bhuyan" first 11
}

========= OUTPUT =========
{
  "first_5_character": "Ankur",
  "first_11_character": "Ankur123 Jy"
}


  • last: Its return last provided characters including whitespaces
JavaScript
 
%dw 2.0
import last from dw::core::Strings
output application/json
---
{
 "last_6_character" : "Ankur Jyoti Bhuyan" last 6,
 "last_15_character" : "Ankur 12c& JyotiBhuyan" last 15
}

========= OUTPUT =========
{
  "last_6_character": "Bhuyan",
  "last_15_character": "2c& JyotiBhuyan"
}


  • hammingDistance: It returns the Hamming distance between two strings. It is a metric for comparing two binary data strings. It uses an XOR operation to measure the distance between two sequences.
JavaScript
 
%dw 2.0
import hammingDistance from dw::core::Strings
output application/json
---
{
 "hammingDistance_between_1_and_1" : "1" hammingDistance "1",
 "hammingDistance_between_0_and_1" : "0" hammingDistance "1",
 "hammingDistance_between_0_and_5" : "0" hammingDistance "5",
 "hammingDistance_between_010_and_011" : "010" hammingDistance "011",
 "hammingDistance_between_010_and_111" : "010" hammingDistance "111",
 "hammingDistance_between_010_and_101" : "010" hammingDistance "101",
 "hammingDistance_between_011_and_101" : "011" hammingDistance "101",
 "hammingDistance_between_011_and_111" : "011" hammingDistance "111",
 "hammingDistance_between_011_and_101" : "011" hammingDistance "101"
}

========= OUTPUT =========
{
  "hammingDistance_between_1_and_1": 0,
  "hammingDistance_between_0_and_1": 1,
  "hammingDistance_between_0_and_5": 1,
  "hammingDistance_between_010_and_011": 1,
  "hammingDistance_between_010_and_111": 2,
  "hammingDistance_between_010_and_101": 3,
  "hammingDistance_between_011_and_101": 2,
  "hammingDistance_between_011_and_111": 1,
  "hammingDistance_between_011_and_101": 2
}


  •  levenshteinDistance: It returns the Levenshtein distance between two strings. It is a metric for measuring the difference between two sequences.  The Levenshtein distance between two words is the minimum number of single-character edits (insertions, deletions, or substitutions) required to change one word into the other. 
JavaScript
 
%dw 2.0
import levenshteinDistance from dw::core::Strings
output application/json
---
{
 "levenshteinDistance_between_kitten_and_sitting" : "kitten" levenshteinDistance "sitting",
 "levenshteinDistance_between_Sunday_and_Saturday" : "Sunday" levenshteinDistance "Saturday"
}

========= OUTPUT =========
{
  "levenshteinDistance_between_kitten_and_sitting": 3,
  "levenshteinDistance_between_Sunday_and_Saturday": 3
}


  • lines: It converts a string to an array when it finds \n \r etc.
JavaScript
 
%dw 2.0
import lines from dw::core::Strings
output application/json
---
{
 "break_lines_to_array": lines("Hello Ankur,\nWelcome to Dataweave 2.4"),
 "break_lines_to_array": lines("1\n2\r3\n4"),
 "break_null": lines(null)
}

========= OUTPUT =========
{
  "break_lines_to_array": ["Hello Ankur,","Welcome to Dataweave 2.4"],
  "break_lines_to_array": ["1","2","3","4"],
  "break_null": null
}  


  • mapString: It applies to every character of a string, based on the provided condition it returns the response.
JavaScript
 
%dw 2.0
import mapString,isNumeric from dw::core::Strings
output application/json
---
{
 "mapString_filter_non_numeric": ("~_123abc456_~" mapString if (isNumeric($)) "" else $),
 "mapString_filter_only_numeric": ("~_123abc456_~" mapString if (!isNumeric($)) "" else $)
}

========= OUTPUT =========
{
  "mapString_filter_non_numeric": "~_abc_~",
  "mapString_filter_only_numeric": "123456"
}


  • remove: It removes all occurrences of a specified pattern from a payload.
JavaScript
 
%dw 2.0
import remove from dw::core::Strings
output application/json
---
{
 "remove_matching": "ankurjyotibhuyan, [email protected], Ankur" remove "ankur",
 "remove_null": null remove "ankur"
}

========= OUTPUT =========
{
  "remove_matching": "jyotibhuyan, [email protected], Ankur",
  "remove_null": null
}


  • reverse: Its reverse sequence of characters in a string.
JavaScript
 
%dw 2.0
import reverse from dw::core::Strings
output application/json
---
{
 "reverse_string": reverse("ANKUR"),
 "reverse_number": reverse("12345"),
 "reverse_null": reverse(null)
}

========= OUTPUT =========
{
  "reverse_string": "RUKNA",
  "reverse_number": "54321",
  "reverse_null": null
}


  • replaceAll: It replaces all the matching characters, words, numbers from a given input string.
JavaScript
 
%dw 2.0
import replaceAll from dw::core::Strings
output application/json
---
{
 "replace_single_match": replaceAll("Ankur", "r" , "R"),
 "replace_single_match": replaceAll("ABCD", "A" , "B"),
 "replace_multiple_match": replaceAll("Ankur Ankur", "Ankur" , "ANKUR"),
 "replace_multiple_match": replaceAll("AAAA", "A" , "B"),
 "replace_non_match": replaceAll("Ankur", "j" , "J"),
 "replace_null": replaceAll(null, "aria" , "A")
}

========= OUTPUT =========
{
  "replace_single_match": "AnkuR",
  "replace_single_match": "BBCD",
  "replace_multiple_match": "ANKUR ANKUR",
  "replace_multiple_match": "BBBB",
  "replace_non_match": "Ankur",
  "replace_null": null
}  


  • someCharacter: It checks whether a condition is valid for at least one of the characters in the given string.
JavaScript
 
%dw 2.0
import someCharacter, isUpperCase, isLowerCase, isNumeric, isWhitespace from dw::core::Strings
output application/json
---
{
 "someCharacter_isUpper": "Ankur Jyoti Bhuyan" someCharacter isUpperCase($),
 "someCharacter_isLower": "Ankur Jyoti Bhuyan" someCharacter isLowerCase($),
 "someCharacter_isNumeric": "[email protected]" someCharacter isNumeric($),
 "someCharacter_isWhitespace": "Ankur Jyoti Bhuyan" someCharacter isWhitespace($),
 "someCharacter_NON_isWhitespace": "AnkurJyotiBhuyan" someCharacter isWhitespace($)
}

========= OUTPUT =========
{
  "someCharacter_isUpper": true,
  "someCharacter_isLower": true,
  "someCharacter_isNumeric": true,
  "someCharacter_isWhitespace": true,
  "someCharacter_NON_isWhitespace": false
}


  • substring: It returns a substring that includes the specified form to until index. Substring satisfy the condition from <= indexOf(string) < until.
JavaScript
 
%dw 2.0
import substring from dw::core::Strings
output application/json
---
{
 "substring_0_to_11": substring("Ankur Jyoti Bhuyan", 0, 11)
}

========= OUTPUT =========
{
  "substring_0_to_11": "Ankur Jyoti"
}


  • substringBy: It converts a string into an array when the separator expression match (returns true) else it will just convert the string to an array of string without any split.
JavaScript
 
%dw 2.0
import substringBy, isWhitespace from dw::core::Strings
output application/json
---
{
 "substringBy_whitespace": "Ankur Jyoti Bhuyan" substringBy isWhitespace($),
 "substringBy_no_match": "Ankur Jyoti Bhuyan" substringBy $ == ",",
 "substringBy_comma": "Ankur Jyoti Bhuyan,[email protected]" substringBy $ == ",",
 "substringBy_multple_condition": "Hello~world=here_is Ankur-Bhuyan" substringBy $ == "~" or $ == "=" or $ == "_" or isWhitespace($)
}

========= OUTPUT =========
{
  "substringBy_whitespace": ["Ankur","Jyoti","Bhuyan"],
  "substringBy_no_match": ["Ankur Jyoti Bhuyan"],
  "substringBy_comma": ["Ankur Jyoti Bhuyan","[email protected]"],
  "substringBy_multple_condition": ["Hello","world","here","is","Ankur-Bhuyan"]
}


  • substringEvery: It splits a string into an array with equal length specified in the function.
JavaScript
 
%dw 2.0
import substringEvery from dw::core::Strings
output application/json
---
{
 "substringEvery_5_character": substringEvery("AnkurJyotiBhuyan", 5)
}

========= OUTPUT =========
{
  "substringEvery_5_character": ["Ankur","Jyoti","Bhuya","n"]
}


  • words: It converts an input string to an array. The separators can be blank spaces, newlines, and tabs.
JavaScript
 
%dw 2.0
import words from dw::core::Strings
output application/json
---
{
    "words_to_array": words("Ankur Jyoti Bhuyan\[email protected]\n\nData-Weave")
}

========= OUTPUT =========
{
  "words_to_array": ["Ankur","Jyoti","Bhuyan","[email protected]","Data-Weave"]
}


b. dw::Core

  • indexOf: It returns the index of the first occurrence of the specified element is present in a given string/array, else it returns -1.
JavaScript
 
%dw 2.0
output application/json
---
{
 "present_in_array": ["a","n","k","u","r"] indexOf "k",
 "notPresent_in_array": ["b","h","u","y","a","n"] indexOf "x",
 "present_in_string": "ankur" indexOf "k",
 "notPresent_in_string": "bhuyan" indexOf "x",
 "presentMoreThanOnce_in_string": "ankur_ankur_" indexOf "_"
}

========= OUTPUT =========
{
  "present_in_array": 2,
  "notPresent_in_array": -1,
  "present_in_string": 2,
  "notPresent_in_string": -1,
  "presentMoreThanOnce_in_string": 5
}


  • lastIndexOf: It returns the index of the last occurrence of the specified element is present in given string/array, else it returns -1.
JavaScript
 
%dw 2.0
output application/json
---
{
 "present_in_array": ["a","n","k","u","r"] lastIndexOf "k",
 "notPresent_in_array": ["b","h","u","y","a","n"] lastIndexOf "x",
 "present_in_string": "ankur" lastIndexOf "k",
 "notPresent_in_string": "bhuyan" lastIndexOf "x",
 "presentMoreThanOnce_in_string": "ankur_ankur_" lastIndexOf "_"
}

========= OUTPUT =========
{
  "present_in_array": 2,
  "notPresent_in_array": -1,
  "present_in_string": 2,
  "notPresent_in_string": -1,
  "presentMoreThanOnce_in_string": 11
}


  • onNull: It runs a callback function if the earlier expression returns a null value and then replaces the null value with the result of the callback.
JavaScript
 
%dw 2.0
output application/json
fun onNullTest(aString) = null
---
{
    "onNull Output" : null then (onNullTest("aString")) onNull "Null Value"
}

========= OUTPUT =========
{
  "onNull Output": "Null Value"
}


  • then: It works as a pipe that passes the value returned from the previous expression to the next only if the value returned by the previous expression is not null.
JavaScript
 
%dw 2.0
output application/json
var inputData = [
    {
        "fName" : "Ankur",
        "lName" : "Bhuyan"
    },
    {
        "fName" : "Alex",
        "lName" : "Moby"
    }
]
---
inputData map ((item, index) -> item) then {
        Name: upper($[0].fName ++ " " ++ $[0].lName),
        Name: upper($[1].fName ++ " " ++ $[1].lName)
}

========= OUTPUT =========
{
  "Name": "ANKUR BHUYAN",
  "Name": "ALEX MOBY"
}


Conclusion

This blog is to give an idea about the new features of Mule 4.4. To view the code you can follow it here and test the code you can follow the postman script.

JavaScript Strings Data Types

Opinions expressed by DZone contributors are their own.

Related

  • JavaScript Type Conversion and Coercion
  • Adding Two Hours in DataWeave: Mule 4
  • Secrets in Code: Understanding Secret Detection and Its Blind Spots
  • From Zero to Meme Hero: How I Built an AI-Powered Meme Generator in React

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook