Spring 3.1 Unified property management: before and after

My pet project

Sometimes in between, I work on a little pet project of mine.

If you download the Oracle XE Database, you get an HR example schema with it. You can check out the HR schema’s layout and contents on this link.
My idea was to create an enterprise application on this schema to practice using new frameworks or new features.
At this moment I’m developing a Spring Web MVC application backed by Spring and JPA.

The problem description

When I’m at work, during lunch-time, I’d like my application and tests to be run on the real Oracle database.
But when I continue to work on it at home, I’d just like to run the tests on an in-memory HSQLDB database.

So I’ll need two different configurations.
I don’t want to have to copy or switch configurations all the time and I want to re-use as much of the general configuration as possible without resorting to copy-paste behavior.
How can we accomplish such a thing?

Before: Maven profiles FTW

I can use different Maven profiles for both databases. One oracle profile, and one hsqldb profile.
When I want to switch, I just pass the profile to be used with the Maven build. The Oracle profile will be set as default.
When a profile is activated, I will use filtering during the Maven build to filter database configuration properties from one properties file (oracle.properties or hsqldb.properties) to the database.properties and hibernate.properties files. The database.properties file will then be used as a property-placeholder to setup the dataSource Spring bean.

Here’s an example. You can download the source code from my public Dropbox folder: hr-maven-profiles.zip.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	...
	<profiles>
		<profile>
			<id>oracle</id>
			<activation>
				<activeByDefault>true</activeByDefault>
			</activation>
			<build>
				<resources>
					<resource>
						<directory>src/main/resources</directory>
						<includes>
							<include>**</include>
							<include>**/**</include>
						</includes>
						<filtering>true</filtering>
					</resource>
				</resources>
				<filters>
					<filter>${basedir}/src/main/resources/META-INF/config/oracle/oracle.properties</filter>
				</filters>
			</build>
		</profile>
		<profile>
			<id>hsqldb</id>
			<build>
				<resources>
					<resource>
						<directory>src/main/resources</directory>
						<includes>
							<include>**</include>
							<include>**/**</include>
						</includes>
						<filtering>true</filtering>
					</resource>
				</resources>
				<filters>
					<filter>${basedir}/src/main/resources/META-INF/config/hsqldb/hsqldb.properties</filter>
				</filters>
			</build>
		</profile>
	</profiles>
</project>

With each profile, I activate filtering on all resource files. I also specify what properties file to use to get the property values from. These property values will be filtered into the specified resource files (here, all of the resource files).
You can find more information about the filter and filtering element on the following links:
filter: http://maven.apache.org/pom.html#BaseBuild_Element
filtering: http://maven.apache.org/pom.html#Resources

More specifically, with the hsqldb profile I specify that filtering should be performed on all resource files in the src/main/resources folder and all of it’s sub folders. These will be used as resources on the classpath.
The file used to fetch the values from is the ${basedir}/src/main/resources/.../hsqldb.properties file. When Maven executes the build and performs the tests, these values will be filtered in the files where the property-placeholder key’s are used.

These are the property values for the hsqldb profile:

username=sa
password=
url=jdbc:hsqldb:mem:hr
driverClassName=org.hsqldb.jdbcDriver

dialect=org.hibernate.dialect.HSQLDialect
hbm2ddl.auto=create-drop
hbm2ddl.import_files=/import.sql

They will be filtered in files that use the property-placeholders, respectively database.properties and hibernate.properties:

database.username=${username}
database.password=${password}
database.url=${url}
database.driverClassName=${driverClassName}
hibernate.dialect=${dialect}
hibernate.hbm2ddl.auto=${hbm2ddl.auto}
hibernate.hbm2ddl.import_files=${hbm2ddl.import_files}

After that, the database.properties file is specified as a property-placeholder in the Spring applicationContext.xml configuration file.
The hibernate.properties file will be used automatically by Hibernate when the persistence context is initialized.

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

	<context:property-placeholder location="classpath*:META-INF/config/database.properties" />
	...
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="username" value="${database.username}" />
		<property name="password" value="${database.password}" />
		<property name="url" value="${database.url}" />
		<property name="driverClassName" value="${database.driverClassName}" />
	</bean>
	...
</beans>

As you can see, the keys of the property value to filter and it’s respective Spring property-placeholder cannot be the same, otherwise Maven won’t be able to know where to filter the value’s into.
If you use the same property name for Maven filtering as for the Spring property-placeholder, you’ll get the following Exception message:
Invalid bean definition with name 'dataSource' defined in class path resource [META-INF/config/applicationContext.xml]: Circular placeholder reference 'database.username' in property definitions

To summarize:

  • Specify different profiles for the different configurations
  • Enable filtering within these profiles, by specifying either a properties file to fetch the values from or by specifying the property key-value pairs in the Maven profiles itself.
    If separate properties files are being used, specify all key-value pairs in those properties files
  • When building the application or running tests through Maven, pass the desired profile by using the -P option
  • Maven will filter the key-value pairs into the specified resources and replace the property-placeholders with the specified values
  • The filtered files will be used by Hibernate and Spring (the latter through a property-placeholder element) to configure the dataSource bean and the persistence context

After: Spring Unified Property Management

When I continued reading the Spring reference documentation, more specifically the part about the new features and enhancements in Spring 3.1 and the PropertySource abstraction, I realized that the previous solution was too complex and I could rely only on Spring to solve the problem.

You can download the example on the following link: hr-spring-propertysource.zip.
I also refer to the following SpringSource blog post: Spring 3.1 M1: Unified Property Management.

With the PropertySource abstraction, the Spring Environment object performs a search over a set of PropertySource objects. A PropertySource object is an abstraction over any source of key-value pairs.
Per default, the Spring Environment searches in the JVM system properties and the system’s environment variables. This way, you can pass environment variables to the application using the -D option.

I don’t specify any profiles anymore in the Maven pom.xml. This makes the Maven configuration much more simple and concise. I’ll pass environment variables when running the tests to specify which database to use.

The only thing I have to do is put the environment variable key (in this case, “database”) as a placeholder in the property-placeholder element.
When Spring initializes the container, it will use the PropertySource abstraction to search for the “database” key and replace it’s value into the placeholder.
This way, I can specify the sub folder to fetch the database.properties file from, which will be used for the property-placeholders in the applicationContext.xml.

As an example, I’ll show you the HSQLDB database.properties file, and a part of the applicationContext.xml.
I removed the hibernate.properties file because when using the PropertySource abstraction, the hibernate.properties file cannot be filtered anymore.
This can only be used in the applicationContext.xml files or within annotations in your Java classes.
Therefore, instead of relying on hibernate.properties or persistence.xml, I specify the Hibernate properties directly in the entityManagerFactory Spring bean.

