Tuesday, December 18, 2007

Use Enumeration instead of Constant

Using Enumeration instead of Constant

I think we all regularly use integer or String status codes or other magic numbers in our Java code. And we probably also define (static final) constants to make these constants known to the users of our code. While this works fine for small projects, I noticed, when working on larger scale project, that I spent a considerable amount of time trying to find which constants I needed.

In many applications I encounter, this kind of API for a service is quite common:
public static final String DOCUMENT_TYPE_TEXT = "text";
public static final String DOCUMENT_TYPE_SPREADSHEET = "spreadsheet";
List findDocuments(String documentType);
In the above API, it is pretty obvious that I should use the listed constants as the documentType parameter. However, I have seen many cases where the constants are defined in some other place and sometimes an archeology expedition was needed to find the correct values to use. I also have the freedom to pass any String that I didn't get from a constant and just hardcoded. Because of this freedom, the service must check if the passed in documentType parameter is valid (who knows what the user passes to the service).

To make the API more watertight, we could require the user to supply a constant of a class that we define ourselves:
List findDocuments(DocumentType documentType);
This is the DocumentType class:
public class DocumentType {
public static final DocumentType TEXT = new DocumentType("text");
public static final DocumentType SPREADSHEET = new DocumentType("spreadsheet");

private String name;

private DocumentType(String name) {
this.
name= name;
}

public String getName() {
return
name;
}
}

Apache common lang Enum

In the example above we still need to implement the equals() and hashCode() methods to make it possible to check which documentType the user passed to the service. The easy way is to subclass from the Apache common lang Enum class, this superclass implements the boring stuff (equals, hashCode, compareTo, getName):

import org.apache.commons.lang.enums.Enum;
public class DocumentType
extends Enum {
public static final DocumentType TEXT = new DocumentType("text");
public static final DocumentType SPREADSHEET = new DocumentType("spreadsheet");

private DocumentType(String name) {
super(name);
}
}

This solution works well if you're stuck with Java 1.4. However, if you work on a project that runs on Java 5 or later, you should consider the build-in enum types.

Migrate to Java 5 enum

The Java language designers have added the enum type in Java 5 to make it easier to define a type-safe constant. The DocumentType enumeration becomes very simple:

public enum DocumentType {
TEXT,
SPREADSHEET;
}
The code of our service runs unchanged, since the equals method of an enum behaves the same way. In the case you need to interface with legacy code that gets a string from a database or property file to create the corresponding constant, you can add a String as private member of the enum:

public enum DocumentType {
    TEXT("text"),
SPREADSHEET("spreadsheet");

private final String name;

DocumentType(String name) {
this.name = name;
}

public String getName() {
return name;
}
}

Conclusion

Using strong types instead of Strings or integers has these advantages:
  • the interface of your objects is much clearer and less ambiguous,
  • you get code completion in your IDE (no need to "hunt for constants"),
  • easier refactoring by your IDE,
  • type safety - your client cannot supply invalid String or integer constants.

Monday, November 19, 2007

Spring bean configuration validation

If you enthousiastically use Spring like me and dutifully inject every dependency in your beans with Spring's XML configuration, you have probably encountered the situation that you forgot to inject a property and received a NullPointerException from an unexpected place in your code. Wouldn't it be nice to check the configuration of your bean after it is instantiated? Your bean could implement the InitializingBean interface, which would cause the Spring application context to call the afterPropertiesSet method after your bean is instantiated and injected with dependencies. This would make your bean directly dependent on Spring and you probably would not want that.

Attribute "init-method"

A better solution is to call a method of your bean that validates its own configuration with the "init-method" attribute of the bean element in the application context XML:
<bean id="bean1" class="net.kazed.spring.config.validator.ExampleBean1" init-method="validateConfiguration">
 <property name="bean2" ref="bean2"/>
 <property name="bean3" ref="bean3"/>
</bean>
public void validateConfiguration() {
 DependencyAssert.notNull(bean2, "bean2");
 DependencyAssert.notNull(bean3, "bean3");
}
The Spring container will call the "validateConfiguration" method after your bean, in which you can check if all required dependencies are injected. The only thing is that you should not forget to add the "init-method" attribute.

BeanPostProcessor

