Enterprise Integration Zone is brought to you in partnership with:

John D'Emic is a technologist, developer and author. He is currently a Solutions Architect at MuleSoft and a co-author of both editions of Mule in Action. John is a DZone MVB and is not an employee of DZone and has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

Implementing Custom JSON or Map Data Validation with Mule DevKit

12.17.2012
| 1444 views |
  • submit to reddit
Validating data can be easy with Mule if your message payloads are in certain formats.  XML payloads, for instance, can be verified for correctness via XML schema or XPath filters. Payload type filters and OGNL expression evaluation can go a long way in asserting your POJO payloads are correct.

Payloads with less structure, like Map or JSON data, are a little bit trickier to validate.  This is particularly true on the front-end of web-services where leniency in data format, particularly JSON, can be beneficial.  In these cases a custom Message Processor is usually necessary to filter or sanitise the data.

Creating a Module for Custom Validation

As previously demonstrated Mule is an excellent way to add first-class, configuration-schema aware support for your custom message processors. Let’s implement a Message Processor for Acme Software, Inc that accepts a JSON array on a HTTP endpoint and filters out invalid products from it.

We’ll start by creating a module for our fictional company’s validation extensions using the devkit mvn archetype:

mvn archetype:generate -DarchetypeGroupId=org.mule.tools.devkit - DarchetypeArtifactId=mule-devkit-archetype-generic -DarchetypeVersion=3.0.1 - DarchetypeRepository=http://repository.mulesoft.org/releases/ -DgroupId=acmesoft.com -DartifactId=validator-module -Dversion=1.0-SNAPSHOT -DmuleVersion=3.2.0 - DmuleModuleName=Validator -DmuleModulePackage=com.acmesoft.integration

This gives us a Maven project we can use to host our company’s custom validators. These validators will be “first class” citizens in the Mule config file, happily living alongside Mule’s built in message processors.

Implementing the Custom Validator

The mvn command we executed above will have created a ValidatorModule class in the com.acmesoft.integration package. This is where we’ll implement the code for our custom processor. We’ll modify the stub implementation to look as follows:

@Module(name = "validator", schemaVersion = "1.0-SNAPSHOT")
public class ValidatorModule {


    /**
     * Processor to filter our invalid products from a List payload.
     * <p/>
     * {@sample.xml ../../../doc/Validator-connector.xml.sample validator:my-processor}
     *
     * @param products The products to validate
     * @return The products which are valid
     */
    @Processor(name = "product")
    public Object validateProducts(@Payload List<Map> products) throws Exception {

        List<Map> validProducts = new ArrayList<Map>();

        for (Map product : products) {
            if (product.containsKey("sku") || product.containsKey("product_id")) {
                validProducts.add(product);
            }
        }

        return validProducts;
    }


}

The “name” attribute on the @Module annotation on the class indicates the namespace of the module. Similarly the “name” attribute on the @Processor annotation defines the name of the XML element in the configuration. The XML configuration for our message processor will subsequently look like this:

<validator:product/>

Let’s take a look at the implementation of validateProducts. Specifying the @Payload annotation to one of the arguments lets us identify the payload. In this case we’re expecting a List of Maps, which is valid return type of Mule’s json-to-object-transformer.

We’re then iterating over each Map representation of a product and filtering out those that don’t contain “sku” or “product_id” keys. Finally we’re returning the filtered list which will propagate to the next processor in the chain.

Configuring the Custom Validator

Now we’re ready to place the validator in a flow. We’ll accept JSON product data on an HTTP inbound-endpoint, filter out invalid products and pass the filtered results out on an VM outbound-endpoint:

 <flow name="Product Submission">
    <http:inbound-endpoint address="http://localhost:8080/products"/>
    <byte-array-to-string-transformer/>
    <json:json-to-object-transformer returnClass="java.util.ArrayList"/>
    <validator:product/>
    <vm:outbound-endpoint path="products.out"/>
</flow>

The payload is first being converted from a byte-array to a String. The json-to-object transformer moves the JSON encoded data to a List of Maps format. This is easier to use then the raw JSON for our use case. Our product validator then comes into play, filtering out invalid messages before finally sending the results to the “products.out” VM queue.

Using DevKit with a Mule module has benefits over a “one-off” implementation with a custom- processor element. By using a module we now have the ability to share the validators across multiple Mule projects. The deep integration with the Mule schema allows code completion and documentation in most IDEs, lowering the barrier of entry for others to leverage the custom functionality. Finally the level of effort to accomplish the above is trivialized with the use of DevKit’s annotations.



Published at DZone with permission of John D'Emic, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)