Saturday, June 29, 2019

SSL Handshake Failure Connecting To Mulesooft Anypoint Exchange In Corporate Environment

The Issue

As a Mulesoft developer, we will need to download connectors from Anypoint exchange periodically. When we try to connect to Mulesoft Anypoint Exchange, which is the repository for Mulesoft related connectors and other libraries, we may get SSH Handshake exception, in particular, using corporate provided laptop. Here is the top part of the exception message:
eclipse.buildId=unknown
java.version=1.8.0_212
java.vendor=Oracle Corporation
BootLoader constants: OS=win32, ARCH=x86_64, WS=win32, NL=en_US
Command-line arguments:  -os win32 -ws win32 -arch x86_64

org.mule.tooling.core
Error
Thu Jul 11 17:49:09 CDT 2019
The following exceptions were encountered while resolving dependency com.mulesoft.connectors:mule-salesforce-connector:9.7.6: java.lang.RuntimeException: There was an issue resolving the dependency tree for the bundleDescriptors [[BundleDescriptor{groupId='com.mulesoft.connectors', artifactId='mule-salesforce-connector', baseVersion='null', version='9.7.6', type='jar', classifier=Optional[mule-plugin]}, BundleDescriptor{groupId='org.mule.connectors', artifactId='mule-objectstore-connector', baseVersion='null', version='1.0.0', type='jar', classifier=Optional[mule-plugin]}]]
 at org.mule.maven.client.internal.AetherMavenClient.resolvePluginBundleDescriptorsDependencies(AetherMavenClient.java:322)
 at org.mule.tooling.core.m2.internal.MuleMavenClientResolver.resolvePluginDependencies(MuleMavenClientResolver.java:80)
 at org.mule.tooling.core.module.internal.runner.DownloadTask.doRun(DownloadTask.java:76)
 at org.mule.tooling.core.module.internal.runner.Task.run(Task.java:65)
 at org.mule.tooling.core.module.internal.runner.DownloadTask.run(DownloadTask.java:1)
 at org.mule.tooling.core.module.internal.runner.ArtifactResolvingRunner$ArtifactJob.run(ArtifactResolvingRunner.java:212)
 at org.eclipse.core.internal.jobs.Worker.run(Worker.java:56)
Caused by: org.eclipse.aether.collection.DependencyCollectionException: Failed to collect dependencies at com.mulesoft.connectors:mule-salesforce-connector:jar:mule-plugin:9.7.6 -> com.mulesoft.connectors:mule-connector-commons:jar:2.1.1
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.collectDependencies(DefaultDependencyCollector.java:291)
 at org.eclipse.aether.internal.impl.DefaultRepositorySystem.collectDependencies(DefaultRepositorySystem.java:316)
 at org.mule.maven.client.internal.AetherMavenClient.doResolveDependencies(AetherMavenClient.java:408)
 at org.mule.maven.client.internal.AetherMavenClient.resolvePluginBundleDescriptorsDependencies(AetherMavenClient.java:314)
 ... 6 more