database.username=sa
database.password=
database.url=jdbc:hsqldb:mem:hr
database.driverClassName=org.hsqldb.jdbcDriver

hibernate.dialect=org.hibernate.dialect.HSQLDialect
hibernate.hbm2ddl.auto=create-drop
hibernate.hbm2ddl.import_files=/import.sql
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
		http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">

	<!-- 
	I make use of the Environment abstraction and property sources in Spring to define which database to use.
	The environment variable 'database' has to be set one way or another to be able to run the application or tests.
	-->
	<context:property-placeholder location="classpath*:META-INF/config/${database}/database.properties" />
	...
	<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
		destroy-method="close">
		<property name="username" value="${database.username}" />
		<property name="password" value="${database.password}" />
		<property name="url" value="${database.url}" />
		<property name="driverClassName" value="${database.driverClassName}" />
	</bean>

	<bean id="entityManagerFactory"
		class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
		<property name="dataSource" ref="dataSource" />
		<property name="persistenceUnitName" value="persistenceUnit" />
		<property name="jpaProperties">
			<props>
				<prop key="hibernate.dialect">${hibernate.dialect}</prop>
				<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
				<prop key="hibernate.hbm2ddl.import_files">${hibernate.hbm2ddl.import_files}</prop>
			</props>
		</property>
	</bean>
	...
</beans>

When running the tests, you should pass the desired database using the -D option on command line or environment variables in Eclipse.
An example of this can be: ... -Ddatabase=oracle or ... -Ddatabase=hsqldb.
Respectively, Spring will search the database.properties file in the oracle sub folder or the hsqldb sub folder, and use the specified values to replace the property placeholders.

This concludes my post about Spring’s Unified Property Management for using different configurations.

What about Spring Bean Definition Profiles?

The new Spring @Profile annotation is also a possible candidate to get this kind of behavior.
But when using the @Profile annotation, I don’t think I would be able to let the integration tests run on the Oracle database first, and then switch it to the HSQLDB database without having to change some code.

Using the @Profile annotation, you can set the @ActiveProfiles annotation on your test classes to activate one or more profiles. To switch, you’ll have to change the annotation value to another profile value.
I can only switch the active profile depending on the environment, like DEV or PRD, by activating the hsqldb profile in the test classes, and specifying the oracle profile as an spring.profiles.active init-param in web.xml. This doesn’t solve my initial problem of being able to easily switch databases for my test cases.

Do you think one can use the Spring @Profile annotation without having to change the annotation’s value to switch profiles?
If so, please feel free to comment to this post and share your ideas.

I hope you enjoyed this blog post, and eagerly await your comments and suggestions.

Advertisements
Posted in Java, Spring | Tagged , , , , , , , , | 5 Comments

Dependency Injection vs. Service Locator

Again, while reading through the Spring documentation, I came across this article of Martin Fowler.
I’ll try to give a summary of his article and my opinions about it.

Introduction

Every professional software engineer should know what dependency injection or inversion of control is about, but i’ll try to explain it for those who don’t.
I’ll use quite the same examples as Martin did in his article, which I’ll try to update a little. You can find a link to the source code at the bottom of this blog post (Maven is required to build the source).

Imagine you have to display a list of movies directed by a specified director.
I have an interface and a concrete implementation for finding movies.

public interface MovieFinder {
    public List<Movie> findAllMovies();
}
public class MovieFinderDummy implements MovieFinder {
    public List<Movie> findAllMovies() {
        List<Movie> movies = new ArrayList<Movie>();

        movies.add(new Movie("Gangs of New York", "Martin Scorsese"));
        movies.add(new Movie("E.T.: The Extra-Terrestrial", "Steven Spielberg"));
        movies.add(new Movie("The Aviator", "Martin Scorsese"));
        movies.add(new Movie("Indiana Jones and the Temple of Doom", "Steven Spielberg"));
        movies.add(new Movie("Jurassic Park", "Steven Spielberg"));

        return movies;
    }
}

To list the movies with a specified director, the following code is used:

public class MovieLister {
    private MovieFinder movieFinder;

    public Movie[] listMoviesDirectedBy(String director) {
        List<Movie> allMovies = movieFinder.findAllMovies();
        for (Iterator<Movie> iterator = allMovies.iterator(); iterator.hasNext();) {
            Movie movie = iterator.next();
            if (!movie.getDirector().equals(director)) {
                iterator.remove();
            }
        }

        return allMovies.toArray(new Movie[allMovies.size()]);
    }
}

Especially the MovieFinder at line 02 is of importance here.
You need to have a way to provide the concrete class that will be used for this MovieFinder instance.

Basic solution

What you can do is specify the MovieFinder‘s concrete class in the MovieLister‘s default constructor, like this:

public class MovieLister {
    private MovieFinder movieFinder;

    public MovieLister() {
        movieFinder = new MovieFinderDummy();
    }

    ...

You’ll see. The code works. But we’ll soon be in trouble when sharing this service with other developers who are going to use it for their own projects.
If another developer also wants to use the MovieLister, but wants to get his movies from a text file, a database or XML, he’ll have to change the code of the default constructor.
Of course in our case, he can’t change the constructor. We created the service and packaged it in a JAR without releasing the source code. So he cannot change what kind of MovieFinder is used in the MovieLister. Our code isn’t configurable and reusable.
The MovieLister class is dependent on both the interface and the implementation of MovieFinder.
Actually, you must try to make it only dependent on the interface.

Dependency injection

That is where dependency injection comes into play.
The idea about dependency injection is that the class itself that is going to use the (MovieFinder) dependency is not responsible for instantiating a concrete implementation of the interface, but the dependent concrete implementation is given to the class by some other object. Martin calls that object an assembler.
This way, the MovieLister class isn’t dependent on the MovieFinderDummy implementation anymore, but only on its MovieFinder interface (it doesn’t have to do an import of the concrete implementation class).

There are several types of dependency injection:

  • Constructor injection
  • Setter injection
  • Interface injection
  • Field injection: This one’s new, using annotations on fields, parameters but also on constructors or setters

You can read all details about each type of injection in Martin Fowler’s article.
I’ll only give an example of setter injection using the Spring framework.

Setter injection with Spring

Taken from the SpringSource website:

The Spring Framework provides a comprehensive programming and configuration model for modern Java-based enterprise applications – on any kind of deployment platform. A key element of Spring is infrastructural support at the application level: Spring focuses on the “plumbing” of enterprise applications so that teams can focus on application-level business logic, without unnecessary ties to specific deployment environments.

Spring includes:

  • Flexible dependency injection with XML and annotation-based configuration styles
  • Advanced support for aspect-oriented programming with proxy-based and AspectJ-based variants
  • Support for declarative transactions, declarative caching, declarative validation, and declarative formatting
  • Powerful abstractions for working with common Java EE specifications such as JDBC, JPA, JTA and JMS
  • First-class support for common open source frameworks such as Hibernate and Quartz
  • A flexible web framework for building RESTful MVC applications and service endpoints
  • Rich testing facilities for unit tests as well as for integration tests

You can use Spring to wire up all your dependencies using configuration written in Java code, XML or annotations.
Nowadays, Spring supports setter, constructor and field injection. Using XML most people tend to use setter injection. When using annotations, field injection will be preferred.

I’ll show the example using both XML and annotation-based configuration.
Using annotations, you’ll have to change your code to have a different kind of MovieFinder implementation injected into the MovieLister class. You can use qualifiers, but if the third party component developer provided a MovieFinderFileDummy annotated as a @Service with qualifier “main”, you’ll still have to change the @Autowired @Qualifier annotation to use your own qualifier name inside the provided MovieLister class.
Using XML, your configuration is completely separate from your Java code, so you can completely change the configuration at will without altering the source code.
(Correct me if I’m wrong at this point)
You can also use a mix of annotations and XML configuration. For example, define your MovieLister class in XML where you define the name or the qualifier of the MovieFinder bean to use, and use the @Service and @Qualifier annotation in the MovieFinder to specify your concrete implementation.

Spring XML configuration

Using the same example as above, I’ll now use Spring XML configuration.
I’ve changed the name of MovieFinderDummy to MovieFinderXmlDummy to clearly separate both examples.
The MovieLister doesn’t use a constructor anymore for instantiating the MovieFinder implementation, but uses a setter for injection.

public class MovieLister {
    private MovieFinder movieFinder;

    public void setMovieFinder(MovieFinder movieFinder) {
        this.movieFinder = movieFinder;
    }

    ...
}

My Spring XML configuration looks like the following listing:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">

	<bean id="movieFinder" class="be.stesch.movie.spring.xml.MovieFinderXmlDummy" />

	<bean id="movieLister" class="be.stesch.movie.spring.xml.MovieLister">
		<property name="movieFinder" ref="movieFinder" />
	</bean>
</beans>

Here I declare a movieFinder bean of type MovieFinderXmlDummy.
I then declare the movieLister bean of type MovieLister to use the movieFinder bean as it’s dependent property. This way Spring will inject a MovieFinderXmlDummy instance in the MovieLister.

The Client then uses the ClassPathXmlApplicationContext to load the Spring application context to be able to get the MovieLister and list all movies with the specified director.

public class Client {
    private static final String MOVIELISTER_BEAN_NAME = "movieLister";

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "META-INF/config/xmlApplicationContext.xml");

        MovieLister movieLister = applicationContext.getBean(MOVIELISTER_BEAN_NAME, MovieLister.class);
        Movie[] movies = movieLister.listMoviesDirectedBy("Steven Spielberg");
        ...
    }
}
Spring annotation configuration

When using annotations, my Spring application context XML configuration file get’s reduced to the following listing:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
						http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

	<context:annotation-config />
	<context:component-scan base-package="be.stesch.movie.spring.annotations" />
</beans>

As you can see, I don’t define any beans anymore in this XML. I just define that annotations will be used to configure the Spring container, and where to scan for candidate beans.
Again, here I renamed the MovieFinderDummy to MovieFinderAnnotationDummy for clarity and separation in execution.

@Service("movieFinder")
public class MovieFinderAnnotationDummy implements MovieFinder {
    ...

The MovieLister will now be declared as a Service component where the MovieFinder dependency will be Autowired.

@Service("movieLister")
public class MovieLister {
    @Autowired
    @Qualifier("movieFinder")
    private MovieFinder movieFinder;

    ...

You don’t really need to give a name with the @Service annotation, or use the (Spring based) @Qualifier annotation in the MovieLister class, but it’s just to use the same bean names as in the XML example. Without an @Service name and without an @Qualifier Spring will use the class types to perform dependency injection.
The Client works the same, except for using a different Spring configuration file based on annotations.

public class Client {
    private static final String MOVIELISTER_BEAN_NAME = "movieLister";

    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext(
                "META-INF/config/annotationApplicationContext.xml");

        MovieLister movieLister = applicationContext.getBean(MOVIELISTER_BEAN_NAME, MovieLister.class);
        Movie[] movies = movieLister.listMoviesDirectedBy("Steven Spielberg");
        ...
    }
}

As said, you can mix and match. Make the MovieLister an annotation configured @Service, declare the MovieFinder‘s concrete implementation in the configuration XML itself and don’t use annotations in the MovieFinder implementation class.

If you want to minimize your dependency (import statements) on Spring, you could also use the JSR 330 Standard annotations like @Named instead of @Service, and @Inject instead of @Autowired, like shown in my downloadable source code.
This way, the only import of the Spring framework resides in the Client class, because there your Spring application context has to be set up.
If you create a web application and reference the applicationContext.xml file in your /WEB/INF-web.xml, then you don’t even have a single Spring import in your source code, while still working with Spring.

Service Locator

Now that you have a complete view on dependency injection and Spring, let’s move on to the Service Locator pattern.
The Service Locator has the same goal as dependency injection: to remove the dependency to the implementation from the calling class.
As Martin Fowler’s article states:

The basic idea behind a service locator is to have an object that knows how to get hold of all of the services that an application might need. So a service locator for this application would have a method that returns a movie finder when one is needed.

I like the idea of having a dynamic Service Locator, with a Map containing all services by key. But I can also agree with Martin’s argument that it’s not explicit. The only way of knowing what services are available is by looking at the keys stored in some file or class. So as an example, I made a mix of both.

This is my Service Locator’s code:

public class ServiceLocator {
    public static final String MOVIEFINDER_SERVICE = "movieFinder";

    public static final String MOVIELISTER_SERVICE = "movieLister";

    private static final ServiceLocator instance = new ServiceLocator();

    private final Map<String, Object> services = new HashMap<String, Object>();

    private ServiceLocator() {
    }

    void loadService(String key, Object service) {
        services.put(key, service);
    }

    public static ServiceLocator getInstance() {
        return instance;
    }

    public Object getService(String key) {
        return services.get(key);
    }

    public MovieFinder getMovieFinder() {
        return (MovieFinder) getService(MOVIEFINDER_SERVICE);
    }

    public MovieLister getMovieLister() {
        return (MovieLister) getService(MOVIELISTER_SERVICE);
    }
}

You can see that my Service Locator is a Singleton that has a Map containing two services. The MovieFinder service and the MovieLister service.
To make the ServiceLocator class testable, and to be able to provide the ServiceLocator with different service implementations, I also use a separate Assembler class loading (or putting) serivces in the ServiceLocator‘s services Map.

public class Assembler {
    private static final Assembler instance = new Assembler();

