On Java Development

All things related to Java development, from the perspective of a caveman.

Using Spring to Create Rules

without comments

Introduction

This post shows how Spring can be used to create classes that act as a rule processor or validator. The example presented is very simple but should serve to show the potential for other cases.

Rule Definition

Shown below is a Spring bean that define key/value pairs for the bean BaseStateCodeStateNameRule. The property values declared by this definition will be injected into the Java bean class of the same name and contains methods needed to validate either the state code or the state name.

The intent is that the state codes and names will be declared here once, but then reused or inherited by the beans that are defined below this bean, of which there are two. The first bean contains the rules for state codes and the second contains the rules for the state names. Scroll to the end of the BaseStateCodeStateNameRule bean definition to see them.

If you scrolled to the bottom, you should see the two declarations for the StateCodeRule and the StateNameRule, both of which declare their parent as BaseStateCodeStateNameRule which means these beans also get to use its property mapOfStateCodesAndNames . Each also declare the same property isActive which is a boolean designed to render themselves active and has the effect of rendering the rule active. The value of false would of course turn off the rule. For this property to do any good, the rule logic must check this before executing.

Without parent= “BaseStateCodeStateNameRule” specified, when asking Spring to return the bean StateCodeRule or StateNameRule from its context, Spring will return a brand new inheritance stack which results in an empty mapOfStateCodesAndNames in the parent class BaseStateCodeStateNameRule. When executing the rule, the following error is issued…

SEVERE: Servlet /restpolicysearch threw load() exception
java.lang.NullPointerException at
com.mig.restpolicysearch.process.rules.statecode.BaseStateCodeStateNameRule.
isStateCodeValid(BaseStateCodeStateNameRule.java:65)

…which is complaining about mapOfStateCodesAndNames being null.

If parent= “BaseStateCodeStateNameRule” is specified for StateCodeRule and StateNameRule , Spring correctly returns the inheritance stack that includes its view of the base class, which Spring injected with the map data for state codes and names.

To recap, a single bean definition is used to inject the name/value pairs for state codes and names into a single Java bean. Two other bean definitions were described so that they both inherit the name/value pairs so that they can each operate upon the mapOfStateCodesAndNames property in a manner that makes sense for their scope i.e. code or name.

In the sections that follow, the focus will be on the classes used to enhance reuse of base features and to enforce some architecture upon the developer. Don’t worry. It won’t hurt.

 
 
The BaseRule class

The BaseRule class is an abstract class containing methods that allow for the rule to be active and eligible for execution. The methods are placed here so that any rule classes extending this class will be able to inherit these methods and frees the developer from having to write them. In that way a functionality can be inherited.

Abstract classes cannot be instantiated but they can be subclassed by another abstract class or a class that can be instantiated which must then implement the abstract methods.

As can be seen the only methods declared are for the isActive property, which acts as an on/off switch.

The only class that will extend this class is ApplicationRule, presented below.

 
 
The ApplicationRule class

This class is also declared as abstract so it too cannot be instantiated. It defines two abstract methods which must be implemented by all subclasses which are the classes containing the rule needed by the application(s).

To recap at this point, BaseRule contains the on/off switch for the rule. It as the parent class for ApplicationRule

ApplicationRule is designed to extend BaseRule to enforce the implementation of methods process(Object dataElement) and execute(Object dataElement).

It should be clear at this point the developer wishing to create a new rule class should extend ApplicationRule.

 
 
The BaseStateCodeStateNameRule class

This class is an example of an application’s rule class and will be declared to Spring in the Spring configuration file. This class represents the starting point for creating a new rule. This particular rule class is designed to contain the state codes and names that Spring will inject into the property mapOfStateCodesAndNames. Classes like this one that extend from ApplicationRule must contain the logic that define the rules. Since this class is not declared as abstract it can be extended as in this example but it will probably prove to be rare. In this case, since state codes need validation as well as state names, this class will contain logic for both cases and will be extended by classes that will execute only the methods needed for its single case. This class (and others like it) is the container for the rules.

Normally, any class that extends ApplicationRule would also fully implement the methods process(Object dataElement) and/or execute(Object dataElement) both of which accept an object of an unknown type (TBD by the developer).

This class has methods to facilitate the validation of both the state code and the state’s name. For this rule’s design, two additional classes, StateCodeRule and StateNameRule will be employed to separate areas of concern, namely state code and state name, both of which will use the same property, i.e. mapOfStateCodesAndNames, for the their separate rule processing.

Since this class extends ApplicationRule the abstract methods declared by it must be implemented. Further, because this class has a dual purpose, the methods process(Object dataElement) and execute(Object dataElement) will have an empty implementation for this class. This means that the two other classes for state codes and state names will be providing the code for them since they will be doing the processing.

To recap at this point, the class presented above represents the class the developer creates. It contains all the rules needed. For this example, the processing is being broken into two areas of responsibility by the classes StateCodeRule and StateNameRule .

 
 
