Search code examples
javavalidationexceptionmulecustom-exceptions

Java, Mule - Throw different types of exceptions on one Validation component


In a flow I've designed, I have a Validation component with a custom validator that references a class, DataValidator, implementing the mule Validator interface. In the DataValidator, I validate several properties and would like to throw different kinds of exceptions (possibly custom exceptions, created by me) for each one. Is this possible?

My understanding is that, by specifying the exceptionClass, the Validation component will only throw exceptions of that class.

There's the option to use an ExceptionFactory instead of an exceptionClass. Does using it allows throwing several types of exception? If so, how can I use it? I checked this blog post, but didn't understand it well enough.

In the case that none of this is possible, is there any way I can get the ValidationResult message in the custom validator component, so that I can use it in the message?


Solution

  • Yes you can throw several types of exceptions. As you mentioned, you'll have to implement the DataValidator and ExceptionFactory interface and configure your component to use them.

    With Studio, choose "Use Exception Factory Config" and specify the full class name you want to use. With XML, specify the exception-factory you implemented in your validation-config. (You can also configure a Spring Bean and reference it):

        <validation:config name="Validation_Configuration" doc:name="Validation Configuration">
            <validation:exception-factory class="com.mycomp.validation.MyExceptionFactory"/>
        </validation:config>
    

    In your flow configure acustom-validator and reference your configuration with exception factory, your validator implementation and the type of exception you want to throw with exceptionClass. To be able to throw any kind of Exception, specify java.lang.Exception or a class from which the custom exceptions you'll want to use can inherit:

    <flow name="validation-exceptionFlow">
        ...
        <validation:custom-validator
            config-ref="Validation_Configuration" 
            class="com.mycomp.validation.MyValidator"
            exceptionClass="java.lang.Exception" 
            doc:name="Validation" />
        ...
    </flow>
    

    Depending on your need you may want to specify exceptionClass differently, the idea being that your actual exceptions should extend it.

    Yout ExceptionFactory implementation is then up to you. You can return whatever exception you want... For example:

    public class MyExceptionFactory implements ExceptionFactory{
    
        @Override
        public <T extends Exception> T createException(ValidationResult result, Class<T> exceptionClass, MuleEvent event) {
            return (T) createException(result, exceptionClass.getCanonicalName(), event);
        }
    
        @Override
        public Exception createException(ValidationResult result, String exceptionClassName, MuleEvent event) {
            //...
            //some logic to identify which kind of exception you want to throw
            //from result and event
            //...
            if(something) {
                return new SomeException("Something happened");
            } else if (somethingElse) {
                return new AnotherException("I am en error...");
            } else {
                return new BananaException("Ook");
            }
        }
    
    }
    

    It appears the interface has two methods, one returning a generic and the other a plain Exception. Not knowing the specific usage of your ExceptionFactory I won't be able to provide much guidance, but be aware that Mule may call any of these methods, and the doc provides some requirements:

    The above interface receives the Event that was rejected by the validation and the validator that raised the error. This method is intended to return the exception to be thrown but not to throw it. Implementations of this interface should never throw exceptions. They should also be thread-safe and have a public default constructor. See Also