    private Assembler() {
    }

    public static Assembler getInstance() {
        return instance;
    }

    public void configure() {
        ServiceLocator.getInstance().loadService(ServiceLocator.MOVIEFINDER_SERVICE, new MovieFinderServiceLocatorDummy());
        ServiceLocator.getInstance().loadService(ServiceLocator.MOVIELISTER_SERVICE, new MovieLister());
    }
}

I think you can see this Assembler somewhat in the same way like setting up the Spring application context. It instantiates the services, and makes them available to the calling environment (in this case, through a Service Locator).

If the services don’t contain any state that should be retained while working in a class (and they shouldn’t!), then you can call the Service Locator every time you need a service, instead of storing it somewhere in it’s calling class.
The main class (Client) should still call the Assembler (like creating a new ApplicationContext) to configure the application and load services in the Service Locator.

public class Client {
    public static void main(String[] args) {
        Assembler.getInstance().configure();

        MovieLister movieLister = ServiceLocator.getInstance().getMovieLister();
        Movie[] movies = movieLister.listMoviesDirectedBy("Steven Spielberg");
        ...
    }
}

The final clash

Dependency Injection vs. Service Locator

Why all the fuzz of manually creating a Service Locator solution while you have dependency frameworks available like Spring?
Well, you’ll have to decide based on your requirements, your project and your knowledge.

The Service Locator and dependency injection both have their pro’s and their con’s or implications. Both cases make the application code independent of the concrete implementation of the service interface.

  • With dependency injection, no explicit request is required. The service “appears” in or is given to the application class.
  • Dependency injection tends to be hard to understand and hard to debug.
  • With Service Locator every “user” of a service has a dependency on the Service Locator. If this is a problem, use dependency injection.
  • Using dependency injection, dependencies can be more clear.
    With Service Locator you’ll have to search for every use. With dependency injection you can just read the constructor or the setters. Your usage depends on the nature of the application.
  • Dependency injection might make testing easier, but a Service Locator can also be testable if it is correctly designed.
  • If your code is going to be used in applications that are outside the control of the developer, Service Locator is out of the question. Use dependency injection.

My opinion here is that a dependency injection framework like Spring has evolved so much, that issues you might be having with dependency injection are irrelevant, except perhaps being harder to understand and harder to debug. Spring has it’s own testing framework, which is really an easy framework. It offers configurable dependency injection in code using Java, annotations or in XML configuration files. And it offers an entire platform of support classes and API’s to use enterprise grade components in an application that’s not running on an enterprise application server.
Why re-invent the wheel (design a Service Locator framework) if you can use Spring easily?

Constructor vs. setter injection

I’ve always used setter injection. I supose I was taught it that way or was used to it like that. But after reading Martin’s arguments, it makes sense.
He suggests using constructor injection because you need to have valid objects at construction time. So perform the injection using the constructor. Apparently, this advice originates from Kent Beck’s Smalltalk Best Practice Patterns: Constructor Method and Constructor Parameter Method.

Using constructor injection allows you to hide immutable fields from users of your class. If you don’t want the MovieFinder to be changed or set in the MovieLister class while using the application, then don’t create a setter for it. You then have to use constructor injection to use the dependency. This way you can encapsulate the dependencies in your class.
A disadvantage of constructor injection is that constructors might get a lot of parameters quite fast, or that you have to create a lot of overloaded constructors for every way the object might be created. If this is the case, Martin suggests resorting to setter injection. So, first use constructor injection, until things become too complex. Then change that class to setter injection.
I follow him in this aspect.

Code vs. configuration files, and separating code from usage

There, I follow his advice as well, more or less.
Up untill these days I only used dependency injection (Spring) using XML configuration files (in commercial projects). I like this way of configuring an application because it’s completely separate from your code. Some third party user might want to change the way you application works by changing the XML configuration. If a client wants to use Hibernate or JPA instead of the JDBC code that you have written, he just has to create a Hibernate / JPA implementation and change the dependencies in your persistence layer to his Hibernate / JPA DAO’s.
For smaller projects, or projects that stay under your own control, programmatic configuration can be preferred. XML configuration tends to get cluttered and hard to read and maintain.

Nowadays, this is where annotations come in. You can use programmatic configuration in the Java file where it belongs, without having to create a whole bunch of separate XML configuration files.
If your project is going out of your hands at the end, it can be better to make use of XML configuration.

To conclude

  • These days, Service Locator isn’t of much use anymore, except in very small proprietary projects. For the rest, use a good dependency injection framework.
  • Prefer constructor injection over setter injection to have valid objects at creation time, unless the constructor becomes too complex.
  • If your project is going out of your hands or tends to change a lot, use XML configuration. Otherwise, use code or annotations to configure your application.

I hope you have enjoyed this blog post.
As always, please post your comments and advice.
You can find the source code on my Public DropBox: movie-demo.zip

Posted in Java, Object Oriented Design, Spring | Tagged , , , , , , | 8 Comments

The Open-Closed Principle: The heart of object oriented design

I have a question for you guys and girls.

This morning, I was reading through the Spring documentation about the Web MVC framework.
In a side-note, “Open for extension…”, SpringSource referred to a paper about the design principle “Open for extension, closed for modification”.

A key design principle in Spring Web MVC and in Spring in general is the “Open for extension, closed for modification” principle.

Some methods in the core classes of Spring Web MVC are marked final. As a developer you cannot override these methods to supply your own behavior. This has not been done arbitrarily, but specifically with this principle in mind.

I found this comment somewhat contradictory to the Open-Closed Principle.

I read the paper of (Uncle) Bob Martin, which can be found at the link The Open-Closed Principle, and wanted to share my thoughts with you.

The paper gives a very good and understandable explanation about this OOD (Object Oriented Design) principle.
It’s all about abstraction, encapsulation and design for change, which are principles that lie at the heart of OOD.
You have to write your code in such a way that, if you need to change the behavior of your application, you just extend instead of modify your existing code base. In the most ideal circumstance, you should not touch any lines of code that you have written in the past.

A procedural design

Bob Martin uses shapes as an example. You could write code like the following listing to create a Client-Server application that draws shapes.

public class Shape {
    ShapeType type;
}
public class Circle extends Shape {
    public Circle() {
        this.type = ShapeType.CIRCLE;
    }

    double radius;

    Point center;
}
public class Server {
    void drawSquare(Square square) {
        System.out.println("I'm drawing a square");
    }

    void drawCircle(Circle circle) {
        System.out.println("I'm drawing a circle");
    }

