Over a million developers have joined DZone.

Validating XML message in Mule 3

DZone's Guide to

Validating XML message in Mule 3

· Integration Zone ·
Free Resource

The State of API Integration 2018: Get Cloud Elements’ report for the most comprehensive breakdown of the API integration industry’s past, present, and future.

A common use case Mule ESB flows is validating if an XML document is valid against a corresponding XSD. It can be quite annoying to find out you have spent a lot of time fixing an issue when it was actually caused by another system that was supplying invalid XML, especially if a project is in the development/test stage.

The ‘standard’ way to do this in Mule is by using the schema-validation-filter, usually in combination with the message-filter. For example, the following configuration will send all non-valid messages to the ‘process-invalid-xml’ flow:

<message-filter onUnaccepted="process-invalid-xml" throwOnUnaccepted="true">
    <xml:schema-validation-filter .../>

In the ‘process-invalid-xml’ flow you can then create a response message (if applicable) to tell the sender of the original message that it contains invalid XML. This was the case in my situation and I also wanted to show the user what was wrong in the XML. To do this, I created my own SAX ErrorHandler and supplied that to the schema-validation-filter like this:

<spring:bean id="xmlErrorHandler" class="net.pascalalma.xml.handlers.MySaxErrorHandler" />
 <message-filter onUnaccepted="invalidRelationXmlFlow" throwOnUnaccepted="false">
     <mulexml:schema-validation-filter errorHandler-ref="xmlErrorHandler"  schemaLocations="xsd/my-schema.xsd"/>

However, no matter what I did my error handler wasn’t being called by the filter. After some debugging I only got it working by extending the original schema-validation-filter and set the error-handler on the created Validator like this:

public class MySchemaValidationFilter extends SchemaValidationFilter
  static Logger logger = Logger.getLogger(MySchemaValidationFilter.class);
  public Validator createValidator() throws SAXException
    Validator validator = super.createValidator();
    return validator;

I am not sure if this is a bug in the original schema-validation-filter or if there is another way to make use of the errorHandler, but this was the only way for me to get it working.

I use my version of the filter with the following configuration:

<custom-filter class="net.pascalalma.xml.filters.MySchemaValidationFilter" >
  <spring:property name="schemaLocations" value="xsd/my-schema.xsd"/>
  <spring:property name="returnResult" value="false"/>
  <spring:property name="errorHandler" ref="xmlErrorHandler"/>

This way I can collect all errors in my error handler and put them with a outbound property on the message and return them to the calling client.

Here is the source code of my error handler:

public class MyErrorHandler implements ErrorHandler {
    static Logger logger = Logger.getLogger(MyErrorHandler.class);
    public List<String> getErrors() {
        return errors;
    public void setErrors(List<String> errors) {
        this.errors = errors;
    private List<String> errors = new ArrayList<String>();
    public void warning(SAXParseException e) throws SAXException {
        logger.warn(e.getLineNumber() + "/" + e.getColumnNumber() + ": " + e.getMessage());
    public void fatalError(SAXParseException e) throws SAXException {
        logger.debug("fatalError occurred: " + e.toString());
        errors.add(e.getLineNumber() +"/" + e.getColumnNumber() + ": " + e.getMessage());
    public void error(SAXParseException e) throws SAXException {
        logger.debug("error occurred: " + e.toString());
        errors.add(e.getLineNumber() +"/" + e.getColumnNumber() + ": " + e.getMessage());

Your API is not enough. Learn why (and how) leading SaaS providers are turning their products into platforms with API integration in the ebook, Build Platforms, Not Products from Cloud Elements.


Published at DZone with permission of

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}