Mule 3.x: JSON Schema Validation with a Dynamic Schema Location
Mule 3.x included a JSON Schema Validator for checking an incoming JSON payload against a referenced schema. The standard configuration works well when the schema location is known at design time.
<json:validate-schema schemaLocation="http://my.site/schemas/some_schema.json" doc:name="Validate Json Schema"/>
The challenge in this use case was that the schema location needed to be determined dynamically—for example, retrieved from a database and stored in a flow variable.
<set-variable name="dynamicSchemaLocation" value="http://my.site/schemas/some_schema.json" doc:name="Variable Dynamic Schema Location" />
Attempting to pass that runtime value directly to the validator's schemaLocation attribute caused the application deployment to fail in the Mule version used for this article.
<json:validate-schema schemaLocation="#[flowVars.dynamicSchemaLocation]" doc:name="Validate Json Schema"/>
Workaround
The solution was to move validation into a custom processor:
- Read the schema location from the flow variable.
- Create an instance of Mule's JSON Schema Validator.
- Supply the resolved schema location programmatically.
- Invoke the validator's
validateoperation.
package com.mycompany;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import org.mule.api.MuleEvent;
import org.mule.api.MuleException;
import org.mule.api.processor.MessageProcessor;
import org.mule.module.json.validation.JsonSchemaDereferencing;
import org.mule.module.json.validation.JsonSchemaValidator;
import com.mycompany.BadRequestException;
import com.mycompany.NotFoundException;
/**
* This is custom JSON schema validation class which uses JsonSchemaValidator
* from mule framework. This class is created because JsonSchemaValidator from
* mule framework cannot evaluate schemaLocation value from flow variable.
*
* @author Sagar Chaudhari
*
*/
public class JsonSchemaValidationProcessor implements MessageProcessor {
private static final String X_FLOW_VAR_SCHEMA_LOCATION = "dynamicSchemaLocation";
private JsonSchemaDereferencing dereferencing = JsonSchemaDereferencing.CANONICAL;
private Map<String, String> schemaRedirects = new HashMap<String, String>();
private JsonSchemaValidator validator;
@Override
public MuleEvent process(MuleEvent event) throws MuleException {
String schemaLocation = event.getFlowVariable(X_FLOW_VAR_SCHEMA_LOCATION);
if (StringUtils.isBlank(schemaLocation)) {
throw new NotFoundException("schemaLocation is not configured");
}
validator = JsonSchemaValidator.builder()
.setSchemaLocation(schemaLocation)
.setDereferencing(dereferencing)
.addSchemaRedirects(schemaRedirects)
.build();
try {
validator.validate(event);
} catch (Exception e) {
throw new BadRequestException(e.getMessage());
}
return event;
}
}
<set-variable name="dynamicSchemaLocation" value="http://my.site/schemas/some_schema.json" doc:name="Variable Dynamic Schema Location" />
<!-- Before invoking this processor, make sure payload is JSON and not Object -->
<custom-processor class="com.mycompany.JsonSchemaValidationProcessor" />
Version context: This is a Mule 3.x implementation. Mule 4 has a different runtime, SDK, expression model, and validation tooling, so do not carry this custom-processor approach forward without checking the current platform capabilities first.
Design Considerations
Dynamic schema selection can be useful when a single flow handles multiple payload contracts, but it also introduces operational concerns. Schema locations should be controlled, validated, and ideally cached rather than accepting arbitrary external paths at runtime.
Takeaway
When a framework component exposes only a static configuration value, a small programmatic wrapper can provide the needed runtime flexibility. The trade-off is tighter coupling to platform internals, so the approach should be isolated and revisited during runtime upgrades.