StateCodeRule class

This is the class that will validate state code. It extends BaseStateCodeStateNameRule presented above, so that it can inherit the methods needed from its parent, ApplicationRule.

Note the implementation for the method execute(Object dataElement) . It contains the logic needed to process the rule methods of its parent class. It is always called by the application, passing the data element with which to validate. If its a single value, it is simply cast to its type. In this case it is a String. If more than one element has to be passed, the developer would need to create a POJO to contain them, pass the POJO to the method which then casts it from an object to the POJO’s class type. From that point the method’s logic can then act upon the individual data elements.

For this example, the method process(Object dataElement) has no work to perform for state codes, but if future requirements call for it, logic will be placed there.

Note the use of the @Override annotation used to override the empty implementation of the parent class. Also note this class has its own isActive property. This makes it possible to inactivate this rule without affecting the other rule or BaseStateCodeStateNameRule .

 
 
The StateNameRule class

The class also extends BaseStateCodeStateNameRule presented above and fully implements the abstract methods as needed. Like the class before, it also implements the method execute(Object dataElement) with logic needed to process the rule methods of its parent class. Again, the method process(Object dataElement) has no work to perform for state codes, but if future requirements call for it, logic will be place in this method which will also separate any concerns for state names.

Also note the use of the @Override annotation used to override the empty implementation of the parent class.

 
 
The RuleResult class

As the name of this class implies, this class is designed to act as a container for the results of the rules processing. It’s simple enough so that not much explanation is needed. It holds messages that can be used by the application. The property isValid indicates the rule’s outcome with true meaning the data passed to the rule is good and false meaning not-so-good.

 
 
Testing

The code below illustrates how the StateCodeRule and StateNameRule classes are used to validate a state code and a state name.

The results of the test are seen in the log file and console as shown.

The log file entires:
2014-04-14 09:02:41 [localhost] [INFO ] STATE_CODE_MSG0001-State code BA is not valid.
2014-04-14 09:02:41 [localhost] [INFO ] STATE_NAME_MSG0001-State name Cansas is not valid.

Console entries:
Is data valid false
dumpMessagesToConsole SCM0001-State code BA is not valid.
Is data valid false
dumpMessagesToConsole SNM0001-State name Cansas is not valid.

 
 
The Design Drivers

Shown below is the class diagram for the design which is represented by the classes BaseRule and ApplicationRule.

For developers not used to Object Oriented Design (OOD) the comment might be, “Why does this design have to be so complicated?” Well, for one thing, it really isn’t that complicated. It only appears that way. Any basic RPG subfile program is much more complicated compared to this. Actually, the design follows basic OOD principles (abstraction and inheritance) to provide a small framework for all rules to use. There are distinct benefits and advantages to any design like this and the more adept at OOD the developer becomes, the more these principles become second nature and almost an afterthought.

The classes that implement the rules are represented by BaseStateCodeStateNameRule, StateCodeRule, and StateNameRule. Probably more often than not, the class represented by BaseStateCodeStateNameRule would be the only class the developer would have to provide for their use case and named accordingly.

The first two classes in the stack are already written and included in baseproject. Abstraction is used to enforce implementation of certain methods in the classes that extend from ApplicationRule. This helps to ensure the developer isn’t forgetting anything, because the IDE will remind them to implement only the methods needed and also helps to enforce the intent of the design. In addition, as the rules classes propagate through the application, they will immediately start to look the same in terms of method names. This injects some uniformity across the population of rules classes and also provide some design stability.

Another important benefit of the design is that it separates the rules and any associated data away from the application. Without doing that, there is little hope of being able to reuse them in other applications. Without such a design approach, validation logic would be tightly coupled to the application and each would then have duplicated validation logic. Little imagination is needed to visualize the maintenance headache if any aspect of embedded and duplicated rule logic needed to be changed.

Alternate approaches, such as formal rules engines, get more complicated and can be expensive. In the event that a rules engine does come along, there is nothing to prevent both strategies from being employed. For example, bulk of the company’s rules would reside in the rules engine to be administered by the business analyst and represents the core repository for business policies and rules. Any custom rules needed for the application could then use this design, which would help keep the rule engine’s definitions uncluttered by the introduction of one-off rules. In addition, rules using this small framework can be easily inventoried so that they could be considered for inclusion into the rule engine.

ApplicationRules

The state code/state name example presented showed how the classes StateCodeRule and StateNameRule extended its parent class. This situation probably an exception rather than the rule. However, this case has the benefit of showing how to solve this kind of bi-directional validation problem by defining two extra beans that inherit BaseStateCodeStateNameRule.

 
 
When to use a Rules Engine
This topic is best left to the documentation for JBoss Drools, which is a rules engine, to explain.