    void drawAllShapes(List<Shape> shapes) {
        for (Shape shape : shapes) {
            switch (shape.type) {
            case SQUARE:
                drawSquare((Square) shape);
                break;
            case CIRCLE:
                drawCircle((Circle) shape);
                break;
            }
        }
    }
}

You can see immediately that if you need a new kind of shape, you need to create a new class for this shape (which is good), but you also need to modify the entire Server class. You have to add another draw method, and you need to change the switch in the drawAllShapes method.
So, a lot of changes in your existing code are necessary just to use a new kind of shape.

An Object Oriented Design

To be able to add new shapes without having to change your existing code base, you can do the following:

public abstract class Shape {
    public abstract void draw();
}
public class Circle extends Shape {
    private double radius;

    private Point center;

    // Getters and setters

    @Override
    public void draw() {
        System.out.println("I'm drawing a circle");
    }
}
public class Server {
    public void drawAllShapes(List<Shape> shapes) {
        for (Shape shape : shapes) {
            shape.draw();
        }
    }
}

As you can see, your code becomes much more concise, readable and when you want to add a new kind of shape, you just extend the Shape class and implement the draw method in that new class. “Open for extension, …”.
Also, you don’t need a ShapeType attribute anymore, because the new shape class IS the type!

This principle goes a lot further, but you can read the rest in Bob Martin’s excellent paper.

My question about this matter

What does SpringSource mean with “Some methods in the core classes of Spring Web MVC are marked final. […] This has not been done arbitrarily, but specifically with this principle in mind.

If the Open-Closed Principle stands for “Open for extension, …” what do final methods have to do with this principle?
Final methods cannot be overridden in subclasses. Thus that behavior cannot be extended. It is closed for modification but I thought that had to do with not touching the existing code base, while being able to change it’s behavior by extending classes and overriding methods.

Can you guys and girls elaborate on this with me?
Feel free to post your comments to this blog post.

As usual, you can find the source code at the following link: shapes-demo.
You won’t need Maven to build this demo. Just extract it in your Eclipse workspace, and import the existing project. You might need to change the classpath to add your own JRE System Library.

Posted in Java, Object Oriented Design | Tagged , , , , | 3 Comments

Hibernate enum UserType Test

At my current project, I’ve encountered something that seemed quite strange, but in the end was so logical.
To make sure that I remember what I’ve learned and to share my knowledge with others, I’ve written this blog post.
For this post, I’ve borrowed and adapted some code from my client’s project to make sure I’m working in the same environment. I give attribution to my client for these parts of the source.

In the beginning – Hibernate UserType issues

In this project, I had a failing Hibernate mapping. Running a specific function in the application triggered an IllegalArgumentException: argument type mismatch.
Looking into the stacktrace, I found out that a Hibernate UserType I had implemented was changed. Someone changed the returnedClass() return value. This value didn’t comply with the necessary type for a setter that was being called.
We fixed the problem, and I started writing an integration test to make sure that the mapping would always be validated.

Writing an Integration Test

I’ll now divert to a sample project instead of the real stuff, to be able to explain the technicalities in a better way.

I want to persist a person to the database. A Person has a gender enum. Two enums exist, the Gender enum and the FakeGender enum. I want to write an integration test to make sure that the mapping would fail if the custom Hibernate UserType is using the incorrect FakeGender enum.
The UserType is written generically to use the returnedClass() class when performing a nullSafeGet() and a nullSafeSet(). You can download the source code at the end of the post to see it all in action.

The Gender enum setup and StringEnumUserType class are a copy of the way the architects and other developers have designed the enum usage at my client’s project. It’s not one of my own inventions.

public enum Gender implements EnumWithValue<Gender> {
    MALE("M"), FEMALE("F");

    private static Map<String, Gender> allEnumValuesAndEnums;

    private String enumValue;

    private Gender(String enumValue) {
        this.enumValue = enumValue;
        EnumUtils.initializeEnumeration(getAllValuesAndEnums(), enumValue, this);
    }

    public String getEnumValue() {
        return enumValue;
    }

    public static Map<String, Gender> getAllValuesAndEnums() {
        if (allEnumValuesAndEnums == null) {
            allEnumValuesAndEnums = new HashMap<String, Gender>();
        }
        return allEnumValuesAndEnums;
    }

    public Map<String, Gender> getAllEnumValuesAndEnumerations() {
        return getAllValuesAndEnums();
    }
}
public class GenderUserType extends StringEnumUserType {
    public Class<FakeGender> returnedClass() {
        return FakeGender.class;
    }
}
public class PersonTest {
    ...

    @Test
    public void testPersonMapping() {
        Person person = new Person();
        ...
        person.setGender(Gender.MALE);

        try {
            entityManager.persist(person);
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            Assert.fail(t.getMessage());
        }
        Assert.assertNotNull(person.getId());

        Person loadedPerson = null;
        try {
            loadedPerson = entityManager.find(Person.class, person.getId());
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            Assert.fail(t.getMessage());
        }
        Assert.assertNotNull(loadedPerson);
        ...
    }

    ...
}

As you can see in the code above, I misconfigured the GenderUserType to use the FakeGender enum instead of the Gender enum. This mimics the behaviour of the real project where a developer changed the returnedClass() method in the UserType I was using for my mapping.
So while I’m setting the correct Gender MALE in the Person instance, I expect the test to fail because the GenderUserType is specifying FakeGender instead of Gender to be used to set the property.
Like it happened when exporting the dossier in the real project, setting FakeGender in setGender() would lead to an argument type mismatch. Or so I expected.

Against all expectations

Against my expectations, the integration test succeeds. It runs green.
I was baffled. It should fail because I’m specifying the mapping to use an incorrect enum type.

After further investigation, I found out the the nullSafeSet() isn’t using the returnedClass(), but the generic EnumWithValue interface to fetch the enumValue. So it’s normal that the error doesn’t occur when persisting the Person instance.
Nevertheless, I didn’t understand why loading the Person instance again, didn’t trigger nullSafeGet() that did use the returnedClass() method.

Then, after some research, the answer made sense. I found a lead on the following blog post: User Types in Hibernate
The nullSafeGet() method is only called when loading an instance directly from the database. So when the instance still exists in the PersistenceContext, it will not be loaded from the database and thus nullSafeGet() will not be called. Because of that, the returnedClass() method will also not be called, and no Exception will be thrown when loading the person instance. The entire object is just loaded from the PersistenceContext.

The solution

What can we do to make sure that a record is effectively loaded from the database in this integration test? Right…
Flush the persistence context to synchronize it to the underlying database, and clear the persistence context causing all managed entities to become detached.
This way, when loading the Person instance again, it will be fetched directly from the database instead of from the persistence context.

