Message Validation
When working with messages sent between separate machines, even when working against a specific schema, there can often be issues with the validity of the messages. These are often due to bugs, data entry errors or schema version mismatches. Both sending and receiving connectors can be optionally configured to validate messages before sending or after receiving.
Send Connectors
To add validation to a sending connector, an implementation of the Validator interface must be provided when building the connector.
public interface Validator {
ValidationReport validate(TransportMessage transportMessage);
}
The connector library provides two validators, one for JSON Schema and another for XML Schema. Validation is performed against a TransportMessage before it is sent to the transport.
XML Schema Validation
The XML validation implementation of Validator is XmlSchemaValidator.
It takes an InputStream representing the schema to use against which all messages passing through this validator will be validated.
String xmlSchema = "/validation/sample-schema.xsd";
InputStream xmlSchemaStream = getClass().getResourceAsStream(xmlSchema);
XmlSchemaValidator xmlValidator = new XmlSchemaValidator(xmlSchemaStream);
SendConnector<ExampleType, ExampleType> sendConnectorWithXmlValidator
= new SendConnector.Builder<ExampleType, ExampleType>(connectorName)
.withActorSystem(actorSystem)
.withConnectorTransport(transport)
.withCorrelationIdExtractor(correlationIdExtractor)
.withValidator(xmlValidator) (1)
.build();
| 1 | Adds the xml schema validator to the connector |
In the above example, we are loading an XML Schema document from the classpath as an input stream.
This is the most common usage pattern for XmlSchemaValidator.
It is possible to set up using other types of input stream, such as a ByteArrayInputStream for loading the schema from a string.
The XML validator implements external entity injection (XXE) protection according to the OWASP cheat sheet on the topic.
JSON Schema Validation
The JSON validation implementation of Validator is JsonSchemaValidator.
It is configured similarly to the XML validator, where we must pass an InputStream representing the schema to validate messages against.
String jsonSchema = "/com/github/fge/jsonschema/examples/fstab.json";
InputStream jsonSchemaStream = getClass().getResourceAsStream(jsonSchema);
JsonSchemaValidator jsonValidator = new JsonSchemaValidator(jsonSchemaStream);
SendConnector<ExampleType, ExampleType> sendConnectorWithJsonValidator
= new SendConnector.Builder<ExampleType, ExampleType>(connectorName)
.withActorSystem(actorSystem)
.withConnectorTransport(transport)
.withCorrelationIdExtractor(correlationIdExtractor)
.withValidator(jsonValidator) (1)
.build();
| 1 | Adds the json schema validator to the connector |
The default JSON schema version is draft-04 which is the de facto standard.
Receive Connectors
To add validation to a sending connector, an implementation of the BeanValidator interface must be provided when building the connector.
public interface BeanValidator<T> {
BeanValidationReport validate(T message);
BeanValidator<T> withConnectorName(String connectorName);
}
The connector library provides a validator for bean validation using the Hibernate validator implementation. Validation is performed against the message once it has been transformed from a TransportMessage to the target type by the provided ReceiveTransportMessageConverter function.
Bean Validator
Messages are expected to be annotated with jakarta.validation annotations if they are to be validated with the bean validator implementation.
Bean validation is available with the BeanValidatorImpl.
It optionally takes a jakarta.validation.Validator representing the validator to use against which all messages passing through this validator will be validated.
If no validator is passed in, then a default validator is created.
public BeanValidatorImpl() {
this(Validation.buildDefaultValidatorFactory().getValidator());
}
public BeanValidatorImpl(jakarta.validation.Validator validator) {
this(null, validator);
}
BeanValidatorImpl(String connectorName, jakarta.validation.Validator validator) {
this.connectorName = connectorName;
this.validator = validator;
}
Validation is optional and can be enabled by providing an implementation of BeanValidator when building the connector.
receiveConnector = initiatingReceiveConnectorBuilder()
.withConnectorTransport(connectorTransport)
.withEventBus(eventBus)
.withBeanValidator(new BeanValidatorImpl<>()) (1)
.build();
| 1 | Adds the bean validator to the connector |