Since our goal was to catch configuration mistakes, this solution just is not good enough. Fortunately, you can create a post-processor for the Spring container that will examine every created bean after instantiation and dependency injection. By implementing a BeanPostProcessor, you can invoke the validateConfiguration method. To make it nice and intuitive, we can create an interface ValidatableConfiguration with the validateConfiguration method. Interface:
public interface ValidatableConfiguration {
/**
 * Validate the configuration of the object.
 */
void validateConfiguration();
}
ValidatingBeanProcessor:
public class ValidatingBeanProcessor implements BeanPostProcessor {
  public Object postProcessBeforeInitialization(Object bean, String beanName)
   throws BeansException {
   return bean;
  }

  public Object postProcessAfterInitialization(Object bean, String beanName)
   throws BeansException {
   if (bean instanceof ValidatableConfiguration) {
     try {
       ((ValidatableConfiguration) bean).validateConfiguration();
     } catch (DependencyNullException e) {
       throw new ConfigurationValidationException("Configuration of bean '" + beanName
         + "' failed - " + e.getMessage(), e);
     }
   }
   return bean;
  }
}
We just declare the ValidatingBeanProcessor once in the application context, and the container will use it for every created bean:
<bean id="beanValidator" class="net.kazed.spring.config.validator.ValidatingBeanProcessor">
The nice thing is that we only have to make the bean implement the ValidatableConfiguration interface and it will automatically be used to validate the bean whenever you declare it in the application context. Advantages:
  • Intuitive design - implement interface and it will be validated
  • No special configuration (except from the one ValidatingBeanProcessor)
  • Validation is done only once and during instantiation of the application context - it will fail early
  • Error message is descriptive - no more puzzling NullPointerException

Constructor injection

Traditionally, the Spring team favored setter injection because of more readable configuration. Spring has always also supported constructor injection and recently this has received more attention in the Spring community (see Alef's blog). Constructor injection makes validation incredibly simple: just validate in the constructor.
public ExampleBean1(ExampleBean2 bean2, ExampleBean3 bean3) {
 super();
 DependencyAssert.notNull(bean2, "bean2");
 DependencyAssert.notNull(bean3, "bean3");
 this.bean2 = bean2;
 this.bean3 = bean3;
}
<bean id="bean1c" class="net.kazed.spring.config.validator.ExampleBean1">
 <constructor-arg ref="bean2"/>
 <constructor-arg ref="bean3"/>
</bean>
As you can see, constructor injection is a bit harder to read because the arguments are nameless and depend on the order.

Conclusion

I would prefer to use constructor injection and use (or combine with) setter injection if some dependencies are optional. The BeanPostProcessor is very useful because it is non-obtrusive and automatically validates the configuration of a bean when it implements an interface that you define yourself and can be a logical part of your domain model. Retrieve here the source code of these examples.

Friday, October 26, 2007

Create your own JSF variable resolver

The system I am working on, uses a singleton service factory (that uses Spring to configure the services) to lookup service instances. The JSF backing beans use these services to perform business operations and need to lookup the services with the central service locator. This is quite straightforward and unfortunately less straightforward when you want to unit test it: it would be a lot easier to inject the services into the backing beans like we are used to in Spring. Spring has a variable resolver that makes it possible to inject Spring managed beans defined in WEB-INF/applicationContext.xml into JSF managed beans. For various reasons the system I am working on cannot put the services in application context of the web application (service instances must be shared between multiple web applications on the server). To make the same sort of injection possible, I created a JSF variable resolver that will lookup the desired service in the global service locator.
public class ServiceLocatorVariableResolver extends VariableResolver {

private VariableResolver originalVariableResolver;
private ServiceLocator serviceLocator;

/**
* Constructor.
* @param originalVariableResolver Original JSF variable resolver.
*/
public ServiceLocatorVariableResolver(VariableResolver originalVariableResolver) {
   this.originalVariableResolver = originalVariableResolver;
}

/**
* {@inheritDoc}
*/
public Object resolveVariable(FacesContext context, String name) throws EvaluationException {
   Object result = null;
   result = originalVariableResolver.resolveVariable(context, name);
   if (result == null) {
     if (serviceLocator == null) {
         serviceLocator = ServiceLocatorFactory.getInstance().getLocator();
     }
     try {
         result = serviceLocator.getBean(name);
     } catch (NoSuchBeanDefinitionException e) {
         // ignore exception - bean not found
     }
   }
   return result;
}
}
As you can see, creating a variable resolver is quite straightforward and make dependency injection possible, even if you use an old fashioned service locator. Unit testing becomes a lot easier this way.