Spring Java Configuration - What's New in M3

Today marks the third milestone release of the Spring Java Configuration project (JavaConfig for short). The release contains numerous bug fixes and new features - I'll highlight a few of the most interesting changes below, but first let me give a quick refresher as to what JavaConfig is all about.
If you have any experience with Spring, the following snippet of XML configuration will likely be familiar. Let's assume we're looking at a file named application-config.xml:
<bean id="orderService" class="com.acme.OrderService"/>
<constructor-arg ref="orderRepository"/>
</bean>
<bean id="orderRepository" class="com.acme.OrderRepository"/>
<constructor-arg ref="dataSource"/>
</bean>
</beans>
Of course, this XML configuration will ultimately serve as a set of instructions for a Spring ApplicationContext to instantiate and configure our beans:
OrderService orderService = (OrderService) ctx.getBean("orderService");
JavaConfig simply provides another mechanism to configure the Spring IoC container, this time in pure Java rather than requiring XML to get the job done. Let's port the configuration above to JavaConfig:
public class ApplicationConfig {
public @Bean OrderService orderService() {
return new OrderService(orderRepository());
}
public @Bean OrderRepository orderRepository() {
return new OrderRepository(dataSource());
}
public @Bean DataSource dataSource() {
// instantiate and return an new DataSource …
}
}
Like the original XML file, this class is simply a set of instructions as to how to construct our application's various components. We'll supply these instructions to an ApplicationContext implementation specifically designed to read and execute Java-based configuration instructions:
OrderService orderService = ctx.getBean(OrderService.class);
And that's it! Well, almost. Of course there's a lot more to JavaConfig, but for the most part the feature set is 1:1 with what's available in Spring's XML config. For full details on how to use JavaConfig, take a look at the reference documentation. If you're new to JavaConfig, be sure to check out the quick start section.
At any rate, the benefits of JavaConfig are straightforward:
- It's pure Java, so there's no XML required
- You get all the benefits of object-orientation in your configuration code
- It's type-safe and refactoring-friendly
- You still get the full power of the core Spring IoC container
With that in mind, let's take a look at what's changed in the M3 release:
AnnotationApplicationContext deprecated
Hardly a 'new feature', but this change is important to mention because much of what I'll discuss below revolves around JavaConfigApplicationContext, the successor to AnnotationApplicationContext. Why was this change made? AnnotationApplicationContext posed a significant naming collision with Spring 2.5's Annotation-Driven Injection facility. JavaConfig presents a different approach to configuration than Annotation-Driven Injection, so we wanted to make this distinction clear by renaming the class entirely. AnnotationApplicationContext will remain deprecated until the 1.0.0.rc1 release, at which point it will be removed permanently.
Type-safety improvements
While the above-mentioned JavaConfigApplicationContext behaves largely like it's predecessor, it also introduces type-safe getBean() methods that take full advantage of generics. The following code now works (and from this point forward is the preferred approach to use with JavaConfig):
OrderService orderService = context.getBean(OrderService.class);
Look ma, no casting! And no string-based lookups, either. Of course, this will beg the question, "what if two or more objects of type OrderService have been configured in the context?" This is a situtation that could easily occur, and there are multiple ways to address it. For brevity in this post, I'll simply refer those interested to take a look at the disambiguation options section of the reference documentation.
These type-safe getBean() methods have also been fitted onto the ConfigurationSupport base class, such that the following is possible:
public class ApplicationConfig extends ConfigurationSupport {
public @Bean OrderRepository orderRepository() {
return new JdbcOrderRepository(this.getBean(DataSource.class));
}
}
Major documentation update
We've worked hard to bring JavaConfig's documentation up to par with the quality for which Spring is famous. As linked above, the reference documentation is available in HTML as well as PDF formats. Note that this documentation is also packaged as part of the regular zip distributions available via SourceForge. As with all the additions in M3, your feedback on the documentation will help improve it as the project moves forward to its 1.0 GA release.
Support for JavaConfig in the web tier
Prior to this release, JavaConfig had to be 'bootstrapped' via XML in order to be used in conjunction with Spring's ContextLoaderListener and DispatcherServlet classes. To address this limitation, JavaConfigWebApplicationContext has been added. Simply specify this class as the contextClass parameter in your web.xml, and you can use your @Configuration classes directly:
<!– Configure ContextLoaderListener to use JavaConfigWebApplicationContext
instead of the default XmlWebApplicationContext –>
<context-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.config.java.context.JavaConfigWebApplicationContext</param-value>
</context-param>
<!– Configuration locations must consist of one or more comma- or space-delimited
fully-qualified @Configuration classes –>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.RootApplicationConfig</param-value>
</context-param>
<!– Bootstrap the root application context as usual using ContextLoaderListener –>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!– Declare a Spring MVC DispatcherServlet as usual –>
<servlet>
<servlet-name>dispatcher-servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<!– Configure DispatcherServlet to use JavaConfigWebApplicationContext
instead of the default XmlWebApplicationContext –>
<init-param>
<param-name>contextClass</param-name>
<param-value>org.springframework.config.java.context.JavaConfigWebApplicationContext</param-value>
</init-param>
<!– Again, config locations must consist of one or more comma- or space-delimited
and fully-qualified @Configuration classes –>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value>example.web.WebBeansConfig</param-value>
</init-param>
</servlet>
</web-app>
In practice, it is likely that many folks will want to continue using a combination of XML and JavaConfig, especially in web applications. This approach still works just fine (see combining configuration approaches), but it was important to the team that we offer users a truly "XML-free" approach if they so desire it. This change rounds out that possibility.
Modularity improvements with new @Import annotation
Much like Spring XML config's <import/> element, it is now possible to have one @Configuration class import another (and thus all its bean definitions):
public class FooConfig {
public @Bean Foo foo() { … }
public @Bean Bar bar() { … }
}
@Import(FooConfig.class)
@Configuration
public class ApplicationConfig {
public @Bean ServiceA serviceA() { … }
}
JavaConfigApplicationContext ctx = new JavaConfigApplicationContext(ApplicationConfig.class);
// foo, bar, and serviceA beans will all be available
ctx.getBean(ServiceA.class); // works
ctx.getBean(Foo.class); // works too
This functionality simply provides another tool for effectively modularizing @Configuration classes.
Externalizing values with @ExternalValue and @ResourceBundles
Several have suggested introducing functionality in JavaConfig equivalent to that of PropertyPlaceholderConfigurer for the purpose of accessing values in properties files during configuration. M3 provides just that. Let's assume we have a typical DataSource that needs its JDBC url, username and password. As per usual, these values are stored in a properties file. For the example below, that properties file will be available in our classpath at com/acme/datasource.properties. Contents of that file are as follows:
datasource.username=scott
datasource.password=tiger
Using @ResourceBundles and @ExternalValue, we can now access these properties from within JavaConfig:
@ResourceBundles("classpath:/com/acme/datasource")
public abstract class ApplicationConfig {
public @Bean OrderService orderService() {
return new OrderServiceImpl(orderRepository());
}
public @Bean OrderRepository orderRepository() {
return new JdbcOrderRepository(dataSource());
}
public @Bean DataSource dataSource() {
return new DriverManagerDataSource(url(), username(), password());
}
abstract @ExternalValue("datasource.url") String url();
abstract @ExternalValue("datasource.username") String username();
abstract @ExternalValue("datasource.password") String password();
}
A couple of things to note here: see how the value of the @ResourceBundles annotation doesn't end in .properties? This is because JavaConfig is using Spring's internationalization infrastructure underneath, and will look for variations on datasource.properties such as datasource_en.properties according to the current locale. Also, while this example supplied string values to the @ExternalValue annotation, the default is to look up properties based on the method name. So, if we hadn't supplied @ExternalValue("datasource.url") String url(), and rather just @ExternalValue String url(), JavaConfig would have looked for a property named 'url'.
What's next?
A number of users have been asking when we'll see a 1.0 release of JavaConfig, and with good reason - it's been a long time coming! There remain a number of important changes, both regarding internals as well as the public API that must be addressed before we're ready to call this 'production quality' software. Expect to see more frequent milestones and release candidates in the coming weeks. Bottom line: JavaConfig is now and will continue to be fully supported going forward. If you'd like to keep an eye on progress, please visit JavaConfig's JIRA issue tracking, especially the road map view.
Feedback Requested!
If you've made it this far through the post it's a safe bet you're at least interested in JavaConfig
So take the next step! Download the release, read the documentation, give it a spin and let us know what you think.
[Update 3/27: Post was accidentally deleted, and so re-posted - apologies to those who had already written comments, as they were deleted in the process.]
[Update 4/4: fixed a typo in the sample web.xml.]
Similar Posts
- What's New in Spring Web Services 1.5?
- More on Java Configuration
- Spring Framework 3.0 M3 released
- Spring Java Configuration Moving Ahead
- A Java configuration option for Spring











