Spring Java configuration advantages

The debate on Spring XML config vs Java config is very common, perhaps beaten only by the “Git vs Mercurial” one or “Eclipse vs Intellij”. For this reason I wanted to write this article to explain when and how you should use Spring Java Configuration.

Spring Java configuration briefly

A the beginning, Spring offered only the XML based configuration. This may seems fantastic cause you have separation between the business logic (java spring beans) and the configuration of these objects, expressed in XML. You can eventually modify the behavior of the whole application without recompile it.

The Spring XML syntax is quite easy, so why the Spring Java config was introduced?

Compile time check

The first advantage of the Java config is the compile time check.
Lets see this simple example:

And the class InvoiceService:

You can compile this code without problems. But at runtime you get an UnsatisfiedDependencyException (cause InvoiceService need an InvoiceDao and not a ReservationDao).

I know that modern IDE can make this kind of check on Spring XML files, but in a big Spring project with 30-50 Maven modules this is useless, because normally you always build your project exploiting maven aggregation system.

The corresponding Java configuration version doesn’t have this problem:

You cannot compile it.

Refactoring

Refactoring is the key of modern software development. Business, frameworks and languages change rapidly and your code need to be ready to be changed. Without refactoring your project can turn in a Rat King.

Refactoring a big Spring project (30-50 maven modules) can be frustrating due to the lack of compile time check. If you want to speed up the refactoring process you should use the Java Configuration instead of XML configuration, but following two simple rules:

  • Autowire only @Configuration classes (Navigable configuration pattern)

  • In every Spring Bean define others beans final and Inject by constructor

If you don’t follow these rules using the Java Configuration over the XML could be self-defeating.

The navigation configuration pattern is well described in this interesting article. It consist in import and autowire another @Configuration class and use it like a factory when creating beans. You will have the IDE support on class navigation or when you want to list all the method to find the needed bean:

Schermata 2015-04-25 alle 17.11.34

Making all the fields of a Spring bean final and injecting by constructor make the compile time check of the configuration stronger and will avoid “no qualifying bean of type” errors at runtime.

Spring bean classes following this pattern can be made easily immutable with all advantages of the case. They will be easy to test (you will not need Mockito.injectMock anymore) and easy to maintain.

Testing flexibility

Combining Spring Java configuration, JUnit and Mockito you can write flexibles integration tests mocking only some Spring Beans. This is very useful in a complex system with many external component (LDAP, Solr, external web service).

When all Spring Beans of the system are well unit-tested, you would like to write an integration test.
If you have external component that you want to mock (e.g. LDAP server), you can override the production bean with a mock directly in the test class. In a big project with 20-30 spring context with import depth bigger the 3 o 4, doing the same with XML configuration could be very complex and can lead to an explosion of stub classes and stub contexts in the test scope.
The dummy example below illustrates this technique:

Remember that you can always mix Spring XML and Java configuration, but to exploit this technique the bean to override should be defined in a @Configuration class.

Conclusion

If you work on a big Spring project (more than 10 maven modules), the Java Configuration is definitely better than XML configuration, but you need to respect the navigable configuration pattern and the constructor injection.
If the project is small enough to keep low the number of Spring context and import depth, then you can keep using the XML configuration.

All the code examples are available on GitHub: https://github.com/castronu/spring-java-config-examples

Leave a Comment

Your email address will not be published.

*