The road so far….

May 24, 2010

Spring JavaConfig: redefining the Bean defination mechanism

Filed under: java, maven — Tags: , — Rahul Sharma @ 9:26 am

Spring core by default provides a whole range of options to wire the application and all of them are based on the XML approach.  But the XMLs are loosely types and can cause problems. Spring-JavaConfig provides a new approach to wire the whole application through java Classes only. It is strongly typed and much more powerful than the traditional approach. Here I will try to take a shot at the different approachs while taking a long shot at the JavaConfig approach.

The Conventional Approach

Quite a large number of applications that use Spring follow the traditional approach of  Bean definitions in the XML file. This file is one single place where you would wire your application. Often these files become huge containing numerous Bean definitions. At such a stage you often split the files into multiple XMLs, import them  as per requirement and then move forward. Another problem that is often associated with XMLs is , if there is some problem in wiring that will get highlighted only at runtime e.g. we have made a typo in one of the beans id, now unless the configuration is loaded we will not discover the issue. A way to mitigate the issue is to have unit tests that will load the configuration to see if it loads or not rather pushing the issue till deployment.

Using Annotations: a short hand approach

Spring also provides  a short hand approach with the utilization of annotations. Annotations were introduced in Java 5 and spring tries to employ them. You need to write @Component, @Autowired  and other annotations on the entities you want to create. After this you need to enable the component scan, annotations support and other components in the traditional  XML file. The XML still remains !!!!!

@Component("validator")
public class Validator {
 private Rule rule;

 @Autowired
 public Validator(Rule checker) {
 this.rule = checker;
 }
}

@Component
public class DefaultRule implements Rule {
 public boolean check(String text) {
 System.out.println("text checked for english");
 return false;
 }
}
xml definition:
<beans>
<context:component-scan base-package="info.di.spring.annotation" />
<context:annotation-config />
</beans>

Spring JavaConfig: Throw away that XML file.

The Spring JavaConfig redefines the way you write you Bean definitions. Bean definitions are written in a custom infrastructure class and the class is marked with @Configuration annotation. Methods are written marked with @Bean annotation that will signify that the return object is a Bean. Since you are in a java class  nothing like p:propery-val or p:property-ref exists you must construct objects yourself, so you have much more control over what you want to do with the Bean before returning it. It provides all the standard spring configuration modifiers eg you can use Autowire for autowiring by type/name etc.

Besides the standard modifiers there is one interesting modifier, the Primary modifier. It can be used in cases where you are having multiples beans of the same type and have configured Autowire-By-Type. In such- a-case you must specify the bean name which you want to inject else the spring container will give you error OR you can put the primary=True in one of the @Bean annotation for the specific type  and the container will pick up that bean for autowiring.

Now in order to load the configuration, that you wrote in you infrastructure class,  you need to create a Spring ApplicationContext. A JavaConfigApplicationContext is provided in the package that can load these configuration classes. You can have multiple configuration classes and load them in single Context. Then getBean method can be invoked to get beans of the specified name. The Bean name is the method name by default.

The JavaConfigApplicationContext has some more methods besides the standard ApplicationContext methods .

getBean(Class classtype)

This method will return a bean depending on the class type of the specified type. Using generics it returns the object of the type specified so no type casting is required.

getBean(Class classtype,String name)

In case you have multiple beans of the same type then you can specify the type and name of the Bean  you want to retrieve.

The configuration
@Configuration(defaultAutowire = Autowire.BY_TYPE)
public class ConfigurationBuilder {
 @Bean
 public Validator validator() {
  return new JavaConfigValidator();
  }

 @Bean(primary= Primary.TRUE)
 public Rule defaultRule() {
  return new DefaultRule();
  }

 @Bean
public Rule newRule() {
 return new newRule();
 }
}
Loading the configuration
@Test
 public void shouldLoadInjectionFromJavaConfigAnnotation() {
  JavaConfigApplicationContext context = new JavaConfigApplicationContext(
           ConfigurationBuilder.class);
  Validator javaConfigValidator = context.getBean(Validator.class);
  javaConfigValidator.verify("verify this also");
  Rule newrule = context.getBean(Rule.class, "newRule");
  newRule.check("check this one");
 }

The definitions done in this way are compile time definitions as they are now written in a java class. These definitions are strongly types unlike definitions in XMLs, any typos / errors in them can easily be determined and fixed. Also you have the full control of bean creation logic, any pre initialization and post initialization can be taken care off. Most importantly you are not required to write any XML definitions and your business entities are free from any infrastructure annotations also !!!!!!

Resources :

spring javaconfig

maven configuration

Advertisements

2 Comments »

  1. Hi Rahul,

    It looks like you’re referring to the latest milestone of the JavaConfig project in your write up here, but it should be generally considered obsolete now, as most of the functionality from JavaConfig has been migrated into Spring core for the 3.0 release. Some names have changed, for example JavaConfigApplicationContext is now AnnotationConfigApplicationContext, etc. Certain attributes on @Bean and @Configuration are no longer available. The approach in general remains the same.

    Comment by Chris Beams — May 25, 2010 @ 11:46 am

    • Hi Chris,
      Yes, you are right I am using the latest JavaConfig milestone with Spring 2.5 and thanks for the update. I did not knew that the approach has been adopted in Spring 3.0, with a few modifications. It would have been nice if the project mentioned that it has been discontinued and has been adopted in the Spring 3.0. I have to admit that the approach of using java scores well over using XML.

      Comment by Rahul Sharma — May 25, 2010 @ 1:05 pm


RSS feed for comments on this post. TrackBack URI

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

%d bloggers like this: