Overview

A business component architecture with Spring 3.0/3.1 – Part 2: Resources

4 Comments

This is the second post in a series describing a business component architecture using Spring 3.0/3.1 features like Java based configuration, the environment abstraction, bean definition profiles and property sources. Check here for part three on properties.

In the first blog post of this series I presented the business component architecture and described, which kind of sub projects are needed and what function they have. For the configuration I use Spring 3’s Java based approach.
In a normal case a business component needs access to resources, probably a database, maybe a messaging middleware, and usually those resources differ from environment to environment. This blog post is about the environment specific integration of those resources.

In many companies most of the components access the same resources (in the same stage). For example having two components using the same DataSource for accessing a database has the advantage of a simple transaction management. The same with messaging middleware: often you have one provider.
Seeing this it makes sense if some kind of architecture team provides these resources in a way that they can be used directly, but easily extended or replaced as well. In contrast to the business components these components are pure infrastructure components. I differentiate between low level data access components and high level data access components.

Low level data access components and Spring’s bean definition profiles

For the simplicity of the example I only take a look at database access, but it should be easy to extend the concept to other type of resources.
An interface for data access is provided:

public interface LowLevelDataAccessConfig {
 
	public DataSource dataSource() throws Exception;
 
	public PlatformTransactionManager transactionManager();
 
}

The responsible architecture team provides default implementations like this one:

@Profile("websphere")
@Configuration
public class JndiDataAccessConfig implements LowLevelDataAccessConfig {
 
	@Bean
	public DataSource dataSource() throws Exception {
		InitialContext initialContext = new InitialContext();
		return (DataSource) initialContext
				.lookup("java:comp/env/jdbc/datasource");
	}
 
	@Bean
	public PlatformTransactionManager transactionManager() {
		return new WebSphereUowTransactionManager();
	}
 
}

It’s clear that this configuration is made for usage in a Websphere application server. In our company this may be the defined standard for the production environment.
This line is especially interesting:

@Profile("websphere")

Here the bean definition profiles come into play, freshly introduced in Spring 3.1. For more information take a look at this blog post. Via the annotation @Profile on class level we say that bean definition should only be added to the ApplicationContext if the profile websphere is active. Activation can be done in several ways, one way is to set a JVM property with the key spring.profiles.active.
Another provided implementation is the following:

@Profile("standalone")
@Configuration
public class StandaloneDataAccessConfig implements LowLevelDataAccessConfig {
 
	@Bean
	public DataSource dataSource() {
		BasicDataSource dataSource = new BasicDataSource();
		dataSource.setUrl("someURL");
		dataSource.setUsername("username");
		dataSource.setPassword("password");
		return dataSource;
	}
 
	@Bean
	public PlatformTransactionManager transactionManager() {
		return new DataSourceTransactionManager(dataSource());
	}
 
}

This configuration can be used outside an application server, it gets active if the profile standalone is activated.
Note: URL, username and password of course should be read from a properties file, I will take a look at properties in the next post of this series.

High level data access components

Low level data access components like a DataSource shouldn’t be used directly by a business component. Here the high level data access components come in into play, using the low level data access components. In the following example a JdbcTemplate is configured as a high level component, but there could be others here, like self written components fulfilling certain requirements.

@EnableTransactionManagement
@Import({ JndiDataAccessConfig.class, StandaloneDataAccessConfig.class })
@Configuration
public class HighLevelDataAccessConfig {
 
	@Autowired
	private LowLevelDataAccessConfig dataConfig;
 
	@Bean
	public JdbcTemplate jdbcTemplate() throws Exception {
		return new JdbcTemplate(dataConfig.dataSource());
	}
}

So, what do we have here? Let’s walk through the new elements.

@EnableTransactionManagement

@EnableTransactionManagement enables annotation based transaction management via @Transactional annotations in business components.

@Import({ JndiDataAccessConfig.class, StandaloneDataAccessConfig.class })

@Import imports the configuration classes mentioned here, but only if the corresponding profile is active.

	@Autowired
	private LowLevelDataAccessConfig dataConfig;

The autowiring mechanism looks for a Spring bean implementing the interface LowLevelDataAccessConfig. There has to be exactly one such a component, otherwise the ApplicationContext cannot be created. In our case it’s either the JndiDataAccessConfig on activation of the profile websphere, the StandaloneDataAccessConfig on activation of the profile standalone or any other configuration implementing LowLevelDataAccessConfig and being added to the ApplicationContext.

Using high level data access components in business components

In the first part of this series I defined a partner business component leaving open the data access. Let’s take a look at this component including data access:

public class PartnerServiceImpl implements PartnerService {
 
	private JdbcTemplate jdbcTemplate;
 
	public PartnerServiceImpl(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}
 
	@Override
	public Partner getPartner(long id) {
		return this.jdbcTemplate.queryForObject("SELECT ....",
				new PartnerRowMapper(), id);
	}
 
}

The configuration class looks like this:

@Import(HighLevelDataAccessConfig.class)
@Configuration
public class PartnerConfig {
 
	@Autowired
	private HighLevelDataAccessConfig dataAccessConfig;
 
	@Bean
	public PartnerService partnerService() throws Exception {
		return new PartnerServiceImpl(dataAccessConfig.jdbcTemplate());
	}
 
}

Navigation in configurations

Without any problem we can navigate from the CashingConfig
CashingConfig
to the PartnerConfig and from there into the HighLevelDataAccessConfig.
PartnerConfig
From HighLevelDataAccessConfig we cannot go on directly due to several implementations.
HighLevelDataAccessConfig
This easy type of navigation is not possible in XML.

Conclusion

Business components need resources. They get them by importing and using generally defined infrastructure components. The entry point is a high level configuration that, according to the activated profile, gets injected the appropriate low level resources. For all standard cases low level resources are well defined and can be used out of the box. For non standard cases it’s easy to integrate other low level resources. Using one interface LowLevelDataAccessConfig assures that one ApplicationContext always just includes one low level resource configuration.
In a following blog post I’ll talk about properties.

Kommentare

  • Ashish

    Nice posts.

  • Bob

    Don’t need to declare interface methods public

  • Sean

    In part 1, you mentioned

    “In this way we separate configuration and infrastructure strongly from business logic, for example we have no dependency on Spring in the interface and the implementation project. The configuration of the cashing component has a dependency on the configuration project of the partner business component:”

    But in Part 2, you use jdbcTemplate class in business implementation project, then biz project should depend on spring framework, shouldn’t it?

    • Tobias Flohre

      14. February 2012 von Tobias Flohre

      Yes, you’re right, as soon as you use the JdbcTemplate like I did it, the impl-project depends on the Spring Framework. But the JdbcTemplate is a different type of component, it’s a helper class and has nothing to do with the dependency injection mechanisms. And the JdbcTemplate is just an example of a high level data access component, for example at my current customer they have their own proprietary data access components.

Comment

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