Explicit vs Implicit configuration in Spring

With the move to annotations for use of Spring, many projects have become based on component-scanning, auto-wiring and property-placeholder injection — an ‘implicit’ approach to configuration.

However, it can still be very useful to specify ‘explicit’ configuration. This gives us control of top-level application config & enables extensible configuration using the Strategy pattern.

Gaining control of configuration is crucial to enable per-customer/ per-application customization.

Implicit Configuration

Implicit configuration rests on three legs — annotations to mark Spring-managed beans, component-scanning to find them, and property-placeholder injection to customize values.

Many projects are built with pervasive use of @Service/ @Component annotation & auto-wiring to connect them all.

This however suffers the limitation, that only a single bean can match any autowired reference.  Property files provide the only  source of customization.

Powerful configuration requires use of the ‘Strategy’ and ‘Delegate’ patterns. However, these confuse auto-wiring. Rich subclassing & configuration of strategies also require stronger configuration than just placeholder injection.

How can we combine this with our existing code?

Explicit XML for Strategy-based Configuration

Spring’s XML configuration provides an ideal means of explicit bean control & instantiation. This is perfect for major project structures, as well as strategy/ subclass configuration.

Generally, XML-based configuration is best for:

  • core application configuration
  • major infrastructure/ startup components, such as your DB connection or Hibernate
  • any rich customization relying on subclassing/ or extensibility

Now, one of the key goals here is not to eliminate annotation-based configuration — but to extend & complement it. Many projects have hundreds of existing auto-scanned & auto-wired components, which we are going to retain compatibility with.

Approach

We’re going to introduce “explicit configuration” for just one or a few key beans, and have these seamlessly inter-operate with the rest of our project.

For this example I am showing an “App Config” bean, which provides a central place for key parameters to be picked up by library code & services.

For example, this enables shared mid-level layers (library code) to be identified & parameterized differently when used by different applications — despite the code being the same.

1. Define the bean class

Here, I’m defining a “central configuration” class to hold key mid-level parameters & identification. Other beans will reference this, to use the values..

/** AppConfig;
 *      -- explicitly instantiated, not to be made @Component or @Service!      SPEC.
 */
public class AppConfig {
    protected String businessChannel;
    protected String websiteRoot;
    protected ITaxCalculator taxCalculator;

    // Business Channel;    web, mobile, email   etc.
    public String getBusinessChannel() {return businessChannel;}
    public void setBusinessChannel (String businessChannel) {this.businessChannel = businessChannel;}

    // Website Root;        base URL for redirects etc.
    public String getWebsiteRoot() {return websiteRoot;}
    public void setWebsiteRoot (String websiteRoot) {this.websiteRoot = websiteRoot;}

    // Tax Calculator;      subclassed & configurable strategy
    public ITaxCalculator getTaxCalculator() {return taxCalculator;}
    public void setTaxCalculator (ITaxCalculator taxCalculator) {this.taxCalculator = taxCalculator;}

}
2. Don’t use annotations on an ‘explicitly configured’ bean

Annotations such as @Component and @Service are matched by component-scanning, to instantiate an “implicitly configured” instance of your bean.

Since we’re defining it explicitly in XML, using annotations would cause a second (unconfigured) instance to be registered! This would cause a uniqueness error with auto-wiring.

So keep it off, and leave a comment for other developers.

3. Configure as ‘autowire-candidate’ in Spring XML application-context

I could specify a SalesTaxCalculator for the US — but here, I’m defining the tax strategy as GST with a 12.5% rate. This illustrates the usefulness, not just to select subclasses, but to parameterize & configure them. By selecting & implementing different strategies we can adapt the deployment/application to different states & countries.

Note that the bean has to be a candidate for autowiring. This can be filtered by the top-level element ‘default-autowire-candidates’ setting, so this may not be necessary in your project — but I’ll show it here as specified explicitly.

<!-- Application Config;    major system-wide paramaters.
      -     - enable app-specific configuration of shared library code,
      -     - customer-specific 'website URLs', 
      -     - and customization of Tax strategy.
     -->
<bean class="example.AppConfig" autowire-candidate="true">
    <property name="businessChannel"    value="WEB" />
    <property name="websiteRoot"        value="http://literatejava.com/" />
    <property name="taxStrategy">
        <bean class="example.tax.GstCalculator">
            <property name="title"          value="GST" />
            <property name="ratePercent"    value="12.5" />
        </bean>
    </property>
</bean>
4. Use annotations to reference the ‘explicitly configured’ bean

Now we have defined the AppConfig bean within our application context, our code (including shared and library code) is freely able to use it — including by auto-wiring.

@Service
@Transactional(readOnly = true)
public class OrderService {

    @Autowired
    protected AppConfig appConfig;

    // place an Order, using the defined business channel
    //
    public void placeOrder (Order order) {
        // ...
    }

}

Conclusion

Annotation scanning & auto-wiring help us on big projects, where many hundreds or thousands of beans may need to be wired.

However, tend to lead to an “implicit” configuration model with property files & property-placeholder injection being the only source of configurability. This is a weaker & less flexible model than the full power of Spring.

