V1.2:validation-basic

From Smooks

Jump to: navigation, search

This example illustrates how Smooks can be used to perform Validation of message fragment data. It performs two types of Validation using two different types of Validation rules:

  1. Message field value/format validation using Regular Expressions (Regex) defined in a .properties file RuleBase e.g. validating a field as being a valid email address.
  2. Business Rules validation using MVEL expressions defined in a .csv file RuleBase e.g. validating that the total price of an order item on an order (price * quantity) does not breach some predefined Business Rule.

For more on Smooks Rules and Validation, see the Smooks v1.2 User Guide.

Contents

Executing the example is quite simple. From the example root folder, execute:

  1. "mvn clean install"
  2. "mvn exec:java"

Example source can be viewed and/or checked out from SVN here.


References:


(Back to Examples Index Page...)

The Input Message

The message use in this example is an XML order message containing a collection of order items. This functionality works similarly for all other data formats supported by Smooks i.e. EDI, CSV, Java, JSON etc

<Order>
<header>
<orderId>A188127</orderId>
<username>user1</username>
<name>
<firstname>Harry</firstname>
<lastname>Fletcher</lastname>
</name>
<email>harry.fletcher@gmail.</email>
<state>South Dakota</state>
</header>
<order-item>
<quantity>1</quantity>
<productId>364b</productId>
<title>The 40-Year-Old Virgin</title>
<price>29.98</price>
</order-item>
<order-item>
<quantity>2</quantity>
<productId>299</productId>
<title>Pulp Fiction</title>
<price>29.99</price>
</order-item>
</Order>

Overview

We want to perform a number of validations on the order message data:

  1. That the supplied <username> follows a format of an upper case character, followed by five digits e.g. "S12345" or "G54321". We perform this validation using a Regular Expression.
  2. That the supplied <email> is a valid email address format. We perform this validation using a Regular Expression.
  3. That the <productId> field of each order item follows a format of exactly three digits e.g. "123" or "321". We perform this validation using a Regular Expression.
  4. That the order item total for each order item does not exceed 50.00 (price * quantity < 50.00). We perform this validation using an MVEL Expression.

Defining the Validation Rules

In this example we have divided the Regex rules into 2 separate .properties files and dropped them into the "rules" folder of the example. The MVEL expression will be located in a .csv file, also in the "rules" folder of the example.

The customer related Regex rules are in the "customer.properties" file:

# Customer data rules...
customerId=[A-Z][0-9]{5}
 
# Email address...
email=^[\\w-\\.]+@([\\w-]+\\.)+[\\w-]{2,4}$

The product related Regex rule is in the "product.proeprties" file:

# Product data rules...
productId=[0-9]{3}

The MVEL expression for performing the oreder item total check is located in the "order-rules.csv" file. The easist way to edit a .csv file is through a Spreadsheet application like OpenOffice or Excel:

Image:MVEL-csv-rulebase-example.png

Defining the Localized Message

This is simply a case of creating ResourceBundle .properties files for each of the rule source files. The names of the message resource bundle .properties files are based on the names of their corresponding rule files. See the User Guide for more details.

The message bundle for the rules defined in "rules/customer.properties" are located in the "rules/i18n/customer.properties" file (in the same folder):

customerId=ftl:Invalid customer number '${ruleResult.text}' at '${path}'.  Customer number must begin with an uppercase character, followed by 5 digits.
email=ftl:Invalid email address '${ruleResult.text}' at '${path}'. Email addresses match pattern '${ruleResult.pattern}'.

The message bundle for the rule defined in "rules/product.properties" are located in the "rules/i18n/product.properties" file (in the same folder):

# Product data rule messages...
productId=ftl:Invalid product ID '${ruleResult.text}' at '${path}'. Product ID must match pattern '${ruleResult.pattern}'.

The message bundle for the rule defined in "rules/order-rules.csv" are located in the "rules/i18n/order-rules.properties" file (in the same folder):

# Order item rule messages. The "orderDetails" and "orderItem" beans are populated by Smooks bindings - see config in following section.
order_item_total=ftl:Order ${orderDetails.orderId} contains an order item for product ${orderItem.productId} with a quantity of ${orderItem.quantity} and a unit price of ${orderItem.price}. This exceeds the permitted per order item total.

Smooks Configuration

The configuration for applying these validation rules is as follows:

<?xml version="1.0"?>
<smooks-resource-list xmlns="http://www.milyn.org/xsd/smooks-1.1.xsd"
xmlns:rules="http://www.milyn.org/xsd/smooks/rules-1.0.xsd"
xmlns:validation="http://www.milyn.org/xsd/smooks/validation-1.0.xsd"
xmlns:jb="http://www.milyn.org/xsd/smooks/javabean-1.2.xsd">
 
<params>
<!-- Generate a ValidationException if we get more than 5 validation failures... -->
<param name="validation.maxFails">5</param>
</params>
 
<!-- Define the ruleBases that are used by the validation rules... -->
<rules:ruleBases>
<!-- Field value rules using regex... -->
<rules:ruleBase name="customer" src="rules/customer.properties" provider="org.milyn.rules.regex.RegexProvider"/>
<rules:ruleBase name="product" src="rules/product.properties" provider="org.milyn.rules.regex.RegexProvider"/>
 
<!-- Order business rules using MVEL expressions... -->
<rules:ruleBase name="order" src="rules/order-rules.csv" provider="org.milyn.rules.mvel.MVELProvider"/>
</rules:ruleBases>
 
<!-- Capture some data into the bean context - required by the business rule validations... -->
<jb:bean beanId="orderDetails" class="java.util.HashMap" createOnElement="header">
<jb:value data="header/*"/>
</jb:bean>
<jb:bean beanId="orderItem" class="java.util.HashMap" createOnElement="order-item">
<jb:value data="order-item/*"/>
</jb:bean>
 
<!-- Target validation rules... -->
<validation:rule executeOn="header/username" name="customer.customerId" onFail="ERROR"/>
<validation:rule executeOn="email" name="customer.email" onFail="WARN"/>
<validation:rule executeOn="order-item/productId" name="product.productId" onFail="ERROR"/>
 
<validation:rule executeOn="order-item" name="order.order_item_total" onFail="ERROR"/>
 
</smooks-resource-list>

Smooks Execution Code

The code for executing this from the Main class in the example:

protected static ValidationResult runSmooks(final String messageIn) throws IOException, SAXException, SmooksException {
// Instantiate Smooks with the config...
final Smooks smooks = new Smooks("smooks-config.xml");
 
try {
// Create an exec context - no profiles....
final ExecutionContext executionContext = smooks.createExecutionContext();
final ValidationResult validationResult = new ValidationResult();
 
// Configure the execution context to generate a report...
executionContext.setEventListener(new HtmlReportGenerator("target/report/report.html"));
 
// Filter the input message...
smooks.filterSource(executionContext, new StringSource(messageIn), validationResult);
 
return validationResult;
}
finally {
smooks.close();
}
}

The console output after executing this example:

Image:Validation-example-output.png