Archive

Posts Tagged ‘Spring’
  • Flavors of Spring application context configuration

    Spring framework logo

    Every now and then, there’s an angry post or comment bitching about how the Spring framework is full of XML, how terrible and verbose it is, and how the author would never use it because of that. Of course, that is completely crap. First, when Spring was created, XML was pretty hot. J2EE deployment descriptors (yes, that was the name at the time) was XML-based.

    Anyway, it’s 2017 folks, and there are multiple ways to skin a cat. This article aims at listing the different ways a Spring application context can be configured so as to enlighten the aforementioned crowd - and stop the trolling around Spring and XML.

    XML

    XLM has been the first way to configure the Spring application context. Basically, one create an XML file with a dedicated namespace. It’s very straightforward:

    <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.xsd">
        <bean id="foo" class="ch.frankel.blog.Foo">
            <constructor-arg value="Hello world!" />
        </bean>
        <bean id="bar" class="ch.frankel.blog.Bar">
            <constructor-arg ref="bar" />
        </bean>
    </beans>
    

    The next step is to create the application context, using dedicated classe:

    ApplicationContext ctx = new ClassPathXmlApplicationContext("ch/frankel/blog/context.xml");
    ApplicationContext ctx = new FileSystemXmlApplicationContext("/opt/app/context.xml");
    ApplicationContext ctx = new GenericXmlApplicationContext("classpath:ch/frankel/blog/context.xml");
    

    XML’s declarative nature enforces simplicity at the cost of extra verbosity. It’s orthogonal to the code - it’s completely independent. Before the coming of JavaConfig, I still favored XML over self-annotated classes.

    Self-annotated classes

    As for every new future/technology, when Java 5 introduced annotations, there was a rush to use them. In essence, a self-annotated class will be auto-magically registered into the application context.

    To achieve that, Spring provides the @Component annotation. However, to improve semantics, there are also dedicated annotations to differentiate between the 3 standard layers of the layered architecture principle:

    • @Controller
    • @Service
    • @Repository

    This is also quite straightforward:

    @Component
    public class Foo {
    
        public Foo(@Value("Hello world!") String value) { }
    }
    
    @Component
    public class Bar {
    
        @Autowired
        public Bar(Foo foo) { }
    }
    

    To scan for self-annotated classes, a dedicated application context is necessary:

    ApplicationContext ctx = new AnnotationConfigApplicationContext("ch.frankel.blog");
    

    Self-annotated classes are quite easy to use, but there are some downsides:

    • A self-annotated class becomes dependent on the Spring framework. For a framework based on dependency injection, that’s quite a problem.
    • Usage of self-annotations blurs the boundary between the class and the bean. As a consequence, the class cannot be registered multiple times, under different names and scopes into the context.
    • Self-annotated classes require autowiring, which has downsides on its own.

    Java configuration

    Given the above problems regarding self-annotated classes, the Spring framework introduced a new way to configure the context: JavaConfig. In essence, JavaConfig configuration classes replace XML file, but with compile-time safety instead of XML-schema runtime validation. This is based on two annotations @Configuration for classes, and @Bean for methods.

    The equivalent of the above XML is the following snippet:

    @Configuration
    public class JavaConfiguration {
    
        @Bean
        public Foo foo() {
            return new Foo("Hello world!");
        }
    
        @Bean
        public Bar bar() {
            return new Bar(foo());
        }
    }
    

    JavaConfig classes can be scanned like self-annotated classes:

    ApplicationContext ctx = new AnnotationConfigApplicationContext("ch.frankel.blog");
    

    JavaConfig is the way to configure Spring application: it’s orthogonal to the code, and brings some degree of compile-time validation.

    Groovy DSL

    Spring 4 added a way to configure the context via a Groovy Domain-Specific Language. The configuration takes place in a Groovy file, with the beans element as its roots.

    beans {
        foo String, 'Hello world!'
        bar Bar, foo
    }
    

    There’s an associated application context creator class:

    ApplicationContext ctx = new GenericGroovyApplicationContext("ch/frankel/blog/context.groovy");
    

    I’m not a Groovy developer, so I never used that option. But if you are, it makes a lot of sense.

    Kotlin DSL

    Groovy has been unceremoniously kicked out of the Pivotal portfolio some time ago. There is no correlation, Kotlin has found its way in. It’s no wonder that the the upcoming release of Spring 5 provides a Kotlin DSL.

    package ch.frankel.blog
    
    fun beans() = beans {
        bean {
            Foo("Hello world!")
            Bar(ref())
        }
    }
    

    Note that while bean declaration is explicit, wiring is implicit, as in JavaConfig @Bean methods with dependencies.

    In opposition to configuration flavors mentioned above, the Kotlin DSL needs an existing context to register beans in:

    import ch.frankel.blog.beans
    
    fun register(ctx: GenericApplicationContext) {
        beans().invoke(ctx)
    }
    

    I didn’t use Kotlin DSL but to play a bit with it for a demo, so I cannot say for sure about pros/cons.

    Conclusion

    So far, the JavaConfig alternative is my favorite: it’s orthogonal to the code and provides some degree of compile-time validation. As a Kotlin enthusiast, I’m also quite eager to try the Kotlin DSL in large projects to experience its pros and cons first-hand.

  • A use-case for Spring component scan

    Regular readers of this blog know I’m a big proponent of the Spring framework, but I’m quite opinionated in the way it should be used. For example, I favor explicit object instantiation and explicit component wiring over self-annotated classes, component scanning and autowiring.

    Concepts

    Though those concepts are used by many Spring developers, my experience has taught me they are not always fully understood. Some explanation is in order.

    Self-annotated classes

    Self-annotated classes are classes which define how they will be instantiated by Spring via annotations on the classes themselves. @Component, @Controller, @Service and @Repository are the usual self-annotated classes found in most Spring projects.

    @Component
    class MySelfAnnotatedClass
    

    The main disadvantages of self-annotated classes is the hard coupling between the class and the bean. For example, it’s not possible to instantiate 2 singleton beans of the same class, as in explicit creation. Worse, it also couples the class to the Spring framework itself.

    Note that @Configuration classes are also considered to be self-annotated.

    Component scanning

    Self-annotated classes need to be listed and registered in the context. This can be done explicitly:

    @Configuration
    class MyConfig {
    
        @Bean
        fun myClass() =  MySelfAnnotatedClass()
    }
    

    However, the most widespread option is to let the Spring framework search for every self-annotated class on the project classpath and register them according to the annotations.

    @Configuration @ComponentScan
    class MyConfig
    

    Autowiring

    Some beans require dependencies in order to be initialized. Wiring the dependency into the dependent bean can be either:

    • explicit: it’s the developer’s responsibility to tell which beans will fulfill the dependency.
    • implicit (or auto): the Spring framework is responsible to provide the dependency. In order to do that, a single bean must be eligible.

    Regarding the second option, please re-read an old post of mine for its related problems.

    Sometimes, however, there’s no avoiding autowiring. When bean Bean1 defined in configuration fragment Config1 depends on bean Bean2 defined in fragment Config2, the only possible injection option is autowiring.

    @Configuration
    class Config2 {
    
        @Bean
        fun bean2() = Bean2()
    }
    
    @Configuration
    class Config1 {
    
        @Bean @Autowired
        fun bean1(bean2: Bean2) = Bean1(bean2)
    }
    

    In the above snippet, autowiring is used without self-annotated classes.

    Reinventing the wheel

    This week, I found myself re-implementing Spring Boot’s actuator in a legacy non-Spring Boot application.

    The architecture is dead simple: the HTTP endpoint returns a Java object (or a list of them) serialized through the Jackson library. Every endpoint might return a different object, and each can be serialized using a custom serializer.

    I’ve organized the project in a package-per-endpoint way (as opposed to package-per-layer), and have already provided several endpoints. I’d like people to contribute other endpoints, and I want it to be as simple as possible. In particular, they should only:

    1. Declare controllers
    2. Declare configuration classes
    3. Instantiate Jackson serializers

    The rest should taken care of by generic code written by me.

    The right usage of autowire

    Controllers and configuration classes are easily taken care of by using @ComponentScan on the main configuration class located in the project’s main package. But what about serializers?

    Spring is able to collect all beans of a specific class registed into a context into a list. That means that every package will declare its serializers independently, and common code can take care of the registration:

    {% highlight java linenos %} @Configuration @EnableWebMvc @ComponentScan class WebConfiguration : WebMvcConfigurerAdapter() {

    @Autowired
    private lateinit var serializers: List<StdSerializer<*>>
    
    override fun configureMessageConverters(converters: MutableList<HttpMessageConverter<*>>) {
        converters.add(MappingJackson2HttpMessageConverter().apply {
            objectMapper.registerModule(SimpleModule().apply {
                serializers.forEach { addSerializer(it) }
            })
        })
    } } {% endhighlight %}
    

    Magic happens on lines 6 and 7 above. This configuration class has already been written, and new packages don’t need to do anything, serializers will be part of the list.

    Here’s an example of such a configuration class, declaring a serializer bean:

    @Configuration
    class FooConfiguration {
    
        @Bean
        fun fooSerializer()  = FooSerializer()
    }
    
    class FooSerializer : StdSerializer<Foo>(Foo::class.java) {
        ...
    }
    

    Even better, if packages need to be modularized further into full-fledged JARs, this setup will work in the exact same way without any change.

    Conclusion

    A better understanding of self-annotated classes, component-scanning and autowiring is beneficial to all Spring developers.

    Moreover, while they have a lot of drawbacks in “standard” beans classe, it’s not only perfectly acceptable but even an advantage to do so within the scope of configuration classes. In projects designed in a package-by-feature way, it improves modularization and decoupling.

    Categories: Development Tags: Springautowiringcomponent scangood practice