Part 2: Configuring the Application

In a series of blogs we will look at how to create a REST service using the latest version of Spring. Our service will have validation so we can make sure the data stored meets the requirements and it will be secured so only the correct people can make updates.

In the last entry we created a very basic application. In this entry we configure the application using Java config.

Configuration

After we have created our entities we need to wire up our configuration. Spring 3.0 introduced a programmatic way of configuring your application. The first iteration of Spring required a lot of xml, the next step was namespaces that would default a lot of the most common uses and now there is JavaConfig. The JavaConfig way is more convention over configuration than any other incarnation of Spring Framework so far but there is still the ability to modify everything you choose to modify.

Let's look at the configuration example first and then go through what each part means.

@Configuration
@PropertySource({"classpath:config.properties"})
@ComponentScan(basePackages = {"com.captechconsulting"})
public class AppConfig {
}

The @Configuration Annotation

Classes annotated with @Configuration lets the Spring context know that it contains one or more bean definitions. There can be more than one @Configuration class in an application, in fact it is a good thing to break it up so it is easier to follow once your application grows. All classes with the @Configuration will be read by the context. Although not used in this example @Import can be used to modularize the configuration in case you depend on another configuration class.

The @Bean Annotation

The @Bean annotation means that any time a bean of the type specified is needed Spring will call the method to instantiate it. The default scope is singleton which means that Spring will only call it once and then use the same instance throughout the whole application. You could instead make it a prototype by adding @Scope("prototype") which in turn means that any time a bean of this type is used it makes a call to your method to create a new instance.

The @PropertySource Annotation

This tells Spring to read property file with additional configuration properties. These properties can be used anywhere in your application by injecting an instance of the Environment class, more on this further down.

The @ComponentScan Annotation

Tells Spring to scan the package "com.captechconsulting" for annotated classes. Spring will scan this package recursively and cache any classes annotated by the normal Spring annotations @Service, @Component, @Repository and so on.

The @ImportResource Annotation

Although not used in this example you could also include the traditional Spring xml config files if you needed to by adding a @ImportResource annotation but in this post we are going to focus on doing all the configuration in code instead.

Next we need to create the DataConfig class.

@Configuration
@EnableJpaRepositories(basePackages = "com.captechconsulting.core.dao")
@EnableTransactionManagement
public class DataConfig {
 
 @Autowired
 private Environment env;
 
 @Bean
 public LocalContainerEntityManagerFactoryBean entityManagerFactory() {
 LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
 emf.setDataSource(dataSource());
 emf.setPackagesToScan("com.captechconsulting.core.domain");
 
 JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
 emf.setJpaVendorAdapter(vendorAdapter);
 emf.setJpaProperties(additionalProperties());
 
 return emf;
 }
 
 @Bean
 public DataSource dataSource() {
 DriverManagerDataSource dataSource = new DriverManagerDataSource();
 dataSource.setDriverClassName(env.getProperty("database.connection.driver"));
 dataSource.setUrl(env.getProperty("database.connection.url"));
 dataSource.setUsername(env.getProperty("database.connection.user"));
 dataSource.setPassword(env.getProperty("database.connection.password"));
 return dataSource;
 }
 
 @Bean
 public PlatformTransactionManager transactionManager() {
 JpaTransactionManager transactionManager = new JpaTransactionManager();
 transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
 
 return transactionManager;
 }
 
 @Bean
 public PersistenceExceptionTranslationPostProcessor exceptionTranslation() {
 return new PersistenceExceptionTranslationPostProcessor();
 }
}

In our simple example we just create a new local data source but it would be just as easy to lookup a JNDI based data source if we wanted to. In this example we will be using Hibernate by wiring it up as the vendor in my EntityManagerFactory.
By autowiring the Environment as seen in the example above you are accessing any property files added to the configuration. All the database properties have been externalized to a property file so they are not hardcoded in our application. There will be other examples of using the Environment later.

The @EnableJpaRepositories Annotation

This is part of the configuration of Spring Data JPA. This will tell Spring Data to scan our package "com.captechconsulting.core.dao" for interfaces that extend JpaRepository. This is all that is needed to get the basic CRUD functionality.

The @EnableTransactionManagement Annotation

This sort of speaks for itself but what it does is lets us use @Transactional on any class or method in our application. This makes any call to the class or method be part of a transaction and Spring then handles all the commits and rollbacks in your application.

Our last config file is the WebConfig.

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
 
 @Override
 public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
 configurer.enable();
 }
}

The @EnableWebMvc Annotation

This will set up a basic Spring MVC environment such as mapping requests to the correct controller, adding the view resolvers and validation handler among other things. It will do this based on the most common use cases for each. By overriding configureDefaultServletHandling() we are customizing it by enabling the fallback to the normal servlet handling for anything not specifically matched by our own servlet.
In our case we won't have any views but we will customize that behavior later.

Initialising the Configuration

The last part needed to get this app off the ground is a WebApplicationInitializer. This is an interface that is automatically picked up by Spring to initialize your application.

public class MyWebAppInitializer implements WebApplicationInitializer {
 
 private static final Logger LOG = LoggerFactory.getLogger(MyWebAppInitializer.class);
 
 @Override
 public void onStartup(ServletContext container) {
 // Create the 'root' Spring application context
 AnnotationConfigWebApplicationContext rootContext = new AnnotationConfigWebApplicationContext();
 // Register application config
 rootContext.register(AppConfig.class);
 
 // Manage the lifecycle of the root application context
 container.addListener(new ContextLoaderListener(rootContext));
 
 // Register and map the dispatcher servlet
 addServiceDispatcherServlet(container, rootContext);
 }
 
 private void addServiceDispatcherServlet(ServletContext container, AnnotationConfigWebApplicationContext rootContext) {
 final String SERVICES_MAPPING = "/";
 
 ServletRegistration.Dynamic dispatcher = container.addServlet("servicesDispatcher", new DispatcherServlet(rootContext));
 dispatcher.setLoadOnStartup(1);
 SetString> mappingConflicts = dispatcher.addMapping(SERVICES_MAPPING);
 
 if (!mappingConflicts.isEmpty()) {
 for (String s : mappingConflicts) {
 LOG.error("Mapping conflict: " + s);
 }
 throw new IllegalStateException("'ServicesDispatcher' could not be mapped to '" + SERVICES_MAPPING + "'");
 }
 }
 
}

This creates a AnnotationConfigWebApplicationContext and adds our main config class AppConfig. We have to add this to get things started because this is the class that tells Spring to scan the rest of the classes with the @ComponentScan which triggers Spring to read the rest of our @Configuration classes.
We also add the DispatcherServlet which is the cornerstone of Spring MVC to the servlet container and adding the mapping of "/" so that our servlet picks up all requests to our host. This servlet is responsible for mapping requests to the correct handler. It uses the configuration set up by our @EnableWebMvc in the WebConfig class. This will only work on application servers supporting version 3.0 or later of the servlet specification. My server of choice is Tomcat 7 which this application has been tested on.

Conclusion

So far we have looked at creating a basic Spring application and configuring it. The benefit of this approach is that you can easily debug what is happening in the configuration. Spring also provides reasonable defaults for all the configuration so you only have to override the things you would like to change.

Each part of this blog will add functionality to our application.
Part 1: Creating the Basic Application
Part 2: Configuring The Application
Part 3: Adding the REST Services
Part 4: Adding Validation
Part 5: Adding Security to the Services
Part 6: Customising the Security for REST

In the next part of this blog we will look at how to add RESTful services on top of this basic application.

The code examples are all heavily edited excerpts but the complete source code can be found on GitHub.