Using Spring XML for key configuration enables more direct & explicit control over application configuration. Subclassed & extensible configuration can be supported, enabling richer & more powerful OO techniques such as the strategy & delegate patterns.

With an XML file per application, or per customer, this enables powerful application-/ customer-specific configuration. Large shared codebases can be enhanced with small sections of pluggable configuration, to deliver widely configurable applications.

How have you been configuring your Spring applications? Share your experiences.

References:
- Spring: Including/excluding a bean from autowiring
- Spring: Classpath scanning & managed components
- Spring: Property placeholder configuration
- Wikipedia: Strategy pattern
- Wikipedia: Delegate pattern

11 thoughts on “Explicit vs Implicit configuration in Spring”

  1. I have generally held this same understanding of implicit vs. explicit configuration, but I have seen one really cool usage of implicit configuration along with the strategy pattern. If your strategies are mutually exclusive, as in web app vs. thin client vs. mobile app, you can package them in separate artifacts and deploy only the one that is relevant to the usage. The appearance of a bean on the classpath causes the correct strategy to be used. There are, of course, other use cases for the strategy pattern, but this particular usage was pretty eye-opening for me when I first saw it applied.

    1. Thanks Tim, interesting suggestion — we have a similar “pluggable validator” in one existing app.

      Of course, this only works where code can be structured into a separate module & where usage/instantiation of the strategy will always be singular & mutually exclusive.

      My preference, for ease of maintenance & more powerful strategy possibilities, is to keep the different classes in the same code base but explicitly select & configure which one to use.

      This also enables delegation, configuration by properties & composition of strategies.

      This is what I’m looking towards with the TaxCalculator, which is just a simple-ish example. Shipping calculations really start to open the box as to the desirability of extensibility/ composition :)

      For example, a GlobalShippingCalculator could composite USShippingCalculator, WorldAirmailShippingCalculator and WorldFreightShippingCalculator.

      Or, for a defined date range, US shipping might be free. So you could define in a DateLimitedShippingCalculator, delegating (for that date range) to a FreeShippingCalculator!

      This is the power of explicit configuration. For me, this was what was most exciting about Spring..

  2. With Spring 4, they have added an @Conditional annotation that you can use to get a sort of “best of both worlds”. In custom @Conditional matchers, you can do a lot more advanced configuration (with the added help of the compiler) than would otherwise not be possible with XML.

    @Conditional is also the basis on which Spring Boot works. You mentioned a case for XML being selecting between “major startup components”. Spring Boot decides to start Jetty or Tomcat simply based on if the jar is in the class-path. Something like that is only possible with @Configuration.

    In general, Spring itself is getting far, far away from XML with a push for more annotation-based components. Legacy apps (Broadleaf Commerce included) still rely on a lot of XML configuration but I wouldn’t recommend evergreen projects use XML-based confuguration at all.

    1. Thanks, Phillip. While @Conditional sounds good, any form of configuration embedded with the bean class is essentially limited to a singleton and “implicit” style of usage.

      Customer & deployment requirements are a first-class fact. Implicit configuration is great where appropriate, and we use lots of it, but for those key top-level configurations it’s simpler & much more correct to accept these as “primary” & make them explicit.

      @Conditional means that your strategies have to know, and agree between themselves, on the entire universe of customer/deployment usage. For trivial cases this can work, beyond that it’s horrendously limited.

      Two design options, you tell me which is best?

      1) Implement a GST Strategy, which not only knows how to calculate GST but must also encode with annotations every country/deployment situation in the world to which it will apply.

      2) Implement a GST Strategy. Select it for the customer/deployments which need it.

      Lastly, most of the really powerful OO techniques — Strategy pattern, Composition & Delegation — require the ability to create & configure instances explicitly — not just one auto-configured singleton per class.

      These techniques are where the true power of OO lies. We need them in the toolbox for real software modularity & configurability. Configured by separate XML, or conceivably by separate code, but for these implicit configuration is not enough.

      1. Yeah, you made some good points here for scenarios that can be really hard without explicit configuration. And maybe other scenarios aren’t just ‘hard’, but they’re counterintuitive to try to have it be implicitly discoverable.

        I think what I was actually intending to write was more of a critique on using XML for explicit configuration; basically what Josh Long wrote below for just Java-based configuration as opposed to XML. Spring is starting to abandon the XML format specifically, but not necessarily the explicit nature of bean configuration. Instead, those bean definitions can be defined with Java code that gives you type-safety and potentially a tighter feedback loop (although in some scenarios you can get pretty tight with XML-based too). And now with Spring 4, you can even do Groovy-based bean configs which is pretty interesting: https://spring.io/blog/2014/03/03/groovy-bean-configuration-in-spring-framework-4

        By the same token, you can forego web.xml completely in the Servlet 3.0 spec and instead write an implementation of ServletContainerInitializer (I think that’s right) that does the same thing (with Spring, you would write an implementation of WebApplicationInitializer).

  3. Nice blog! As you suggest, implicit and explicit configuration need not be an either/or proposition. I wondered if you’ve taken a look at Spring’s Java configuration style.

    It offers the best of both worlds: it’s type safe, verified by the compiler, and you don’t have to worry about fat-fingering XML and discovering it only at runtime, and it’s centralized, and able to use property placeholders. Here’s an example that configures two different datasources that are activated using Spring’s profiles. It also turns on component-scanning (the same as you might using <ctx:component-scan/>) to find all beans in the same package as, or below, this configuration class’s package. It turns on declarative transaction management, as well, using @EnableTransactionManagement (simialar to <tx:annotation-driven/>). It imports bean definitions from another configuration class, as well as from another Spring XML configuration file. The configuration class defines two different dataSources, one specifically for production (and it relies on the Environment abstraction to access property values in a property file, in this case application.properties), and another embedded one specifically for unit-testing and development. @Profile is a specialization of the aforementioned @Conditional annotation. This configuration class also wires up a JdbcTemplate instance and a DataSourceTransactionManager which the declarative transaction management will need to do its work.

    The methods are provider methods: they define a bean instance, just like a <bean/> instance in XML. They express their dependencies – other beans in the context needed to satisfy their dependencies – as parameters to the provider methods. You can disambiguate which instance of which bean you want if there is an ambiguity by using @Qualifier. The beans can enjoy any of the other configuration options available in XML, including @Scope, @Lazy, etc.


    @Configuration
    @Import(SomeOtherConfiguration.class)
    @ImportResource( "some-other-spring-context.xml")
    @ComponentScan
    @EnableTransactionManagement
    @PropertySource ( "/application.properties")
    class ServiceConfiguration {

    @Autowired
    private Environment env;

    @Bean
    @Profile("production")
    javax.sql.DataSource productionDataSource(){
    String user = this.env.getProperty ( "dataSource.username") ;
    String pw = this.env.getProperty( "dataSource.password") ;
    // ...
    return new SimpleDriverDataSource ( user, pw ... ) ;
    }

    @Bean
    @Profile("dev")
    javax.sql.DataSource devDataSource(){
    return new EmbeddedDataSource(...);
    }

    @Bean (name = "transactionManager")
    PlatformTransactionManager txManager(javax.sql.DataSource configuredDataSource){
    return new DataSourceTransactionManager( configuredDataSource);
    }

    @Bean // bean name is otherwise inferred from the method name
    JdbcTemplate jdbcTemplate ( javax.sql.DataSource ds){
    return new JdbcTemplate(ds);
    }
    }

    I hope this is sort of what you’re looking for. Of course, with Spring Boot, we often don’t even need to write even this much configuration, in XML or Java! :-)

    1. Thanks Josh, exactly. This is a perfect example of “explicit” configuration, defining key configuration & beans in an explicit way.

      Customer & deployment requirements are always first-class facts. Having first-class, direct & explicit specification of these is no less than they deserve.

      Thanks for pointing out Spring’s Java configuration style. As you say, it provides “explicit” configuration by Java class, external to the beans it configures. This is perfect for centralizing key configuration.

      This fulfils the fundamental requirement, that key customer/deployment configuration should be explicit. Since it is separate from the instances it configures, it opens the door to the Strategy/ Composite/ Delegate capabilities — the full power of OO.

      From the early days of Spring I have been very happy with XML, but especially from the dot NET side there has always been interest in “configuration by code” approaches.

      Externalizing configuration via Spring’s Java configuration style gives some interesting differences to XML:
      1) it’s compiled, which gives added verification,
      2) it’s in Java code rather than XML — some people find this harder, some easier;
      3) every customer/ deployment config must be maintained in your codebase.

      So, a very interesting alternative to XML but one which I can fully recommend. Thanks Josh!

  4. In our project we strictly prefer explicit configuration using XML. Implicit Java-based configuration is solely used within Spring Integration Tests. The main reason for this is the fact, that in my opinion the referencing of property placeholders violates the idea of Inversion of Control. While there may be two different thread pools in my applications context, for example, that I used to configure based on the same core thread property, this may change in the future. With XML this is as simple as changing the referenced property keys in XML, while otherwise I have to crawl through the Java Code.
    Apart from that, Spring’s custom namespaces are brilliant for hiding complex setup, e.g. the JMS MessageListenerContainer. And finally, you can always build your own XML namespaces, especially when dealing with customer-specific Spring configurations, e.g. wrapping aways complexity.

    1. Thanks, Maverick. That captures an important point about “explicit” configuration — it gives you the power to have more than one instance of a class.

      You have two thread pools, I have strategies based on composition, somebody else will integrate with two external services — “implicit” configuration is limited or unable to support any of these.

      Essentially, as soon we start to contemplate real “subclass & property” extensible configuration, or go beyond trivial singleton use, we need explicit configuration.

      1. In that context I would also not want to miss the XML abstract bean definitions, which provide suitable fail-safe templating for multiple bean instances. In fact, the whole idea of separating bean definition from bean creation is far superior than combining it in one @Bean method.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>