Over a million developers have joined DZone.
Platinum Partner

Validating XML message in Mule 3

· Integration Zone

The Integration Zone is brought to you in partnership with Red Hat. Use these flashcards along with the popular open source integration framework Apache Camel as an easy reference during the design and development of integration projects.

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());

The Integration Zone is brought to you in partnership with Red Hat.  Discover how your integration architecture may be holding you back and 3 considerations for fixing it.


Published at DZone with permission of Pascal Alma , DZone MVB .

Opinions expressed by DZone contributors are their own.

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

{{ parent.tldr }}

{{ parent.urlSource.name }}