Advanced Configuration of the Spring MVC Frameworkby Dejan Bosanac
In this article I will present some configuration tips for the Spring MVC framework that could help you manage multiple instances of your Spring-based web application. The configuration management topic is often neglected in the literature, but as we will see, it is very important for real-life web development. It is not directly related to any particular technology, so we will start by explaining the basic concepts of the problem. Next, we will focus on the Spring MVC framework and offer a few solutions for projects developed using this technology.
It is common for a web application to be deployed on more than one host. Take, for example, a website that will have only one instance in production. Beside that instance, you (as its developer) will probably have another (development) instance on your development machine. You may also find useful to maintain another installation of your application on some local development server inside of your company (organization). The purpose of this instance would usually be to give access to web designers, for quality assurance stuff, to people that should document the application, etc.
As you can see, even in this simplest possible scenario there are three instances of the application that we should install, configure, and maintain. The situation is even worse for geographically dispersed teams that work on a project like this. For any non-trivial web application project, you will usually have more that one developer with his local installation of the project and local settings, one installation for running unit tests, and so on.
Many organizations create their products as web applications. You may find examples of such products in various e-commerce systems, content management systems (CMSes), or even blog publishing platforms. Products like these are intended for deployment on as many servers as possible. For successful acceptance of general-purpose web applications, their developers must ensure that their apps are easy to install and integrate well with other web applications. After this discussion, it should be clear that application configuration, which is the topic of this article, is one of the very important issues for developers of general-purpose web application projects.
Version control systems, such as CVS or Subversion, are one of the standard tools used by development organizations. This kind of tool represents a central source code repository of some organization and is used to keep the source code in order. Users are able to track changes of the application's source, show differences among file versions, and make project branches. Also, they make partial updates on the application deployments possible.
It is clear that version control system software is necessary for keeping track of your source code and that it can help in a great deal with the application configuration problems discussed here. Still, in this article, we will not focus on version control systems, as there are lots of great materials that cover this topic. Here, we will focus on just a small subtopic of the version control issue: how to ease the configuration of web applications (particularly those written using the Spring MVC framework).
The question is: what kind of configuration we are talking about here? Well, any web application needs resources that are usually specific to the host on which it is running, such as the database URL, the SMTP server that will send emails, folders that will contain some application-specific documents, etc. Settings like these should be centralized so that application configuration could be as easy as possible.
But this describes only the simplest version of the problem. Sometimes, you need more complex configuration differences among application deployments. This means that you will have to make different bean wirings among deployments, which complicates this issue even further.
Solutions to these application configuration issues have many benefits, ranging from easier installation and configuration of your application to easier source version control, which leads to fewer conflicts in your source repository. Now let's discuss this topic in more detail and through examples.
Let's start with demonstrating the simpler version of the problem we described above. In this scenario, all that you want to change among application deployments are simple configuration parameters, such as URLs, passwords, etc. If you have ever tried to develop a web application using the Spring MVC framework, you know that there are two configuration files that should be used:
/WEB-INF/applicationContext.xml allows you to configure your beans, or to indicate the context of your application. This is the place where you define your business logic beans, resources, and all other beans that are not directly related to the web tier.
/WEB-INF/[servlet-name]-servlet.xml is used to configure the web tier and view resolvers, controllers, validators, and all other beans that you need in the MVC framework. The [servlet-name] refers to the name of the Spring's dispatcher servlet defined in the web.xml deployment descriptor.
So what's the problem here? The problem is that your
applicationContext.xml will contain some bean definitions that are host-specific. The most obvious example of this issue is a bean that holds JDBC connection information, but any non-trivial application will have a dozen such beans. Take a look at the following example:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName"> <value>org.postgresql.Driver</value> </property> <property name="url"> <value>jdbc:postgresql://localhost/test</value> </property> <property name="username"> <value>postgres</value> </property> <property name="password"> <value></value> </property> </bean>
The problem with this solution is in hard maintenance of the applicationContext.xml file. For starters, imagine that you have your project in the source code version control system, such as CVS. Now let's say that you want to add new functionality to your website, and for that, you need to put some extra bean definitions in the application context definition. The problem is how to reflect those changes on the production server.
Usually your local instance of the application will not use the same database as the live site, so the applicationContext.xml file will contain settings to access your local database. When you want to commit your changes in the source repository, you have to take care of synchronization of these host-specific properties. The file in the repository will probably end up with configuration from your local settings. Now, when you want to update the configuration on the production server, you will have to manually synchronize the values of the properties. This can be a very tedious task, and is also very prone to errors.
With every instance of the application, this issue becomes more important. Imagine that three developers work on the code base and that they each use their local database. When you commit your changes, each of them must be very careful when updating source code on their local hosts. Their manual synchronization of your changes, followed by committing of their work, makes the version control system useless for these configuration files. If you've ever used Spring MVC, you know that applicationContext.xml is the crucial element of your application, since it is the glue that holds things together. Therefore, it is very important to find a mechanism that helps us keep things organized in our applications.
As we said earlier, this is the easier configuration problem that you can experience. The harder version of the problem is when you need to have different bean wirings on different hosts. Examples of this kind of problem are very easy to find in everyday software development tasks. For instance, imagine that you have a custom authentication module for your product that is able to authenticate users from relational databases or LDAP servers. Naturally, the authentication module could be configured with the bean that abstracts a certain repository. If you want to change how users are authenticated among different application deployments, you will need to make different bean wirings in your applicationContext.xml file. This kind of configuration issue could be seen in all applications that have configurable features among deployments.
In the rest of this article, we will focus on these two configuration issues. We will focus first on the problem of synchronizing bean properties and its solutions, and then move to the more complex issues of synchronizing bean wirings.