Archive

Posts Tagged ‘autowiring’
  • 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
  • My case against autowiring

    Autowiring is a particular kind of wiring, where injecting dependencies is not explicit but actually managed implicitly by the container. This article tries to provide some relevant info regarding disadvantages of using autowiring. Although Spring is taken as an example, the same reasoning can apply to JavaEE’s CDI.

    Autowiring basics

    Autowiring flavors

    Autowiring comes into different flavors:

    • Autowiring by type means Spring will look for available beans that match the type used in the setter. For example, for a bean having a setCar(Car car) method, Spring will look for a Car type (or one of its subtype) in the bean context.
    • Autowiring by name means Spring search strategy is based on beans name. For the previous example, Spring will look for a bean named car regardless of its type. This both requires the bean to be named (no anonymous bean here) and implies that the developer is responsible for any type mistmatch (if the car bean is of type Plane).

    Autowiring is also possible for constructor injection.

    Autowiring through XML configuration

    Let’s first dispel some misconceptions: autowiring does not imply annotations. In fact, autowiring is available through XML since ages and can be enabled with the following syntax.

    <bean autowire="byType" class="some.Clazz" />
    

    This means Spring will try to find the right type to fill the dependency(ies) by using setter(s).

    Alternative autowire parameters include:

    • by name: instead of matching by type, Spring will use bean names
    • constructor: constructor injection restricted to by-type
    • autodetect: use constructor injection, but falls back to by-type if no adequate constructor is found

    Autowiring through annotations configuration

    Available annotations are the following:

    Annotation Description Source
    @org.springframework.bean.factory.Autowired Wires by type Spring 2.5+
    @javax.annotation.Resource Wires by name Java EE 5+
    @javax.inject.Inject Wires by type Java EE 6+
    @javax.inject.Qualifier Narrows type wiring Java EE 6+

    Dependency Injection is all about decoupling your classes from one another to make them more testable. Autowiring through annotations strongly couples annotated classes to annotations libraries. Admittedly, this is worse for Spring’s @Autowired than for others as they are generally provided by application servers.

    Why it is so bad after all?

    Autowiring is all about simplifying dependency injection, and although it may seem seductive at first, it’s not maintainable in real-life projects.

    Explicit dependency injection is - guess what, explicitly defining a single bean to match the required dependency. Even better, if Java Configuration is used, it is validated at compile time.

    On the opposite, autowiring is about expressing constraints on all available beans in the Spring context so that one and only one matches the required dependency. In effect, you delegate wiring to Spring, tasking him to find the right bean for you. This means that by adding beans in your context, you run the risk of providing more than one match, if your previous constraints do not apply to the new beans. The larger the project, the larger the team (or even worse, the number of teams), the larger the context, the higher the risk.

    For example, imagine you crafted a real nice service with a single implementation, that you need to inject somewhere. After a while, someone notices your service but creates an alternative implementation for some reason. By just declaring this new bean in the context, along with the former, it will break container initialization! Worse, it may be done in an entirely different part of the application, with seemingly no link with the former. At this point, good luck to analyze the reason of the bug.

    Note that autowiring by name if even worse, since bean names have a probability of collision, even across different type hierarchies.

    Autowiring is bad in Spring, but it is even worse in CDI where every class in the classpath is a candidate for injection. By the way, any CDI guru reading this post care to explain why autowiring is the only way of DI? That would be really enlightening.

    Summary

    In this post, I tried to explain what is autowiring. It can be used all right, but now you should be aware of its con. IMHO, you should only use it for prototyping or quick-and-dirty proof of concepts, everything that can be discarded after a single use. If really needed, prefer wiring by type over wiring by name as at least it matching doesn’t depend on a String.

    Categories: Java Tags: autowiringCDIspring
  • CDI worse than Spring for autowiring?

    Let’s face it, there are two kinds of developers: those that favor Spring autowiring because it alleviates them from writing XML (even though you can do autowiring with XML) and those that see autowiring as something risky.

    I must admit I’m of the second brand. In fact, I’d rather face a rabbied 800-pounds gorilla than use autowiring. Sure, it does all the job for you, doesn’t it? Maybe, but it’s a helluva job and I’d rather dirty my hands than let some cheap bot do it for me. The root of the problem lies in the implicit-ness of autowiring. You declare two beans, say one needs a kind of the other and off we go.

    It seems simple on the paper and it is if we let it at that. Now, autowiring comes into two major flavors:

    • By name where matching is done between the property's name and the bean's name
    • By type where matching is done between the property's type and the bean's type

    The former, although relatively benign, can lead to naming nightmares where developers are to tweak names to make them autowire together. The second is an utter non-sense: in this case, you can create problems in a working context by creating a bean in it, only because it has the same class as another bean already existing in the context. Worse, autowiring errors can occur in a completely unrelated location, just because of the magic involved by autowiring. And no, solutions don’t come from mixing autowiring and explicit wiring, mixing autowiring between name and type or even excluding beans from being candidates for autowiring; that just worsens the complexity as developers have to constantly question what will be the behavior.

    Autowiring fans that are not convinced should read the Spring documentation itself for a list of limitations and disadvantages. This is not to say that autowiring in itself is bad, just that is has to be kept strictly in check. So far, I’ve allowed it only for small teams and only for tests (i.e. code that doesn’t ship to production).

    All in all, Spring autowiring has one redeeming quality: candidates are only chosen from the context, meaning instances outside the context cannot wreak havoc our nicely crafted application.

    CDI developers should have an hint where I’m heading. Since in CDI every class on the classpath is candidate for autowiring, this means that adding a new JAR on the application’s classpath can disrupt CDI and prevent the application from launching. In this light, only autowiring by name should be used for CDI… and then, only by those courageous to take the risk :-)

    Categories: Java Tags: autowiringCDIspring