    ...
        try {
            entityManager.persist(person);
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            Assert.fail(t.getMessage());
        }
        Assert.assertNotNull(person.getId());

        entityManager.flush();
        entityManager.clear();

        Person loadedPerson = null;
        try {
            loadedPerson = entityManager.find(Person.class, person.getId());
        } catch (Throwable t) {
            LOGGER.error(t.getMessage(), t);
            Assert.fail(t.getMessage());
        }
   ...

And voilà … the test fails. I’m happy now. Weird, being happy when a test fails.

If we now change the GenderUserType returnedClass() method to the correct enum type, then the test will succeed again, like it should.

public class GenderUserType extends StringEnumUserType {
    public Class<Gender> returnedClass() {
        return Gender.class;
    }
}

So, what I learned today: If you really want to test your Hibernate or JPA mapping, flush and clear the session after persisting the instance and load it again to retrieve it directly from the database.
Ofcourse, using DbUnit to insert data into the database tables using a dataset, and then retrieving it to test your mappings might even be better, but the object model in this case was so complex that it wasn’t just possible to do this with DbUnit in a short amount of time.

Expanding the tests

In the end, what I did was write a test method that tests the mapping with a correctly configured UserType, and a separate test method with an incorrectly configured UserType. I set the returnedClass in the UserType by using a private static field which is set using reflection.
The first test method sets the Gender enum as returnedClass and expects the test to succeed.
The second test method sets the FakeGender enum as returnedClass and expects a PersistenceException for the test to succeed.

Feel free to download the sample project and post your comments. You’ll need Java 1.5+ and Maven to build and run the project.
Download Source Code
You’ll notice that the second test method fails, unless you uncomment the flush() and clear() method invocations, indicating the whole purpose of this blog post.

Posted in Hibernate, Java | Tagged , , , , , | 3 Comments

Spring FactoryBean-managed wiring: Part 2

I finally succeeded in getting rid of the XML configuration for the Spring container, and managed to wire everything using Spring annotations.
This post will describe what changes I had to make and what issues I experienced when converting the configuration to annotations.

XML vs. Annotations

Different opinions exist about XML configuration or annotations. I won’t go too far in those.
I like annotations because it makes your configuration readable directly in your source code, and you don’t have to go find some configured bean in one of the huge XML files.
On the other hand, configuring a Spring container using XML is much more verbose, but everything can be found in one file – or at least multiple files in one location – and there’s no magic involved. When using annotations, it might seem like dark magic when a bean can’t be injected, just because you forgot to give it a proper name or use the proper qualifier. Also, using separate versions of configuration files and Maven profiles is also only possible using XML.
So, just to tag along with the crowd and new way of thinking, I chose to get rid of the XML completely for this small HelloWorld project and only use Spring annotations to configure the application.
Of course, it depends on the circumstances whether or not you want to use XML or annotations, or even both.

Bye Bye XML

The first thing I did was delete the application-config.xml file. Of course I then had to change the main application class to instantiate the ApplicationContext using the AnnotationConfigApplicationContext.

The new main class now looks like this:

public class FactoryBeanDemo {
    ...
    public static void main(String[] args) {
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext("be.stesch");

        HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
        LOGGER.debug("Printing {}", helloWorldService.getHelloWorld());
        System.out.println(helloWorldService.getHelloWorld());
    }
    ...
}

Of course, running this application will spawn an Exception immediatly, because when scanning the base-package no Spring configured beans will be found any longer.
You will get the following Exception:

Exception in thread "main" org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'helloWorldService' is defined
	at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:527)
        ...

So I had to take some more steps to complete the configuration.

Basic Spring annotations

First, I have to declare the service beans that I’m going to use in the FactoryBean to be Spring beans.
To make a Java bean a Spring-managed service bean, you use the @Component or @Service annotation.
You also have several other annotations – called stereotypes – to do the same thing, but they have a slightly different meaning and will be used in different contexts. See the link Classpath scanning and managed components for more information.

  • @Component: a generic stereotype for any Spring-managed component.
  • @Repository: used in the persistence layer to declare a Spring-managed DAO component.
  • @Service: used in the service layer to declare a Spring-managed business service facade.
  • @Controller: used in the presentation layer to declare a Spring-managed controller, for example a web controller.

Then I configure the FactoryBean itself to be able to let it create and instantiate the correct HelloWorldService object.
You have to declare the HelloWorldServiceFactory bean to be a @Component.
Trying basically to convert the XML configuration straight to annotations, I annotated the getObject() method with the @Bean annotation.
What these annotations should do is say: I have a factory-bean HelloWorldServiceFactoryBean which I want to be a Spring-managed bean. It’s purpose it to create another Spring-managed bean of type HelloWorldService by using the factory-method getObject().
You have to pass the name attribute to the @Bean annotation to make sure the returned service instance will be called ‘helloWorldService‘.

@Component
public class HelloWorldServiceFactoryBean implements FactoryBean<HelloWorldService>, ApplicationContextAware {
    ...
    @Override
    @Bean(name = "helloWorldService")
    public HelloWorldService getObject() throws Exception {
        HelloWorldService helloWorldService = null;

        if (ServiceConstants.COMPANY_A.equalsIgnoreCase(serviceType)) {
            LOGGER.debug("Getting bean '{}'", ServiceConstants.COMPANY_A_SERVICE);
            helloWorldService = (HelloWorldService) applicationContext.getBean(ServiceConstants.COMPANY_A_SERVICE);
        } else if (ServiceConstants.COMPANY_B.equalsIgnoreCase(serviceType)) {
            LOGGER.debug("Getting bean '{}'", ServiceConstants.COMPANY_B_SERVICE);
            helloWorldService = (HelloWorldService) applicationContext.getBean(ServiceConstants.COMPANY_B_SERVICE);
        }

        return helloWorldService;
    }
    ...
}

You might think you’re finished now, but running the main application will present you the next Exception.

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorldService' defined in class path resource [be/stesch/demo/factorybean/HelloWorldServiceFactoryBean.class]: factory-bean 'helloWorldServiceFactoryBean' returned null
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:355)
        ...

It seems a little bit weird that no class of your own application is mentioned in the stacktrace, apart from the main application class. Time to debug the application.
When you put a breakpoint in the getObject() method of the HelloWorldServiceFactoryBean you’ll notice that the serviceType field, that used to come from a properties file, is null. Of course – we forgot to declare a Spring bean for the PropertyPlaceholderConfigurer.

The idea is to get rid of XML completely, and only use annotations. This way, we cannot use XML to declare a PropertyPlaceholderConfigurer spring-bean, the way I did it in part 1. The property value somehow has to get injected in the FactoryBean to be able to use it in the getObject() method.