Peter Bona says:
Added on March 27th, 2008 at 7:38 amBoth in your post's and the documentation's example web.xml appears org.springframework.config.java.JavaConfigWebApplicationContext, thought it is org.springframework.config.java.CONTEXT.JavaConfigWebApplicationContext.
Why do you have @Configuration annotation? JavaConfig seems to be working fine without defining on a configuration class.
Chris Beams (blog author) says:
Added on March 27th, 2008 at 7:51 amHi Peter. Regarding the typo in the package name, this post actually does have the correction (thank you). I\'ve also fixed it in svn for the documentation.
As for @Configuration, you\'re quite right - it is not strictly required. I\'ve put it in the examples simply to be explicit, but the annotation actually serves three potential purposes:
I\'ll update the documentation to reflect this information - thanks!
Twice says:
Added on March 27th, 2008 at 10:17 amJavaConfig looks to be heading in the right direction and thanks for the work you guys are putting in it.
Sam Lee says:
Added on March 28th, 2008 at 2:40 am@ExternalValue is good step to make JavaConfig production-ready, from the perspective of maintaining configuration values. It's not clear how one can use it to support the typical case where different values are needed in different environment, e.g., developer vs integration vs production.
Igor Poteryaev says:
Added on March 28th, 2008 at 9:06 amCan we use Spring JavaConfig in OSGI environmemnt ?
Chris Beams (blog author) says:
Added on March 28th, 2008 at 1:02 pmHi Igor. First of all, JavaConfig is not yet shipping as an OSGi bundle (see SJC-64). Beyond that, using it in an OSGi context is a bit of an unknown insofar as that it hasn't been tried. Initially, JavaConfig will need to be bootstrapped via XML (with ConfigurationPostProcessor), in order to avoid proliferating JavaConfig-specific OSGI ApplicationContexts. But I'm getting ahead of myself - the bottom line is that this is certainly important, and SJC-89 has been created to ensure compatibility before we release 1.0. I'd suggest putting a watch on that issue.
http://jira.springframework.org/browse/SJC-89
bhaskar says:
Added on March 30th, 2008 at 5:48 amWhat is the future of Java Config, when Spring 2.5 supports Annotation based configuration ?
Not that I want to undermine the efforts of Java Config team, but what value does it provide over spring core's annotation based config ?
Jan says:
Added on March 30th, 2008 at 6:44 amWould it be possible for Guice to become the IoC/DI underpinning Spring. A lot of the things (and more) you're trying to achieve with JavaConfig is already implemented in that framework.
Pierangelo says:
Added on March 30th, 2008 at 2:14 pmWould it be possible to use extension method provided by the language instead of the use of @Import annotation?
@Import(FooConfig.class)
@Configuration
public class ApplicationConfig {
would become
@Configuration
public class ApplicationConfig extends FooConfig {
You can write your ApplicationConfig skeleton and then extend it as you wish.
j. betancourt says:
Added on March 30th, 2008 at 6:13 pmVery nice. JavaConfig enriches the dev's toolset. I'm reminded of the old Java classes that were used to configure EJBs before XML was used. Seems so long ago! It was not nice to have to maintain and compile stuff just to configure other stuff. Perhaps this is a drawback; or I'm missing something in what JavaConfig is?
I think A Groovy Spring builder (GroovyConfig?) would be cool. I'm sure there is one around somewhere. This would be a great alternative to XML config, and could grow to be a DSL. Of course, a true DSL, as Drools created for their framework would be optimal.
— Josef
Chris Beams (blog author) says:
Added on March 30th, 2008 at 10:44 pm@bhaskar:
Spring 2.5's annotation-driven injection presents a different model for configuration. In JavaConfig, configuration information remains centralized within @Configuration classes, while in Spring 2.5's new support, configuration annotations are distributed throughout your components and then autowired. JavaConfig follows very closely the model of Spring XML configuration, but provides a pure-Java way of expressing the configuration metadata.
@Jan:
While there are some similarities (100% java, type-safe config, etc), Guice and JavaConfig differ in a number of fundamental ways. Briefly put, JavaConfig works very closely with the core Spring IoC container, and Guice does not; JavaConfig favors a fully centralized approach to expressing DI logic (within @Configuration classes), while Guice favors DI annotations in application classes. If there are particular features you'd like to see in JavaConfig, feel free to enter them in JIRA (http://jira.springframework.org/browse/SJC).
@Pierangelo:
Yes, polymorphic @Configurations are fully supported. @Import simply provides another mechanism for modularizing configurations. You may use either or both of these approaches, depending on the situation. Right tool for the job
@j. betancourt:
Regarding recompilation issues, this is really a matter of style, preference, and requirements. If you have requirements around not needing to recompile, use XML, by all means. If you like the XML style, use it for sure. Spring IDE provides extraordinarily good support so there's no reason not to. However, if you want the full power of Java and object-orientation in your configurations, want better type-safety, or simply prefer not to work with XML so much, JavaConfig is a great option. We're not presenting any one 'silver bullet', but rather tools for devs to choose from. As I mentioned above to Pierangelo, it's about using the right tool for the job.
Jörn Zaefferer says:
Added on April 6th, 2008 at 10:46 amGreat to the see the Type-safety improvements! I found it rather annoying to configure components in type-safe Java but the having to fall back to use names and casts.
This won't core Spring components which are designed to be configured via XML. An example of that is the LocalSessionFactoryBean, which has a setHibernateProperties method, which is rather cumbersome to use and not type-safe at all. I hope to see improvements in that direction, too.
Another request I have: Please add sources to the maven distribution!
It would also help to put the necessary dependency-block for the pom.xml file on the project page.
Regards
Jörn
Tetsuo says:
Added on May 31st, 2008 at 10:17 pm@Pierangelo
A problem with using the 'extends' keyword for importing another configuration class is that Java only supports single inheritance, so, you can't extend multiple modules.
Chris, with the @Import solution, how can I get a bean from the imported context in the current context? I mean:
@Import(DataBaseConfig.class)
@Configuration
public class ApplicationConfig {
@Bean
public OrderService orderService() {
return new OrderService(dataSource());
// this dataSource comes from the imported context
}
}
Would I have to declare an abstract 'dataSource()' method?
And if you could declare imports like this:
@Configuration
public abstract class ApplicationConfig {
@Import
protected abstract DataBaseConfig dataBaseConfig();
@Bean
public OrderService orderService() {
return new OrderService(dataBaseConfig().dataSource());
}
}
This would be much more type-safe, and convenient, since you wouldn't have to re-declare the abstract method for each dependency.
Chris Beams (blog author) says:
Added on June 1st, 2008 at 2:48 am@Tetsuo
This is certainly an interesting idea! Please log a new feature request in JIRA about this so it can be considered fully.
Antony Stubbs says:
Added on July 30th, 2008 at 9:07 pmIs it possible with JavaConfig to inject constructor dependencies into a bean that haven't been declared as beens as you can do in Guice?
i.e. can we construct an object like this:
public Doc(Leg leg)
without having a bean of type Len registered? I don't think you can do this with Spring XML as with auto wiring, all dependencies must be declared . correct?
Chris Beams says:
Added on July 30th, 2008 at 9:31 pmHi Anthony,
Yes, it's quite easy to do what you're asking about:
@Configuration
public class AppConfig {
@Bean
public Doc doc() {
return new Doc(new Leg());
}
}
That's it! You have full programmatic control over object creation, so do as you please.
Kasturi Kumthekar says:
Added on August 19th, 2008 at 10:13 amI am looking to solve a config problem , and I am not sure if JavaConfig will help me out in that. Please let me know if it can and how. If it is not possible via JavaConfig, then can you point me elsewhere that would help.
The problem is thus:
Typical Spring configurations (XML or otherwise) assume that we know at deploy/config time , what the dependency of one bean would be, say "OrderService" depends on "OrderRepository".
But we have a case where OrderService depends on an "interface" "OrderRepository" and there are atleast 5 to 10 different implementations of that interface. Secondly we do not know until runtime(based on certain values retrieved from the DB and user request) which particular implementation of OrderRepository interface would be wired in.
We have a home-grown Database-backed way of resolving it. Spring claims that it also has a Database-backed configuration mechanism, but I haven't been able to locate a solution.
Your answer is greatly appreciated.
Thanks.
Chris Beams says:
Added on August 19th, 2008 at 2:07 pmHi Kasturi,
Assuming there are a finite number of OrderRepository implementations, and they're known up front, you might consider developing something like a 'DelegatingOrderRepository' that takes as dependencies bean instances of all of the known repositories. Inject the DelegatingOrderRepository instance into your OrderService, and give DelegatingOrderRepository the ability to introspect into the current request and decide, on a call-by-call basis, which of the delegate repositories to invoke. Assuming you're using Spring MVC, consider using the RequestContextHolder ThreadLocal to get hold of the current request from within your DelegatingOrderRepository implementation.
As far as determining which implementations are available in the database, consider implementing a FactoryBean to help you do this. For example, DelegatingOrderRepositoryFactoryBean could, in it's getObject() method, be responsible for finding all known implementations in the database, instatiating them as appropriate, injecting those instances into a DelegatingOrderRepository instance, and then return that instance. Of course, if you're not already familiar, you'll want to read up on the documentation for FactoryBean to understand how it plugs into the container lifecycle.
With regard to JavaConfig, you certainly could use JavaConfig to do all this, but it won't provide you any fundamental advantage over doing it in XML. You'd get the type safety and ease-of-use of pure Java, but everything I just described can be done easily from XML, too. If you already know Spring XML, you should probably stick with that in this case.
Greg says:
Added on August 27th, 2008 at 3:21 pmHow would you handle something like:
classpath:MyApp_${context}.props
classpath:Common.props
SYSTEM_PROPERTIES_MODE_OVERRIDE
…where I have a system level property determining WHICH properties file to plugin (dev/test/production), provided by "-Dcontext=dev" on my java run command? If that is available, I would be very interested in this project
P.S. I have been interested in this feature since I read Rod's blog about it. Excellent work! I implemented something like it for Spring Python (see https://springpython.webfactional.com/wiki/DecoratorBasedApplicationContext)
Greg Turnquist says:
Added on August 27th, 2008 at 3:26 pmArggh! I tried to embed some Spring XML, and the blog software ate my XML up.
Let me see if these tags will work:
[quote post="300"]
classpath:MyApp_${context}.props
classpath:Common.props
SYSTEM_PROPERTIES_MODE_OVERRIDE
[/quote]
How about that? Does it support that yet?
Greg Turnquist says:
Added on August 27th, 2008 at 3:45 pmNever mind the Spring XML. I have a PropertiesPlaceholderConfiguror, which uses SYSTEM_PROPERTIES_OVERRIDE to read a JVM property indicating which properties file to read in: myapp_dev.properties, myapp_test.properties, or myapp_production.properties. Does Java Configuration have a solution for that yet?
Chris Beams says:
Added on August 28th, 2008 at 10:39 pmGreg's request above (and my response) has been added to the comment thread at http://jira.springframework.org/browse/SJC-171
Arul says:
Added on September 3rd, 2008 at 4:52 pmHi Chris,
I am working on creating a dynamic spring config for my project using Java Config. How about translating the following XML using JavaConfig?
LocalContainerEntityManagerFactoryBean is not related to javax.persistence.EntityManagerFactory. So, I am having trouble configuring entityManagerFactory using Java Config.
I appreciate any insight into this issue.
Thank you,
Arul
Arul says:
Added on September 3rd, 2008 at 4:55 pmSome how my XML is not showing up in my earlier post, trying to repost:
[quote post="300"]
[/quote]
Arul says:
Added on September 3rd, 2008 at 5:01 pmPosting escaped XML, one last time.
<bean id="personDao" class="impl.PersonDaoImpl">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="flux" />
<property name="dataSource" ref="dataSource"/>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="showSql" value="${jdbc.showSql}"/>
<property name="generateDdl" value="${jdbc.generateDdl}"/>
<property name="databasePlatform" value="${jdbc.databasePlatform}"/>
</bean>
</property>
</bean>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
<property name="dataSource" ref="dataSource"/>
</bean>
Chris Beams says:
Added on September 3rd, 2008 at 5:04 pmHi Arul. There is now a dedicated forum for JavaConfig at forum.springframework.org. Please post this question there. Thanks!
Arul says:
Added on September 3rd, 2008 at 5:58 pmThanks Chris.
I posted it to the forum.
donny says:
Added on October 11th, 2008 at 11:56 amThanks Chris, it's a great post!
I have experience with Spring for several years , but I'm new to JavaConfig. I have one question. In our development we use spring's transaction management because it's so powerful and convenient, thanks to the AOP! ^_^ Usually we'll define one base bean like this:
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
PROPAGATION_REQUIRED
then we can define our transactional service as :
now our "fooService" can use the above transaction attribute defined in its parent bean, but how to implement this configuration when we are using JavaConfig? I didn't find any hint in JavaConfig's reference document.
Thanks again!
Chris Beams says:
Added on October 13th, 2008 at 12:32 pm@donny: It looks like the comment formatting ate your XML. Repost this question to the JavaConfig forum, and we'll address it there.
http://forum.springframework.org/forumdisplay.php?f=48
- Chris