Caused by: org.eclipse.aether.resolution.ArtifactDescriptorException: Failed to read artifact descriptor for com.mulesoft.connectors:mule-connector-commons:jar:2.1.1
 at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:282)
 at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.readArtifactDescriptor(DefaultArtifactDescriptorReader.java:198)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.resolveCachedArtifactDescriptor(DefaultDependencyCollector.java:535)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.getArtifactDescriptorResult(DefaultDependencyCollector.java:519)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:409)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:363)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.process(DefaultDependencyCollector.java:351)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.doRecurse(DefaultDependencyCollector.java:504)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:458)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.processDependency(DefaultDependencyCollector.java:363)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.process(DefaultDependencyCollector.java:351)
 at org.eclipse.aether.internal.impl.DefaultDependencyCollector.collectDependencies(DefaultDependencyCollector.java:254)
 ... 9 more
Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not transfer artifact com.mulesoft.connectors:mule-connector-commons:pom:2.1.1 from/to mulesoft-releases (https://repository.mulesoft.org/releases/): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
 at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolve(DefaultArtifactResolver.java:444)
 at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifacts(DefaultArtifactResolver.java:246)
 at org.eclipse.aether.internal.impl.DefaultArtifactResolver.resolveArtifact(DefaultArtifactResolver.java:223)
 at org.apache.maven.repository.internal.DefaultArtifactDescriptorReader.loadPom(DefaultArtifactDescriptorReader.java:267)
 ... 20 more


This article describes the procedures to fix this kind of issues.

Find The Root Cause

Problems solving skills are really about to find the root cause of the issue. In this issue, if we look the error message carefully, we will find the following:

Caused by: org.eclipse.aether.resolution.ArtifactResolutionException: Could not transfer artifact com.mulesoft.connectors:mule-connector-commons:pom:2.1.1 from/to mulesoft-releases (https://repository.mulesoft.org/releases/): sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

What this error message is saying that Java process was trying to transfer data from host of: repository.mulesoft.org. The problem is the SSL Handshake. To resolve this kind of problem we need to import the certificate from the site to cacerts.

Tasks

In this article, I only import 3 certificates from the following site:

  • anypoint.mulesoft.com
  • maven.anypoint.mulesoft.com
  • release.anypoint.mulesoft.com

Prerequisites

  1. On Windows install Cygwind
  2. Have Admin privilege of the laptop

Solutions

When we connect to Mulesoft Anypoint Exchange, AnypointStudio needs to go through SSL Handshake procedure before we can see the download page. If this process failed, typically, AnypointStudio (a java process) could not store the certificate), the SSHHandshakeException will be thrown by the studio. The following steps will fix the issue:

Step One: Download certificate from anypoint.mulesoft.com
openssl s_client -connect anypoint.mulesoft.com:443 -showcerts </dev/null 2>/dev/null |openssl x509 -outform PEM >anypoint.pem
Step Two: Download certificate from maven.anypoint.mulesoft.com
openssl s_client -connect maven.anypoint.mulesoft.com:443 -showcerts   </dev/null 2>/dev/null | openssl x509 -outform PEM >mulesoft.maven.pem
Step Three: Download certificate from repository.anypoint.mulesoft.com
openssl s_client -connect repository.mulesoft.org:443 -showcerts   </dev/null 2>/dev/null | openssl x509 -outform PEM >mulesoft.repo.pem
Step Four: Copy the 3 certificates
cp *.pem /cygdrive/c/’Program Files’/Java/jdk1.8.0_212/jre/lib/security
As you can see that I am using cygwin on Windows. On Macbook Pro, the JAVA_HOME is may be different. In this case the JAVA_HOME is under:
/cygdrive/c/’Program Files’/Java/jdk1.8.0_212
Step Five: Import the certificate to cacerts
/cygdrive/c/’Program Files’/Java/jdk1.8.0_212/jre/lib/security
keytool -import -alias anypoint -keystore cacerts -file anypoint.pem
Repeat the same procedure for the other 2 certificaes. Step Fix: Restart Anypoint Studio

Saturday, March 16, 2019

Email Address Validation Using Dataweave Regex

Introduction

This short article is about how to use regex with Dataweave 2.0 with regard to email validation. Regex is used in Mulesoft language very wide with regard two functions, matchs(...) and match(...). It is very important to master the regular expression in order to be professional in Mulesoft integration projects. The are a lot of reference available one. Here are few:

Use Case

We expect the output of the dataweave transformation as the following depending on the validity of the email address:
[
    {
        ...
        "invalidEmail": "johndo@yahoo"
        ...
    },
    {
        ...
        "PersonEmail": "john.smith@google.com"
        ...
    },
    ...
]

Invalid Emails

The following types of emails are invalid:
  1. beginning with a dot: .gary.liu@google.com
  2. ending with a dot: gary.liu@google.com.
  3. double dots: gary.liu@google..com
  4. domain name contains underscore: gary.liu@att_rr.com
  5. domain name contains space: gayr.liu@att rr.com
  6. domain name contains and of the following: ,<>/[]
  7. no organization email: gary@google

Solution

%dw 2.0
output application/json
var regexEmail = /^[^.][a-zA-Z0-9.!#$%&’*+\/=?^_`{|}~-]+@[a-zA-Z0-9-](?!.*?\.\.)[^_ ; ,<>\/\\]+(?:\.[a-zA-Z0-9-]+)[^.]*$/
---
payload map using (email = $.email) {
 (validEmail: email) if (email matches regexEmail),
 (invalidEmail: email) if ( not  (email matches regexEmail))
}
The above dataweave script is self-explanatory. Few explanation is required if you are not very familiar with regular expression:
  1. negation: [^_;,\.] this expression means if the email domain contains underscore _ , semi-coma, etc. is not valid email
  2. simple ^ and $ represent the beginning and end of the line
  3. [a-zA-Z0-9] mean any charater A a, Bb ... Zz, or 0 to 9 digits are valid
  4. + sign means to match one for more
  5. * sign matches 0 or more
  6. ?! means not include, (?!.*?\.\.) --> not include double dots: ..

Saturday, March 2, 2019

How To Resolve Issue With: "General SSLEngine problem"

The Background

This happens when you enable the HTTPS with your own certificates. In my case, I have configured Anypoint runtime fabrics with self generated certification using the following command:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365
The above command generates two files: cert.pem and key.pem. The purpose of them is beyond the scope of the article. The error will occur when the local mule flow call the remote application which is deployed in the Anypoint Runtime Fabrics.

Solution

To resolve this problem, we just need to import the cert.pem to cacerts file. The command is (on MacOs):
cd /Library/Java/JavaVirtualMachines/jdk1.8.0_181.jdk/Contents/Home/jre/lib/security
sudo keytool -import -trustcacerts -keystore cacerts -storepass changeit -alias rogers-poc-cert -file /Users/gl17/anypoint/certs/poc/cert.pem
Make sure restart Anypoint Studio.

Monday, January 14, 2019

Deploy Mule 4 Application To Anypoint Runtime Fabric Using Maven Plugin

Introduction

In CI/CD process, it is very common to use Mule Maven plugin to build and deploy application to the Cloudhub, on-premise private cloud like AWS, AZure, Google Cloud, etc. Since Mule 4, a lot of changes related to the deployment has changed, in particular, related to the Mule Runtime Fabric (RTF). Actually, RTF is a completely new infrastructure for Mule application deployment. I will cover more on that topic later. In this article, I am going to cover the following topics related to the deployment to Anypoint Runtime Fabric (RTF):
  1. Prepare pom.xml setup to deploy mule project to Anypoint RTF
  2. Encrypt password
  3. Troubleshooting

If everything works, at the end, we should be able to achieve the following goals:

  • deploy mule projects (assets) to Anypoint Exchange
  • deploy mule projects to Anypoint Runtime Fabric

In order for mule maven plugin to work, we need change the following two files:

  • pom.xml
  • ./m2/settings.xml

The complete project for this article can be find at my github repository

Settings.xml

In order to deploy mule applications using mule maven plugin, we need to set the Anypoint credentials, which are the ones we use to login to anypoint portal (http://anypoint.mulesoft.com). The best way to do this is to add server information in the .m2/settings.xml as the following:
        
                
                      ExchangeRepository
                      gary_liu_client
                      {5XLgXNDBGBIHa99xNAyJ6gL+ZxyUiyIJNHWu0H7Ctew=}
                
        
The password is encrypted. To encrypt password we need to add another file namely: ~/.m2/settings-security.xml:

  {Vq5Aso1ZkO4HdJrUscJTZEii4BcFy+khGiGxDNVNgc4=}

The encrypt master password in the above is created by the following commands:
$ mvn --encrypt-master-password MasterPassword
{+4nnH6EW9HcHAHYBGnloFCAZZHSC4W3Xp9Zls0LvBqk=}
Once we encrypted the master password, we can encrypt the password to the anypoint portal as the following:
mvn --encrypt-password AnypointPortalPassword
For more details about the maven password encryption, you may refer to the following page: https://maven.apache.org/guides/mini/guide-encryption.html

pom.xml



 4.0.0

 fea874ca-11d9-4779-b1ce-90d49f738259
 mule-maven-plugin
 1.0.2
 mule-application

 mule-maven-plugin

 
  UTF-8
  UTF-8
  3.2.3
  https://anypoint.mulesoft.com
  MC
  QA

  4.1.4
  gary-deployment
  100m
  500Mi
 

 
  
   
    org.mule.tools.maven
    mule-maven-plugin
    ${mule.maven.plugin.version}
    true
    
     
      ${anypoint.uri}
      ${anypoint.provider}
      ${deployment.environment}
      ${deployment.target}
      ${app.runtime}
      ExchangeRepository
      ${app.name}
      
       ${deployment.replica}
       ${app.cores}
       ${app.memory}
      
     
     mule-application
    
   

   
    org.codehaus.mojo
    properties-maven-plugin
    1.0.0
    
     
      initialize
      
       read-project-properties
      
      
       
        ${maven.properties}
       
      
     
    
   
  
 

 
  
   ExchangeRepository
   Corporate Repository
   https://maven.anypoint.mulesoft.com/api/v1/organizations/${groupId}/maven
   default
  
 

 
           ......
 
        ......

The details are explained in the next section. But one item I must point out here: <groupId>fea874ca-11d9-4779-b1ce-90d49f738259</groupId>. The groupId is your Anypoint platform organization ID.

Explanations

The configuration in both pom.xml and settings.xml are pretty straightforward. Few items worths to explain. First, what is the latest version of mule maven plugin? This can be found at: https://docs.mulesoft.com/release-notes/mule-maven-plugin/mule-maven-plugin-release-notes. Currently, the latest verson is 3.2.3.

Secondly, I use another plugin in addition to the mule maven plugin, namely, properties-maven-plugin. This plugin allow us to pass a property file to the pom.xml.

   
    org.codehaus.mojo
    properties-maven-plugin
    1.0.0
    
     
      initialize
      
       read-project-properties
      
      
       
        ${maven.properties}
       
      
     
    
   
Note that in the configuration, we put ${maven.properties} variable. This allow as to pass the property file as:
mvn clean deploy -DmuleDeploy -Dmaven.properties=src/main/resources/mule.rtf.deploy.properties
Thirdly, note that in the mule maven plugin, I use <server>ExchangeRepository</server> as shown below. The ExchangeRespository is the server defined in the ~/.m2/settings.xml
    
     
      https://anypoint.mulesoft.com
      MC
      QA
      qa-azure-rtf
      4.1.4
      ExchangeRepository
      ${app.name}
      
       1
       100m
       500Mi
      
     
     mule-application
    
The details for the parameters can be referred at: https://docs.mulesoft.com/mule-runtime/4.1/runtime-fabric-deployment-mmp-reference.

Publish Assets To Exchange

In order to deploy mule application to RTF using Mule Maven Plugin, we must publish the application (asset to Anypoint Exchange). To me this is extra step unnecessary. To publish an artifact (asset) to the Anypoint Exchange, we run the following command:
mvn clean package deploy -Dmaven.properties=src/main/resources/mule.rtf.deploy.properties
After it completes the publishing, you can verify the result by the Anypoint Port using the following web address:
https://anypoint.mulesoft.com/exchange/{groupId}/{artifactId}
Here is an my example:
https://anypoint.mulesoft.com/exchange/fea874ca-11d9-4779-b1ce-90d49f738259/mule-maven-plugin/

Deploy Application To RTF

Deployment to RTF could be slow and sometimes could take very long time if it failed. I think the plugin should be improved on this by using asynchronous deployment instead of waiting and constantly checking with the runtime manager. Any way the deployment to RTF can be done using the following command:
mvn clean package deploy -DmuleDeploy -Dmaven.properties=src/main/resources/mule.rtf.deploy.properties

Take Aways

The commands used in the process:
mvn --encrypt-master-password GaryLiu1234
mvn --encrypt-password GaryLiu1234
mvn clean package deploy-Dmaven.properties=src/main/resources/mule.rtf.deploy.properties
mvn clean package deploy -DmuleDeploy -Dmaven.properties=src/main/resources/mule.rtf.deploy.properties
Web address to check assets in the Anypoint Exchange in the Anypoint Portal:
https://anypoint.mulesoft.com/exchange/{groupId}/{artifactId} Key Considerations using the Mule Maven Plugin in the CI/CD:
  • Make sure don't wait for the deployment to finish as it can take very long time
  • There are rest API you can check the deployment process. You should use the APIs to check the deploy
  • At the moment, anypoint-cli is not working for RTF

Saturday, December 15, 2018

Mule 4 Integration With Cassandra

Introduction

Mule 4 Cassandra Database Connector, current version of 3.10, has made significant improvement over the previous version. It is fairly straight forward to setup the integration to the Cassandra Database using the connector. This article is an introduction of the Cassandra Connector to Cassandra cluster.

Cassandra Cluster Configuration

I have created 2 a two node cluster as shown the in following diagram. The details on how to setup the Cassandra clustering will be covered in another post. Basically, I opened the native transport port 9042, which is the default vale on both nodes.
We need to some initial setup using cqlsh too by run the following command:
$ cqlsh -u cassandra -p casandra
cassandra@cqlsh> create keyspace if not exists dev_keyspace with replication = {'class' : 'SimpleStrategy', 'replication_factor' : 2};
The above command will create a keyspace, namely dev_keyspace. We can query the keyspaces by the following command:
cassandra@cqlsh> desc keyspaces;
You should see the following:
system_schema  system      system_distributed
system_auth    dev_keyspace  system_traces
The next step is to create emp table by the following command:
cassandra@cqlsh> create table emp (empid int primary key, emp_first varchar, emp_last varchar, emp_dept varchar);
And insert a row:
create table emp (empid int primary key, emp_first varchar, emp_last varchar, emp_dept varchar);
insert into emp (empid, emp_first, emp_last, emp_dept) values (1, 'Gary','liu','consulting');
That is all and we are ready to do the integration.

Integration Using Mule 4 Cassandra Connector

Add Cassandra Connector

First, we need to search the Exchange and add the Cassandra Connection as shown in the following snapshot:

Create CassandraDB Config

Create a mule configuration, namely, global-config.xml. Then create CasandraDB Config as the following:
Enter the General setting as the following. Note: Leave the Host empty as we use cluster configuration.
Now, click the "Advanced Settings" tab and enter the information as the following:

As you can see, we can enter the ip addresses separated by comma. In this way, we can achieve high availability from client side of view. Now, we test the connectivity. If the port of 9042 is exposed correctly, it should work fine. I will explain more in the next article on how to make sure we expose the native transport port correctly.

Create Integration Flows

Read Flow

The read flow is very straight forward. The cassandra-db:select operation uses payload as the whole query. We just need to set payload. In this case, it is "select * from emp;"

<flow name="select-objecsFlow" doc:id="8bdcc4fe-cf4e-49be-b2f9-2dfacbddaf4b" >
<http:listener doc:name="Listener" doc:id="ab57d8ab-2623-468b-b635-a0c6efd6c829" config-ref="HTTP_Listener_config" path="/cassandra/emp"/>
<set-payload value="select * from emp;" doc:name="Set Payload"  />
<cassandra-db:select doc:name="Select"  config-ref="CassandraDB_Config_cluster" />
<ee:transform doc:name="Transform Message"  >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
payload]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level="INFO" doc:name="Logger" doc:id="e6097436-1909-4d8b-8c81-27be82c11714" message="#[payload]" />
</flow>

</mule>

Insert A Row

To insert a row, we need to use insert operation as the following:

<flow name="insert-objecsFlow" doc:id="8bdcc4fe-cf4e-49be-b2f9-2dfacbddaf4b" >
<http:listener doc:name="Listener" doc:id="ab57d8ab-2623-468b-b635-a0c6efd6c829" config-ref="HTTP_Listener_config" path="/cassandra/emp/create"/>
<ee:transform doc:name="Transform Message" doc:id="0d484493-fa23-4a56-9547-58f0bb54dbd1" >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/java
---
payload]]></ee:set-payload>
</ee:message>
</ee:transform>
<cassandra-db:insert table="emp" doc:name="Insert" doc:id="71cb7584-981a-4475-a839-ea82ed3b9832" config-ref="CassandraDB_Config_vm1" keyspaceName="rogers_dev"/>
<ee:transform doc:name="Transform Message"  >
<ee:message >
<ee:set-payload ><![CDATA[%dw 2.0
output application/json
---
payload]]></ee:set-payload>
</ee:message>
</ee:transform>
<logger level="INFO" doc:name="Logger" doc:id="e6097436-1909-4d8b-8c81-27be82c11714" message="#[payload]" />

</flow>

Currently, we can only insert one row at a time. To insert multiple rows, we can use for loop or use batch processes for large volumes. 

About CassandraDB Connector

The detailed information can be found at the following Mulesoft Document:
https://docs.mulesoft.com/connectors/cassandra/cassandra-connector

Important Cassandra Information

When you using cqlsh to connect Cassandra cluster, you should notice the following:

cqlsh -u cassandra -p cassandra
Connected to DevelopmentCluster at 127.0.0.1:9042.
[cqlsh 5.0.1 | Cassandra 3.11.3 | CQL spec 3.4.4 | Native protocol v4]

The v4 is the current native protocol version, which is required to configure the connector.



Saturday, August 4, 2018

Mule 4 : Dataweave 2 In Action - Use Function Modules

Introduction

In Mule 4, the mel2 functionalities are replaced by the Dataweave 2 ones. For those who worked in Mule 3, you will find the mule 4 ways of using function modules are much more advanced than the old way (see my post). In this article, I am going to present Mule 4 ways to define and use global functions.

Define Functions In Dataweave Modules

Here is my project layout:

As you can see, I place the function modules in the dir: src/main/resources/modules. And the dataweave function module is defined in CommonFunc.dwl.

%dw 2.0
fun concatName(aPerson) = aPerson.firstName ++ ' ' ++ aPerson.lastName

fun stringToDateUTC(dateString) = ((dateString as String {format: "yyyy-MM-dd'T'HH:mm:ss.SSSZ"} >> "UTC"
 )) as DateTime {format: "yyyy-MM-dd'T'HH:mm:ss.SSS"} 

I defined two functions: concatName, stringToDateUTC. The purposes are self-explained.

Use Function Modules

I place the normal dataweave modules in the dir of src/main/resources/dataweave. The usage of the functions is demonstrated at the following dwl file:

%dw 2.0
import * from modules::CommonFunc
output application/json
---
{
 "Name" : concatName(payload),
 "CreatedDate" : stringToDateUTC(payload.createdDate)
}

Here are few points:

  • import functions
    1. import modules::CommonFuc
    2. import * from modules::CommonFunc
    3. import concatName stringToDateUTC from modules::CommonFunc
  • use functions in dwl
    1. CommonFunc::concatName(payload)
    2. concatName(payload)

For those who know python, you may find the syntax is very similar between the two languages, in terms of modules, and references.

Testing Data

Here is the complete flow:
 
  
   
  
  
   
    
   
  
  
 
Here is testing data:
{
 "firstName" : "Gary",
 "lastName" : "Liu",
 "createdDate":"2018-07-17T16:18:03+00:00"
}

