Spring: injecting an enum conditionally

The other day I was working on a piece of legacy code, with old-fashioned xml based Spring injection. All of a sudden I found myself in a situation where I had to inject an enum, based on some condition specified in a .properties file. This is easy to do with Java config, but not so usual to me with XMLs, so I thought I’d put it here.

Let’s take a very basic example. We are creating a credit card validator. There are a number of things that need to be checked, like only digits are accepted, card number length, whether the number is valid or not, expiry time, cvc code etc. This basic service has to support two types of validation: fail fast and fail safe (fail fast will stop validating upon the first error, while fail safe aggregates all the problems) through a configurable parameter validation.type. If this property is set to 1, we do fail fast validation, in other cases fail safe.

The parameter is contained in a file called validation.properties, and looks like this:

validation.type = 0

Now let’s define an enum that will specify the validation type, I called it ValidationType:

package tamasgyorfi.injection.cond;

public enum ValidationType {
	FAIL_FAST, FAIL_SAFE
}

And now, a (dummy) service object that will carry out the validation itself, based on the validation type:

package tamasgyorfi.injection.cond;

public class CreditCardValidator {

	private final ValidationType validationType;

	public CreditCardValidator(ValidationType validationType) {
		this.validationType = validationType;
	}
	
	public void validate(final String cardNumber) {
		System.out.println("Validation strategy: " + validationType);
	}
}

And now, the most important things. We inject the enum, based on the number in the property file -all through xml config.

	<!-- this will read the property file -->
	<bean
		class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
		<property name="locations" value="classpath:validation.properties" />
	</bean>


	<bean id="validtor" class="tamasgyorfi.injection.cond.CreditCardValidator">
		<!-- for the enum, we specify the class and the value -->
		<constructor-arg type="tamasgyorfi.injection.cond.ValidationType"
			value="#{${validation.type} == 1 ? 'FAIL_FAST' : 'FAIL_SAFE' }" />
			<!-- note the #{${validation.type} == 1 ? 'FAIL_FAST' : 'FAIL_SAFE' } part -->
	</bean>

And here is a trivial main method, so we can see “Validation strategy: FAIL_SAFE”:

	public static void main(String[] args) {
		ApplicationContext appContext = new ClassPathXmlApplicationContext("beans.xml");	
		appContext.getBean(CreditCardValidator.class).validate("222-958-5478");
	}

It was not very complicated after all, but there are several things to note:

  • we specified the enum by its class and value, as a constructor argument.
  • the value for the enum was the exact string constant corresponding to name(). Should we had mistyped it, we would have got an exception saying: “no matching editors or conversion strategy found”. Upper/lower case letters matter, as usual.
  • the Spring expression language (SpEL) let us use conditional expressions in the form of #{expression}. It allows for more complex structures too, check out the link.
  • SpEL had no problem mixing expressions (#{}) with property placeholders (${})
Advertisements

Author: tamasgyorfi

Senior software engineer, certified enterprise architect and certified Scrum master. Feel free to connect on Twitter: @tamasgyorfi

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s