In the last installment, we started a discussion about data validation, which is one of the essential components of enterprise application design. After a quick review of the two types of data validation, data-format validation and business-specific validation, we discussed the most beneficial placement of each type of validation logic in your application code. We ended up with good, workable solutions for both data-format and business-specific validation, but we didn't really address the larger complexities you might face in this area of programming.
Specifically, we decided the best way to deal with data-format validation code was to keep it close to the client, thus keeping the processing overhead to a minimum. Because our example application included a business delegate class, we placed the validation logic there. The problem with this placement is that it could introduce a lot of redundancy into your code.
In this tip, we'll revisit data-format validation, introducing a data validation helper class, which will let us keep the validation procedures close to the client without introducing any unnecessary code.
Consolidating validation logic
It's quite common to have the same data type used as an argument to multiple business methods, across multiple business delegates. For example, a book's ISBN might be passed to the search method of an Inventory delegate and the purchasing method of a Payment delegate. If our validation logic were tied to the business delegates, as it was in the last tip, we would end up with ISBN validation code in both of these methods.
The first step to improving our data-format validation procedure is to move all the validation logic into a single helper class, from which other methods can invoke it as needed. This type of consolidation both reduces code redundancy and makes it possible to maintain and change our application's data formats when we need to.
To achieve consolidation, we'll use a Validator class, which simply provides static methods for the various data types we need to validate. Listing 1 shows the shell for such a class.
Note that the simple methods in Listing 1 can be called from other classes, such as our business delegates, to perform validation logic as needed. Also note that the methods do not return boolean values.
Listing 1. A Validator skeleton
package com.ibm.validation;
import java.util.Iterator;
import java.util.List;
public class Validator {
public static void validateISBN(String isbn)
throws InvalidDataException {
// Check the data type, and throw an error if
// needed
}
public static void validateIPAddress(String ipAddress)
throws InvalidDataException {
// Check data type
}
public static void validateUPC(String upc)
throws InvalidDataException {
// Check data type
}
public static void validateUPC(float upc)
throws InvalidDataException {
validateUPC(new String(upc));
}
public static void validateList(List list, Class class)
throws InvalidDataException {
for (Iterator i = list.iterator(); i.hasNext(); ) {
Object obj = i.next();
if !(obj instanceof class) {
throw new InvalidDataException("This list only " +
"accepts objects of type " +
class.getName());
}
}
}
}
|
Listing 2 shows the kind of cluttered code that would result from using boolean return values.
Listing 2. Using boolean return values in the Validator
public boolean checkout(List books) throws ApplicationException {
if (Validator.validateList(books, Book.class)) {
try {
return library.checkout(books);
} catch (RemoteException e) {
throw new ApplicationException(e);
}
}
}
public Book lookup(String isbn) throws ApplicationException {
if (Validator.validateISBN(isbn)) {
try {
return library.lookup(isbn);
} catch (RemoteException e) {
throw new ApplicationException(e);
}
}
}
|
In more complex methods, the above nesting could get even more cluttered. We've avoided this extra level of complexity and kept our code much cleaner by simply allowing exceptions to be thrown. In addition, note that InvalidDataException extends ApplicationException. This allows the signature of all of the delegate methods to stay the same, and therefore also allows any validation exceptions to be thrown through the same
mechanism. We avoid having to either add another throws clause to the method signature, or having to add another try/catch block to the method body. In short, it keeps our code clean and simple rather than riddled with brackets, application exceptions, validation exceptions, and if/then and try/catch blocks.
With the Validator in place and set up for the specific data types we need to validate, it's a snap to use it in our application, and specifically in our business delegate methods. Listing 3 shows the delegate from the last tip, reworked to use the new Validator class.
Listing 3. Data-format validation in the business delegate
package com.ibm.library;
import java.rmi.RemoteException;
import java.util.Iterator;
import java.util.List;
import javax.ejb.CreateException;
import javax.naming.NamingException;
import com.ibm.validation.Validator;
import com.ibm.validation.InvalidDataException;
public class LibraryDelegate implements ILibrary {
private ILibrary library;
public LibraryDelegate() {
init();
}
public void init() {
// Look up and obtain our session bean
try {
LibraryHome libraryHome =
(LibraryHome)EJBHomeFactory.getInstance().lookup(
"java:comp/env/ejb/LibraryHome", LibraryHome.class);
library = libraryHome.create();
} catch (NamingException e) {
throw new RuntimeException(e);
} catch (CreateException e) {
throw new RuntimeException(e);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
}
// No validation required for accessor (getter) methods
public boolean checkout(Book book) throws ApplicationException {
// No validation required here; the object type
// takes care of it
try {
return library.checkout(book);
} catch (RemoteException e) {
throw new ApplicationException(e);
}
}
public boolean checkout(List books) throws ApplicationException {
// Validate list
Validator.validateList(books, Book.class);
try {
return library.checkout(books);
} catch (RemoteException e) {
throw new ApplicationException(e);
}
}
public Book lookup(String isbn) throws ApplicationException {
// Validate ISBN
Validator.validateISBN(isbn);
try {
return library.lookup(isbn);
} catch (RemoteException e) {
throw new ApplicationException(e);
}
}
// And so on...
public void destroy() {
// In this case, do nothing
}
}
|
Using a stand-alone Validator has rendered our code more modular and maintainable. Additionally, we've moved all our validation logic into one place, avoiding redundancy in the code. The result is a better, less bug-prone application.
In the next tip in this series, we'll examine the other side of validation: exception handling. Until then, I'll see you online.
- The tutorial Getting started with Enterprise JavaBeans technology (developerWorks, April 2003) provides a comprehensive introduction to Enterprise JavaBeans technology.
- In his article "Best practices in EJB exception handling" (developerWorks, May 2002), Java architect Srikanth Shenoy demonstrates how to code for faster problem resolution on EJB technology-based systems.
- Sun Microsystems EJB technology home page is a good starting place for information on EJB technology.
- Another great resource, TheServerSide.com, offers articles and information pertaining to J2EE.
- See the developerWorks Java technology tutorials page for a listing of free EJB technology- and J2EE-related tutorials from developerWorks.
- Find hundreds more Java technology resources on the developerWorks Java technology zone.

Brett McLaughlin has been working in computers since the Logo days (remember the little triangle?). He currently specializes in building application infrastructure using Java and Java-related technologies. He has spent the last several years implementing these infrastructures at Nextel Communications and Allegiance Telecom, Inc. Brett is one of the co-founders of the Java Apache project, Turbine, which builds a reusable component architecture for Web application development using Java servlets. He is also a contributor of the EJBoss project, an open source EJB application server, and Cocoon, an open source XML Web-publishing engine. Contact Brett at brett@oreilly.com.
Comments (Undergoing maintenance)