What I did was creating an ApplicationConfig class that is responsible for creating Spring beans like the PropertyPlaceHolderConfigurer. I got my inspiration from a DZone Javalobby article: Spring and Hibernate application with zero XML.
The ApplicationConfig class has to be annotated with @Component, and the method creating the PropertyPlaceHolderConfigurer gets the @Bean annotation indicating that it will create a Spring-managed bean. Previously the @Bean and also @Configuration annotations were part of the JavaConfig project. As of version 3.0, JavaConfig got migrated into the core Spring framework.

This is the ApplicationConfig class and the getPropertyPlaceholderConfigurer() method:

@Component
public class ApplicationConfig {
    @Bean
    public PropertyPlaceholderConfigurer getPropertyPlaceholderConfigurer() {
        PropertyPlaceholderConfigurer propertyPlaceholderConfigurer = new PropertyPlaceholderConfigurer();
        propertyPlaceholderConfigurer.setLocation(new ClassPathResource("application-config.properties"));

        return propertyPlaceholderConfigurer;
    }
}

Then I inject the ‘service_type‘ property value into the HelloWorldServiceFactoryBean‘s serviceType field using the @Value annotation.
I also found that way of injecting properties in the Spring and Hibernate DZone article mentioned above.

@Component
public class HelloWorldServiceFactoryBean implements FactoryBean<HelloWorldService>, ApplicationContextAware {
    ...
    @Value("${service_type}")
    private String serviceType;
    ...
}

All Spring beans previously configured in XML are now configured by annotations.
Everything is annotated the way I configured it in XML and the way I thought the configuration should work.

And then the truth came out!

More code change necessary!

I got a very weird Exception that I did not expect to see:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'helloWorldService' defined in class path resource [be/stesch/demo/factorybean/HelloWorldServiceFactoryBean.class]: No matching factory method found: factory bean 'helloWorldServiceFactoryBean'; factory method 'getObject()'. Check that a method with the specified name exists and that it is non-static.
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:528)
    ...

The factory-method getObject() is not found in the declared FactoryBean. What the …?
It really is there, it exists.
The method returns a HelloWorldService instance, it exists in the HelloWorldServiceFactoryBean which is annotated with the @Component annotation and is thus Spring-managed, and the method itself is annotated with the @Bean annotation and thus should create the ‘helloWorldService‘ Spring-managed bean.
I was completely baffeled, and it took me a while to scourge around the Internet searching for people with the same problem and some solutions.

I did not find the exact same problem, but I came up with a solution using some examples I’ve found on the Internet.
I used the same ApplicationConfig class where I created the PropertyPlaceholderConfigurer to also create the HelloWorldService.
To do this, I’ll have to access the HelloWorldServiceBeanFactory‘s getObject() method and return the created instance as a Spring-managed bean. To be able to get the FactoryBean, I’ll need access to the ApplicationContext. I made the ApplicationConfig class implement ApplicationContextAware so that the ApplicationContext would be injected into the ApplicationConfig class.

This is the source code:

@Component
public class ApplicationConfig implements ApplicationContextAware {
    private ApplicationContext applicationContext;

    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    ...

    @Bean(name = "helloWorldService")
    public HelloWorldService getHelloWorldService() throws Exception {
        HelloWorldService helloWorldService = applicationContext.getBean(HelloWorldServiceFactoryBean.class)
                .getObject();
        return helloWorldService;
    }
}

Also, do not forget to remove the @Bean annotation from the getObject() factory-method in the FactoryBean. Otherwise the same Exception will keep occuring and the application won’t work.

When you run the application now, you’ll see that the correct HelloWorldService instance is created – depending on the ‘service_type‘ property value, and that the application works correctly.

Why annotating the same getObject() factory-method with the @Bean annotation as it was configured in XML doesn’t work, I do not know.
In XML you have to prefix the factory-bean attribute value with an &amp; but I did not find any possibity to do so with annotations.
Why doing the same thing with more or less the same code from another class does work, I do not know either.
But perhaps, someone else might find the solution to a problem like this thanks to my blog post.

If anyone knows and cares to explain the why’s and how’s about this issue, or has other opinions about the solution, please be so kind to post your comments underneath this blog post.


Conclusion

As a conclusion, I can say that it is possible to get rid of the XML entirely. The whole Spring container can be configured by annotating your classes and annotating methods that create beans.
What I had hoped was that I could just use the source code of my previous post about the XML configuration and annotate the existing code.
But that wasn’t completely the case. I had to write some extra code to create a PropertyPlaceholderConfigurer to be able to inject property values in other Spring-managed beans. I also had to move the factory-method – or at least the annotation that I thought would mark getObject() as a factory-method – to another class so there too extra code had to be written.
Of course the changes were minimal, but still they had to be done.

All in all, I learned something about Spring configuration with annotations and I’m eager to read your comments and gain some more knowledge about the subject.

Again, you can find the complete source code and Maven POM file in my Public DropBox folder: http://dl.dropbox.com/u/33979885/Blog%20Source%20Code/factorybean-annotation-demo.zip

Posted in Java, Spring | Tagged , , | 2 Comments

Spring FactoryBean-managed wiring

For my first post I’ll cover a client’s request on one of my projects, and how I was able to implement it.
First I’ll explain some background information as to how I got to the subject, and I’ll then explain the technicalities with some example code.

Background information

I had to migrate a project’s security mechanism from a LDAP directory to a user DAO.
Application security was configured with Acegi Security for Spring. The project’s POM file specified Acegi Security 1.0.3 and the Spring Framework 1.2.8.

The configuration of the user DAO security strategy was finished quite quickly after some research on the subject. But the client had an extra request.
For one departmental agency that used the application, the new DAO security strategy has to be used. For another departmental agency, a separately configured LDAP directory still had to be used.
Other configuration logic in the application was already based on a property key ‘location‘ which specified the departmental agency that the application had to be configured for. The client wanted to use the same property key to determine the security configuration.

I had to use the existing Acegi Security ProviderManager configuration that had a list of AuthenticationProviders and had to add the correct AuthenticationProvider for the specified departmental agency.

I wanted to find a solution for dynamically creating a Spring bean and wiring it inside the ProviderManager. Thanks to a colleague of mine, I got myself directed to the FactoryBean feature of Spring.

Hello FactoryBean!

Of course I won’t handle the exact configuration and details I used on the project itself, but i’ll explain the details using a HelloWorld-style example.

What is FactoryBean and what is it meant for? As quoted from the Spring Framework 3.0 reference:

You implement the org.springframework.beans.factory.FactoryBean interface for objects that are themselves factories.

The FactoryBean interface is a point of pluggability into the Spring IoC container’s instantiation logic. If you have complex initialization code that is better expressed in Java as opposed to a (potentially) verbose amount of XML, you can create your own FactoryBean, write the complex initialization inside that class, and then plug your custom FactoryBean into the container.