The shortest answer to this is “when there is no satisfactory traditional programming approach to solve the problem.”. Given that short answer, some more explanation is required. The reason why there is no “traditional” approach is possibly one of the following:

  • The problem is just too fiddle for traditional code.
  • The problem may not be complex, but you can’t see a non-fragile way of building a solution for it.
  • The problem is beyond any obvious algorithmic solution.
  • It is a complex problem to solve, there are no obvious traditional solutions, or basically the problem isn’t fully understood.
  • The logic changes often
  • The logic itself may even be simple but the rules change quite often. In many organizations software releases are few and far between and pluggable rules can help provide the “agility” that is needed and expected in a reasonably safe way.
  • Domain experts (or business analysts) are readily available, but are nontechnical.
  • Domain experts often possess a wealth of knowledge about business rules and processes. They typically are nontechnical, but can be very logical. Rules can allow them to express the logic in their own terms. Of course, they still have to think critically and be capable of logical thinking. Many people in nontechnical positions do not have training in formal logic, so be careful and work with them, as by codifying business knowledge in rules, you will often expose holes in the way the business rules and processes are currently understood.

If rules are a new technology for your project teams, the overhead in getting going must be factored in. It is not a trivial technology, but this document tries to make it easier to understand.

Typically in a modern OO application you would use a rule engine to contain key parts of your business logic, especially the really messy parts. This is an inversion of the OO concept of encapsulating all the logic inside your objects. This is not to say that you throw out OO practices, on the contrary in any real world application, business logic is just one part of the application. If you ever notice lots of conditional statements such as “if” and “switch”, an overabundance of strategy patterns and other messy logic in your code that just doesn’t feel right: that would be a place for rules. If there is some such logic and you keep coming back to fix it, either because you got it wrong, or the logic or your understanding changes: think about using rules. If you are faced with tough problems for which there are no algorithms or patterns: consider using rules.

Rules could be used embedded in your application or perhaps as a service. Often a rule engine works best as “stateful” component, being an integral part of an application. However, there have been successful cases of creating reusable rule services which are stateless.

For your organization it is important to decide about the process you will use for updating rules in systems that are in production. The options are many, but different organizations have different requirements. Frequently, rules maintenance is out of the control of the application vendors or project developers.

 
 
When not to use a Rules Engine
Again, from the JBoss Drools documentation:

To quote a Drools mailing list regular:

    It seems to me that in the excitement of working with rules engines, that people forget that a rules engine is only one piece of a complex application or solution. Rules engines are not really intended to handle workflow or process executions nor are workflow engines or process management tools designed to do rules. Use the right tool for the job. Sure, a pair of pliers can be used as a hammering tool in a pinch, but that’s not what it’s designed for. –Dave Hamu

As rule engines are dynamic (dynamic in the sense that the rules can be stored and managed and updated as data), they are often looked at as a solution to the problem of deploying software. (Most IT departments seem to exist for the purpose of preventing software being rolled out.) If this is the reason you wish to use a rule engine, be aware that rule engines work best when you are able to write declarative rules. As an alternative, you can consider data-driven designs (lookup tables), or script processing engines where the scripts are managed in a database and are able to be updated on the fly.

 
 
Summary

This post showed how Spring can be used to create validation rules. As an example, a Spring definition and bean was employed to facilitate the validation of state codes and names. The class also supported conversion of state codes to their formal name and back again.

With this approach it is possible to create rules for just about anything. A few possibilities are named below.

  • Range validation
  • Look-up operations (this example)
  • JSF component loading with valid values (pick lists, etc.)
  • Input validation
  • A store of default values for table fields

The benefits of this approach are:

  • Since rule definitions are contained within their own Spring context definition file, they can be reused across multiple projects. Because of this centralization, changes can be made more reliably and remove duplication across the source base.
  • Rules classes are of course also reusable.
  • The rules are easily changed and can be made inactive as the case arises which can facilitate use of alternate processes and values.
  • Rule execution can be controlled at a granular level by defining booleans for the rule. For example entries such as those shown below can be included for a rule definition. Unlike the isActive property assigned for the whole bean, which should be viewed as belonging to the entity, entries like those below can be used to control validation of certain properties of the entity.

  • Definitions can be shared across multiple beans. (State codes for vendor and customer, etc.)
  • Because rule logic is contained in their own rule class, the same rules are therefore employed across all services using them.
  • When validation occurs before record commit, data is assured to be written in the expected form. For example, when dates are stored as integers, validation can ensure the value is in a certain format, such as “YYYYMMDD” as apposed to “MMDDYYYY”. With centralized date rules and employing them at the service level, errors introduced by the developer can be mitigated. For example, the browser component allowed a date to be entered as “MMDDYYYY”, but the rule class employed by the service prevented its persistence into the database. This case can arise when the service and DAO layers reside in a REST or SOA based service on another networked server.

 
The Spring configuration file and supporting classes are included in baseproject.

Written by admin

April 11th, 2014 at 11:09 am

Leave a Reply

You must be logged in to post a comment.