Wednesday, July 25, 2018

Mule 4: Dataweave 2 In Action - Using Filter

Use Cases

The requirement is to update overall status to PARTIAL if there is any failure record in the payload, i. e. item.status = "Failed"

Input:
{
    "status": "SUCCESS",
    "items": [
        {
            "accountId": "10101xyzabc",
            "status": "Success"
        },
        {
            "accountId": "10102aaabbb",
            "status": "Failed"
        }
    ]
}
Expected Output:
{
    "status": "PARTIAL",
    "items": [
        {
            "accountId": "10101xyzabc",
            "status": "Success"
        },
        {
            "accountId": "10102aaabbb",
            "status": "Failed"
        }
    ]
}

Datawave 2.0

%dw 2.0
output application/json
---
{
 status: if (sizeOf(payload.items map($) filter ($.status == "Failed")) > 0) "PARTIAL" else "SUCCESS",
 items: payload.items 
}

Complete Flow

The following is the complete flow. Please note that I have commented out the transformation payload to java. This is a big improvement of Mule 4 over mule 3.
 
  
   
  
  
  
   
    
   
   
   
  
  
 

Key Learnings

  1. sizeOf function
  2. filter function
  3. if else, in Dataweave 1.0, this will be when else
if else is a very good syntax improvement over Dataweave 1.0

Anypoint Studio Error: The project is missing Munit lIbrary to run tests

Anypoint Studio 7.9 has a bug. Even if we following the article: https://help.mulesoft.com/s/article/The-project-is-missing-MUnit-libraries-...