OpenEmcee Microflow Engine for Java

Home | Downloads | Project Information | Discussion Groups | Tutorials | Team

Documentation

Tutorials
JavaDoc
News

FAQ's

Lists/Support
Strange name?

Downloads

Downloads
CVS Access

 

 

 

 

 

 

 

 

 

 

 

 

 

An Intro to OpenEmcee Microflow Validators

By Scott Schenkein, Edited By Michael Roane

Welcome to the OpenEmcee Microflow Validator introduction. In my career as a systems programmer, I have often found myself looking for an elegant and repeatable way to validate the data flowing through systems. While input validation is an essential part of any stable system, it has a tendency to hinder the readability (and thus understandability) of code.

In our first installment, "An Intro Tutorial to OpenEmcee Microflows", we showed how we can use the OpenEmcee Microflow Engine to separate business logic from core program flow. In this article, we will demonstrate how we can use the framework to separate data validation from business logic, and program flow.

Data Permissions Revisited

Recall from the first tutorial that we register permissions for data that we wish to flow through our Microflow. We have removed all but one data permission from the other example here for sake of clarity.

<?xml version="1.0"?>

<!DOCTYPE openemcee-microflow-descriptor PUBLIC "-//OpenEmcee Software//Microflow Job Definition 1.0//EN" "http://openemcee.org/microflow/dtds/openemcee-mfjd-1_0.dtd">
<job-definition identifier="SampleJob">    <setup>        <permissions>           <data>          <name>account_id</name>           <type>java.lang.String</type>           </data>        </permissions>    </setup>

In this example, we use what is called "un-validated, typed data". In other words, the data is guaranteed to be of a certain type (here java.lang.String), but the content of that data is not guaranteed.

The problem we are solving

Let's say that our system is having issues because the system, which is generating our "account_id", sometimes returns garbage instead of an actual order number. For example, "COBOL EXC 9432, UNABLE TO DO PHYSICAL ORDER FETCH OF DATA" rather than "A348933434".

In order to maintain the integrity of our system, we are going to create a data validation routine. If we encounter an invalid "account_id", the system needs to cease processing to avoid any downstream impact.

Here are the requirements for our validation:

  1. The account number must be at least 10 digits long.
  2. It must start with a letter.
  3. It must not contain any characters that are not digits or numbers.

How we solve the problem

The OpenEmcee Microflow framework provides a validation interface. In order to use this interface, one must create a class which implements the "org.openemcee.microflow.usercore.PermissionedDataValidator" interface. This interface contains two methods:

public boolean setParameters(MicroflowParameters params);
public boolean validate(Object obj);

The "setParameters" method is called once when the Validator is created to expose any configuration parameters that are exposed in the XML. We'll talk about the syntax for those later.

The "validate" method is called AFTER a task that accesses or modifies the "validated" data completes.

The Java implementation for the Validator

As we discussed before, we are going to implement the "PermissionedDataValidator" interface to create our validator. Please see the following code, and its embedded comments to understand how this works.

package com.mybank.validators;

import org.openemcee.microflow.usercore.PermissionedDataValidator;
import org.openemcee.microflow.usercore.MicroflowParameters;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class AccountNbrValidator implements PermissionedDataValidator {

    private final static Log log
                    = LogFactory.getLog(AcctNbrValidator.class);

    private int minLength;

    //
    // You MUST have a default constructor, otherwise
    // your Microflow will fail with a CreationException
    public AcctNbrValidator() {}

    //
    // Here is where we read the required length from
    // the XML – more on the XML later.
    //

    public boolean setParameters(MicroflowParameters params) {
         String lenStr = params.getParameter(“min_length”);

         if(lenStr == null) {          
           log.error(“Unable to read ‘min_length’ from params.”);
           return false;  // Error…
         }

         try {
            minLength = Integer.parseInt(lenStr);
         } catch(NumberFormatException e) {
           e.printStackTrace();
           log.error(“Unable to convert to an int.”, e);
           return false; // Error…
         }

         //
         // Success!
         //
         return true;
    }

    //
    // Now we write our validation routine.
    //
    public boolean validate(Object obj) {
       String acctNbr = (String)obj;
       if(acctNbr.length() < minLength) {
          log.error(“Acct nbr is too short:” + acctNbr);
          return false;
       }

       char[] chars = acctNbr.getChars();
       for(int z = 0; z < chars.length; z++) {
         if(!Character.isLetterOrDigit(chars[z])) {
            log.warn(“Contains an illegal character:” + acctNbr);
            return false; // Failed
          }
       }
       return true; // success
    }

}

As you see in the above example, we implement the two methods, returning "true" for a success, and "false" for a failure.

Configuring and Installing your Validator

Now that we have created a validator, we are going to install it into our flow. Please see the following XML and inline comments.

<?xml version="1.0"?>
<job-definition identifier="SampleJob">
<setup>
<permissions>
<!-- DECLARE THE DATA WE ARE GOING TO USE IN OUR FLOW -->
<data>
<name>account_id</name>
<type>java.lang.String</type>
<!—ASSOCIATE THE PROPER VALIDATOR WITH THIS DATA -->
<validator>
<!—THE VALIDATOR WE JUST CREATED -->
<type>com.mybank.validators.AcctNbrValidator</type>
<params>
<param>
<!-- ADD THE PARAMETERS FOR setParameters() -->
<name>min_length</name>
<value>10</value>
</param>
</params>
</validator>

</data>
</permissions>
</setup>

Save your XML, (re)start your client, and you're on your way.

Validator Lifecycle

The Microflow Validator lifecycle is defined as follows:

1) A validator is created using the default constructor. If no public default constructor is available, the workflow terminates with a CreationException.
2) The method "setParameters()" is called (once, and only once per object).
3-n) The "validate()" method is called one or more time with one or more objects. There is no guarantee that the same Validator instance will be used for a particular object, or that the same object will be used with a particular Validator instance.
n+1) The Validator may or may not be orphaned thus making it eligible for garbage collection.

What we've learned

You have now seen how Validators can be used to ensure the integrity of data in an OpenEmcee Microflow, without impacting your business logic or program flow. Note that different Validators can be used in different "contexts" (Microflow Jobs) with the same data, making your core application tasks more reusable.

In a future release of OpenEmcee, we plan to provide some basic canned validators like "String Length", "Number Range", "Regular Expression Matches", etc… If you have an idea for a canned validator you'd like to see, please don't hesitate to send me your ideas, either directly or to the "openemcee-users" list.

Please let us know what you think about the product and this tutorial.

Click here to give your feedback. PLEASE don't forget to leave me your email so I can respond!

Thanks,

Scott Schenkein and the whole OpenEmcee Team


Any software or content on this or affiliated project site are released for your use under MPL 1.1 License.  Please see source code modules for complete license.


 

 
 

SourceForge.net Logo