Imagine:
You have a HelloWorld application for two companies.
The two companies run exactly the same application, both on separate servers. You only want to maintain the application once, and want to be able to change the configuration at deployment time using a properties file. You can use Maven profiles to select the properties file for company A, or the properties file for company B. You would be able to use Maven profiles for all other Spring configuration files too, but when the configuration changes for all companies you’ll have to modify all the XML files instead of just one.
You want to use only one Spring ApplicationContext XML file for the entire Spring Container configuration. You don’t want to have to maintain separate files for every different company.

This is where the FactoryBean comes in.
You can let the FactoryBean create or instantiate a specific implementation of a Bean and return it to inject it into another Bean that will use it as a dependency.

Implementation

I have two services, HelloWorldServiceCompanyAImpl and HelloWorldServiceCompanyBImpl.

public class HelloWorldServiceCompanyAImpl implements HelloWorldService {
    @Override
    public String getHelloWorld() {
        return "Hello Company A!";
    }
}
public class HelloWorldServiceCompanyBImpl implements HelloWorldService {
    @Override
    public String getHelloWorld() {
        return "Hello Company B!";
    }
}

I have a properties file containing the property on which is decided what service implementation will be wired when running the application.

# 'company_a' for the HelloWorldServiceCompanyAImpl
# 'company_b' for the HelloWorldServiceCompanyBImpl
service_type=company_a

At the moment I use XML for configuring the Spring container.
In the FactoryBean, I want to be able to get the two pre-configured Spring beans from the Spring ApplicationContext. Normally you could instantiate the Java beans yourself by just using the new operator, but in my client’s case I had to use a pre-configured LdapAuthenticationProvider or DaoAuthenticationProvider. Constructing and configuring them in code wasn’t the way I wanted to go.

I implemented a FactoryBean that is also ApplicationContextAware. This way, the ApplicationContext will be available in the BeanFactory’s implementation, provided you generated the necessary getter and setter for the ApplicationContext instance. From this ApplicationContext instance, I retrieve the service beans in the FactoryBean getObject() method.
Both service beans are plain simple Spring beans with no complex XML configuration or anything special.

This is the relevant code for instantiating or getting the correct service bean in the FactoryBean:

public class HelloWorldServiceFactoryBean implements FactoryBean<HelloWorldService>, ApplicationContextAware {
    private static final Logger LOGGER = LoggerFactory.getLogger(HelloWorldServiceFactoryBean.class);
    private ApplicationContext applicationContext;
    private String serviceType;
    ...
    @Override
    public HelloWorldService getObject() throws Exception {
        HelloWorldService helloWorldService = null;

        if (ServiceConstants.COMPANY_A.equalsIgnoreCase(serviceType)) {
            LOGGER.debug("Getting bean '{}'", ServiceConstants.COMPANY_A_SERVICE);
            helloWorldService = (HelloWorldService) applicationContext.getBean(ServiceConstants.COMPANY_A_SERVICE);
        } else if (ServiceConstants.COMPANY_B.equalsIgnoreCase(serviceType)) {
            LOGGER.debug("Getting bean '{}'", ServiceConstants.COMPANY_B_SERVICE);
            helloWorldService = (HelloWorldService) applicationContext.getBean(ServiceConstants.COMPANY_B_SERVICE);
        }

        return helloWorldService;
    }
    ....
}

The FactoryBean is configured like this:

    ...
   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="location" value="classpath:application-config.properties" />
    </bean>

    <bean id="helloWorldServiceFactory"
        class="be.stesch.demo.factorybean.HelloWorldServiceFactoryBean">
        <property name="serviceType" value="${service_type}" />
    </bean>
    ...

The HelloWorldService bean is configured in the ApplicationContext XML without specifying the class attribute. I don’t want Spring itself to instantiate the bean, but I want to use a FactoryBean to do so. This requires some special configuration.
When you just enter the FactoryBean’s bean id for the factory-bean attribute, the factory-method will not be found. This is because the factory-method will be searched in the bean that is created by the FactoryBean – in this case, the HelloWorldService. To refer to the FactoryBean itself, the bean id must be prefixed by an &, or more specifically an &amp; in the XML file itself.

When you need to ask a container for an actual FactoryBean instance itself, not the bean it produces, you preface the bean id with the ampersand symbol & (without quotes) when calling the getBean() method of the ApplicationContext. So for a given FactoryBean with an id of myBean, invoking getBean("myBean") on the container returns the product of the FactoryBean, and invoking getBean("&myBean") returns the FactoryBean instance itself.

This leads us to the following HelloWorldService bean configuration:

    ...
    <bean id="helloWorldService" factory-bean="&amp;helloWorldServiceFactory"
        factory-method="getObject" />
    ...

In my Main class, I get the HelloWorldService instance from the ApplicationContext and print out it’s message.
Depending on the ‘service_type‘ property in the application-config properties file, it will print out ‘Hello Company A!’ or ‘Hello Company B!’.

public class FactoryBeanDemo {
    ...
    public static void main(String[] args) {
        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("application-context.xml");

        HelloWorldService helloWorldService = (HelloWorldService) applicationContext.getBean("helloWorldService");
        LOGGER.debug("Printing {}", helloWorldService.getHelloWorld());
        System.out.println(helloWorldService.getHelloWorld());
    }
    ...
}

You can find the complete source code, including the Maven POM file in my DropBox public folder, on the following link: http://dl.dropbox.com/u/33979885/Blog%20Source%20Code/factorybean-xml-demo.zip


In the next part, I hope to be able to get rid of all the XML configuration, and configure the Spring container using annotations.
I tried to do so already, but I got an Exception when running the application. I also got it using XML for configuration, but there it got resolved by prefixing the FactoryBean with &amp;.
As far as I can tell from the @Bean javadoc, the same thing should happen automatically when annotating the getObject() method.

The @Bean annotation may be used on any methods in an @Component class, in which case they will get processed in a configuration class ‘lite’ mode where they will simply be called as plain factory methods from the container (similar to factory-method declarations in XML). The containing component classes remain unmodified in this case, and there are no unusual constraints for factory methods.

I get the following Exception:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'createHelloWorldService' defined in class path resource [be/stesch/demo/factorybean/HelloWorldServiceFactoryBean.class]: No matching factory method found: factory bean 'helloWorldServiceFactoryBean'; factory method 'createHelloWorldService()'. Check that a method with the specified name exists and that it is non-static.
	at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:528)
	at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:983)

If anyone would know a solution to this, please be so kind to post your comments to this topic.
I’ll try to describe it further in the next part.

Posted in Java, Spring | Tagged , , | 3 Comments