Implementing Validation Rules using Aspects Blog

Version 2



    Da ta Validation Rules
    Rules Engines
    Data Validation: Cross-Cutting Concern?
    Validation Framework
    Sampl e Application
    Loan Application Use Case
    Testing Validation Rules

    Two years ago, I worked on a web portal project where we implemented a custom validation framework to validate the data entered by the user. I defined validation rules in XML files and wrote Java code to parse and apply the rules to different data fields on the web pages. One of the limitations of this solution was that we had to add or modify code--on both client and server tiers--whenever we added new fields on the screens that needed data validation or when validation rules changed, per business requirements. If I had to write the validation module again, I would use aspects to dynamically weave validation logic into the application code. With aspects, it would be more flexible to inject validation into any existing code, whether it's on the client, to verify if user entered data is valid, or on the server, where we want to make sure the data is accurate before populating it into database tables.

    This article provides an overview of AOP-based data validation implementation in a sample loan processing application. We will look at validation rules for data fields with different validation requirements, which is common in most real-world applications. We will use annotations-based aspects (using AspectJ) to dynamically weave validation rules into existing application code where the data validation is required.


    Data validation (also known as primary validation orsanity check) is an essential requirement in any Java EE application. Input data, whether it's entered by a user on a HTML form or as the input parameters coming from an external web service client, needs to be checked for valid data type, format, and the accuracy of the data to ensure that it complies with data integrity requirements before we actually process and store it in a back-end database. Failure to detect invalid data could result in bad data getting into the database.

    In some applications, data validation may be a trivial task because the data validation requirements are pretty straightforward and writing a separate validation module is an overkill. But in other enterprise applications (especially in financial, insurance, or manufacturing companies), data validation is a vital part of the application, and extensive validation rules are required to validate the data transmitted across different tiers of the application.

    Security is another important consideration in data validation. With new regulations like the Sarbanes Oxley Act (SOX), validating user input has become one of the most important elements of application design. Security vulnerabilities such as cross-site scripting, phishing, and SQL injection could lead to major security attacks on corporate websites. Stephen Enright wrote a two-part series of articles ( part one, part two) on the importance of validating user input and best practices on how to handle the data validation.

    Data validation logic is usually hard-coded in the application code, tightly coupled with core business logic. This design doesn't give us much flexibility to implement any validation rule changes that occur due to the dynamic nature of the business. And if there are any new data fields that need the same validation logic as one of the existing fields, we have the same problem. We have to write code to add validation logic to each new field. In most Java EE applications, we need to check data validity both in the web layer (servlet container) and the business logic layer (application server).

    We can address all of these problems by defining validation rules in an XML file (or even better, by using a rules engine) and dynamically inject the rules (using AOP) into those parts of application code where validation is required. This approach gives us a loosely coupled and extremely flexible validation framework.

    There are different ways of implementing data validation on the web client and on the server. JavaScript is the most common script language used on the client, and Struts Validator, Spring Validator, or some kind of custom validation framework is used in the MVC and service layers. The following table summarizes these data validation techniques with their usages and limitations.

    Validation FrameworkTierUsageLimitation
    JavaScriptWeb client (browser)Detect invalid data on the client before passing it to server.Limited to data validation in the browser. JavaScript code is not reusable in other layers of the application. Also, the web user can disable JavaScript execution in the browser, meaning the validation code will not run.
    Spring ValidatorMVC (servlet container)Used in the controller class to check the validity of data submitted by the client before sending it to the service or DAO layers. This way, invalid data is detected in the MVC layer rather than passing it all the way to application or database servers.Limited to MVC layer. We can't use validation rules defined in the XML file in other layers of the application. It's also limited to basic validation; we can't really use it to define business-rules-based validations.
    Commons ValidatorMVC/serviceThis framework provides a configurable validation engine and reusable methods on primitive data validations.We can't really use this framework as a robust business rules validation tool.
    Custom Validation FrameworkMVC/service/DAOA customized solution, so we can design it to address specific validation requirements in enterprise applications.Coding, testing, and maintenance overhead. May not be as extensive and flexible as the available validation frameworks.

    Data Validation Rules

    Typically, data validation requirements have the following characteristics.
    1. Validation rules should be simple and atomic.
    2. Validation rules range from basic checks such as data type (integer or string) and format (SSN or date), to rules that use sophisticated business logic to verify if submitted data is valid.
    3. We need to perform data validation on the client so we don't send any invalid data all the way to server, realize it's not valid, and send it all the way back to the client. The users may have to wait longer before they are told the entered data is invalid, and they have to re-enter or modify the data. It could also add significant overhead on network resources to send data between the web client and application server. Client validations usually include basic checks such as checking data type, format, and so on.
    4. We need to perform similar validation checks on the server to make sure submitted data is good enough to be populated in the back-end database. We need server-side validation if there are multiple client applications, accessing the same server code, that are written in different programming languages such as a servlet or programs in Java Swing, PowerBuilder, or Visual Basic. Server validations are usually more sophisticated than client-side checks and include checking for some business rules in addition to basic data type checks.

    Nowadays, rules engines are gaining more popularity in encapsulating business and validation rules in enterprise applications to reduce the cost of managing the rules. Let's briefly take a look at the advantages of using a rules engine to capture business rules.

    Rules Engines

    Rules engines collect complex decision-making logic and work with a group of rule sets, usually defined in XML files, to make decisions on what action needs occur when a specific condition is true. The main driving factor behind using a rules engine for managing rules is that business rules change very often and customers (end users) are always demanding that these changes be rolled out into a production environment as soon as possible to keep up with competitors. Managing business logic using a rules engine gives us the flexibility we need to keep up with the dynamic nature of business process.

    Following are some of the rules engine frameworks (both open source and commercial) that are currently available:

    Data Validation: Cross-Cutting Concern?

    In most Java enterprise applications, we have to implement client and server validations. For these validations, we could use different implementations on the client and server. For example, we could use Struts Validator (or Spring Validator) in the MVC layer and a custom validation framework on the server. But then we would have to change code in two places whenever validation rules change for a specific data field, as business requirements change from time to time.

    Data validation cuts across different application layers and can be treated as a cross-cutting concern, just like other cross-cutting concerns like persistence, security, exception handling, and object caching. It makes a lot of sense to use aspects to add validation logic into existing application code.

    Before we get into the details of a validation framework and its implementation using rules engine and aspects, let's compare the traditional way of implementing data validation in a Java EE application to an aspect-oriented data validation. The following table lists the steps involved in implementing data validation in a typical application.

     # TaskApplication LayerTraditionalAspect-Oriented
    1Client submits the form filled in with data. Check the data to make sure data format and values are acceptable.Web clientUse JavaScript to process data validation in the browser.Define validation rules using XML and a rules engine.
    2Validate data submitted by client for data accuracy.MVC layerUse Spring Validator or similar framework to perform data validation.Write validation code outside of the actual application code.
    3Check the data again to make sure it's valid and passes business validation rules.Service layerDesign and implement validation logic in the server code.Define aspects to inject validation logic into the application code (MVC or service layers).
    4FlexibilityAll layersValidation code is tightly coupled with application code. Changes in validation code impacts the application code, and vice versa.Loosely coupled and flexible, so validation and application code can change independently.

    Validation Framework

    I created a sample application called LoanProc to use the proposed AOP Data Validation framework. This application is a home loan processing application in a mortgage lending company. The LoanProc application source is in the sample code (see Resources below). Let's take a look at some of the objectives we want to accomplish in the AOP Validation framework.

    • Validation rules should be easy to define and maintain without having to modify any Java code.
    • The validation layer should be a centralized point for all validations in the application. Data validation should occur in any application tier without duplicating validation code in each tier.
    • Validation code should be written and maintained declaratively rather than programmatically.
    • Validation code should be flexible so it will be easier to modify the logic whenever business requirements change.
    • The framework should give us the ability to apply validation rules on new data fields without having to write the same logic each time a new field is added on a web page or a server module.
    • The validation layer should be completely separate from the other application layers.

    Sample Application

    To keep it simple for demonstration purposes, our sample loan application page includes four data fields to show how validation rules can be applied to fields with various data types and formats. These validations include basic checks on date of birth and SSN fields, and server validations on loan amount and loan to value (LTV) fields. Following table shows the details of these validations.

    Field NameData TypeClient Validation RulesServer Validation Rules
    Date of BirthDateValid dateNone
    SSNNumberData must be a number, nine digits in lengthNone
    Loan AmountBigDecimalMust be a numberValue cannot be more than 1,000,000
    LTVNumberMust be a number. Value must be less than 1.0LTV cannot be more than 0.85. (This means that we don't want to offer a loan to those who are not putting down at least 15 percent of the loan amount as down payment.)

    It's a good practice to define the validation rules for each module or web page in a separate rules XML file. I defined loan application validation rules in a text file calledLoanApplicationRules.xml.


    I used different open source technologies and frameworks in the sample application. I chose the Drools rules engine framework to define validation rules. Drools is getting more attention in capturing business rules in Java enterprise applications. Check out the article "Give Your Business Logic a Framework with Drools" for more information on using Drools for implementing business logic. I also used the Spring and Hibernate frameworks in service and data access layers, respectively, as these frameworks provide loosely coupled, flexible, and extensible solutions when working on business logic and object-relational modeling tasks. I used AspectJ (version 5.0) to define validation aspects and weave them into controller and service layers of the application. The table below lists these technologies by the application tier.

    ClientJUnit, HttpClient
    MVCSpring MVC
    ServiceSpring Framework
    RulesDrools 2.0
    AOPAspectJ, AJDT 1.3
    Application ServerJBoss 4.0
    DatabaseHypersonic SQL
    IDEEclipse 3.1

    Note: I used AJDT 1.3 for the latest Eclipse version (3.1). This is not a stable release. If you want to test the sample application using a stable AJDT release, use AJDT 1.2 for Eclipse 3.0. Also make sure the Eclipse project is set up with J2SE 5.0, since the application uses annotations to define aspects.

    Loan Application Use Case

    The use case for the loan processing application starts with the user entering loan details in an HTML form and submitting it, which triggers data validation on both the client and server tiers. Depending on successful data validation, a confirmation number is provided to the user that can be used for future inquiries on the loan application. These steps are shown in the sequence diagram in Figure 1.


    Figure 1
    Figure 1. Loan Processing application data flow (Click on the screen shot to open a full-size view.)

    Now, let's look at the main components of the sample application.

    1. Client interface: I used Spring MVC for the controller (web navigation) layer in the loan processing application. This includes a JSP as the view and a Spring Controller to handle the navigation.
    2. The listing below shows the sample code of theonSubmit method controller class (LoanApplicationController).

      protected ModelAndView onSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) throws Exception { System.out.println("Enter onSubmit()."); LoanApplication loanApp = (LoanApplication)command; System.out.println("LoanApplication:\n"+loanApp.toString()); int confirmationNumber = service.registerLoanApplication(loanApp); // Get opportunities request.setAttribute("confirmationNumber", Integer.toString(confirmationNumber)); return new ModelAndView(getSuccessView()); } 
    3. Service layer: I used Spring for writing the service layer that calls the DAO object to perform CRUD operations on theLoanApplication table in the back-end database.
    4. A code snippet of the registerLoanApplicationmethod in the LoanApplicationService class is shown below.

      public int registerLoanApplication(LoanApplication loanApp) { int confirmationNumber = 0; try { dao.updateLoanApplication(loanApp); // Get confirmation number for the submitted loan application confirmationNumber = dao.getLoanApplication( loanApp.getLoanAppId()).getConfirmationNumber(); } catch (DAOException e) { log.error(e,e); } return confirmationNumber; } 
    5. Database: I created the loandb database using the Hypersonic SQL database. The database has a single table called LoanApplication.
    6. Rules: I defined validation rules in an XML file and used the Drools API to load and apply these rules to the data fields.
    7. The validation rules for the loan application fields are defined in rules XML files as shown below.

      <?xml version="1.0"?> <rule-set name="LoanApplicationRules" xmlns="" xmlns:java="" xmlns:xs="" xs:schemaLocation=" rules.xsd java.xsd"> <!-- Java Imports --> <java:import>java.lang.Object</java:import> <java:import>java.lang.String</java:import> <java:import>com.loanapp.domain.LoanApplication</java:import> <!-- Java function to print message --> <java:functions> public void printMessage( com.loanapp.domain.LoanApplication loanApp, String msg) { System.out.println(msg); } </java:functions> <!-- Validate SSN --> <rule name="SSN Validation"> <parameter identifier="loanApplication"> <class>LoanApplication</class> </parameter> <java:condition> loanApplication.getSsn().length() < 9 </java:condition> <java:consequence> printMessage(loanApplication, "Invalid SSN - should be 9 digits."); </java:consequence> </rule> <!-- Check Loan Amount --> <rule name="LoanAmount Is High"> <!-- Parameters --> <parameter identifier="loanApplication"> <class>LoanApplication</class> </parameter> <!-- Validate the data field --> <java:condition> loanApplication.getLoanAmount().intValue() > 1000000 </java:condition> <java:consequence> printMessage(loanApplication, "LoanAmount is higher than the allowed limit."); </java:consequence> </rule> </rule-set> 

      And the code implementation of loading these validation rules using Drools API is as follows:

      public void doValidation(BaseDomainObject domainObj) throws ValidationException { runValidationRules(domainObj); } public void runValidationRules(BaseDomainObject domainObj) { try { // Validation Rules File Name String ruleFileName = domainObj.getClass().getName()+"Rules.xml"; // Load the validation rules loadRules(ruleFileName); WorkingMemory workingMemory = validationRules.newWorkingMemory(); workingMemory.addEventListener( new DebugWorkingMemoryEventListener()); workingMemory.assertObject(domainObj); // Fire rules workingMemory.fireAllRules( ); } catch (Exception e) { } } /** * Load the business rules from the xml file */ private static void loadRules(String ruleFileName) throws Exception { if (validationRules == null) { //Specify this resolver when we load are rules validationRules = RuleBaseLoader.loadFromUrl( BusinessLayer.class.getResource( "/rules/"+ruleFileName)); } } 
    8. Aspects: I wrote aspects to apply validation rules to various data fields (or methods, in the case of server code) in the loan application. We inject these rules into the controller (MVC layer) and service classes to implement the validation rules wherever we need them. For more information on Aspects and AOP check, out the articles "Introduction to Aspect-Oriented Programming" and "Performance Analysis of J2EE Applications Using AOP Techniques."
    9. The following listings show the pointcuts and advices defined to inject validation code into theLoanApplicationController andLoanApplicationService classes, respectively.

      Here's a pointcut and around advice to intercept theonSubmit() method and apply validation on theLoanApplication object.

      @Pointcut( "execution(* *.onSubmit(..)) && args(request, response, command, errors)" ) void executeOnSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) {}; @Before("executeOnSubmit(request, response, command, errors)") public void beforeOnSubmit(HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) { System.out.println("beforeOnSubmit"); } @Around("executeOnSubmit(request, response, command, errors)") public Object aroundOnSubmit(ProceedingJoinPoint jp, HttpServletRequest request, HttpServletResponse response, Object command, BindException errors) { Object proceedResult = null; System.out.println("aroundOnSubmit"); try { DataValidator validator = new DataValidator(); BaseDomainObject domainObj = (BaseDomainObject)command; validator.doValidation(domainObj); proceedResult = jp.proceed(); } catch (Throwable t) { log.error(t,t); } return proceedResult; } 

      Here's the pointcut and advice for theregisterLoanApplication() method inLoanApplicationService class.

      @Pointcut( "execution(* *.registerLoanApplication(..)) && args(loanApp)" ) void executeRegisterLoanApplication(LoanApplication loanApp) {}; @Before("executeRegisterLoanApplication(loanApp)") public void beforeRegisterLoanApplication ( LoanApplication loanApp) { System.out.println("before"); } @Around("executeRegisterLoanApplication(loanApp)") public int aroundRegisterLoanApplication ( JoinPoint thisJoinPoint, LoanApplication loanApp) { System.out.println("aroundRegisterLoanApplication"); return 0; } 

    Figure 2 shows the different elements of the validation framework and their relationship with each other.


    Figure 2
    Figure 2. Application setup diagram (Click on the screen shot to open a full-size view.)

    Testing Validation Rules

    I wrote two JUnit test scripts (DataValidatorTestand LoanApplicationControllerTest) to verify that validation is working correctly by submitting both valid and invalid data. If validation fails, we set thevalidation flag in the LoanApplicationobject to false, indicating that the data cannot be sent to the server. LoanApplicationControllerTest is a good example, since it can be executed outside the J2EE container and the DAO returns a test confirmation number. I also wrote a test client (called LoanApplicationClient) using Commons HttpClient to simulate a web request with data fields filled in with the loan application details. Once the Submit button is clicked, validation rules are applied to the submitted data and validation errors are returned for any invalid data.

    If basic validation passes, server-side validation rules are then applied on the data sent by the client. If there is a violation of any of the rules, server will return error messages for the invalid data.


    In this article, we looked at the implementation of data validation rules using a rules engine and aspects. Data validation is an essential part of any enterprise application, and using aspects to implement it offers the flexibility to respond in an agile manner to any changes in validation requirements.

    We defined data validation rules using a rules engine (Drools) and used aspects to weave validation logic in those classes where validation is required to verify the quality of user-entered data.

    Since we need some kind of validation on the web client so that we don't send any invalid data past the client layer, a better solution is to use JavaScript for basic validation (such as checking empty or null values and format) and process all other types of validations (such as checking for value and business validations) using a centralized custom data validation framework.

    Sometimes, validation rules are stored in a SQL database. It's a good idea to store the validation rules in memory (cache) after loading them from the database for the first time. This way, we won't be hitting the database every time we need to validate a data field.

    An administration tool to add new validation rules or modify or delete existing rules (preferably a JMX-based solution) would be a nice enhancement to the proposed validation framework.

    Note that both object caching and monitoring are also cross-cutting concerns that can use the help of aspects for their implementation. Check out this article on how we can implement object caching using AOP techniques.