Skip to main content

Single Spring Application Deployment for both Local and CloudFoundry.com Servers

In my previous post I showed how it’s possible, using Spring 3.0, to deploy a database application to CloudFoundry.com and what changes are needed for a CloudFoundry.com datasource.  In this post, I’m going to show how a Spring 3.1 application can be configured at runtime to use either a local MySQL database or a CloudFoundry.com MySQL database thus allowing a single deployable Spring application to be deployed either locally or on CloudFoundry.com.

Deploying a Spring application to CloudFoundry.com does not mandate the use of Spring 3.1, however Spring 3.1 makes the process much easier due to the new profile features. So, first off, we must upgrade to Spring 3.1

Upgrading to Spring 3.1
To upgrade a Spring STS application to use Spring 3.1 is an easy procedure. In the project’s pom.xml file, we first need to change the version number of Spring to 3.1.0.M1. I say it’s easy with a STS application as everything else (for example, Spring’s Milestone Maven repository) is already preconfigured in the pom.xml file.

<properties>
  <org.springframework-version>3.1.0.M1</org.springframework-version>
</properties>

If you’re not using Maven, you can download Spring 3.1 M1 from the Community Download page.

Having upgraded the version in Maven, we need to change the namespaces for any application context files. This is as straightforward as changing schema locations to be xxx-3.1.xsd instead of xxx-3.0.xsd

<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:mvc="http://www.springframework.org/schema/mvc"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
  http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
  http://www.springframework.org/schema/mvc
  http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd   
  http://www.springframework.org/schema/context
  http://www.springframework.org/schema/context/spring-context-3.1.xsd">

Upgrading to Spring 3.1.M1 will unfortunately have some side effects within STS. After upgrading, you may see that some lines within application context files are flagged with errors such as:

Error occured processing XML 'org/springframework/core/convert/support/ArrayToCollectionConverter'. See Error Log for more details

This is because STS (v2.6) does not currently fully support Spring 3.1 due to some API changes in 3.1.  Support for Spring 3.1 can be tracked on SpringSource’s Jira issue #1655.

Configuring Bean Definition Profiles
After configuring an application to use Spring 3.1, we can start using the new profiles feature to specify both a cloud datasource and a local datasource.

<beans xmlns=http://www.springframework.org/schema/beans …
 
  <beans profile="default">
    <bean id="dataSource"
      class="org.springframework.jdbc.datasource.DriverManagerDataSource"
      p:driverClassName="${jdbc.driverClassName}"
      p:url="${jdbc.url}" />
  </beans>
  <beans profile="cloud">
    <cloud:data-source id="dataSource" />
  </beans>
</beans>

In this XML fragment, we can see that there are embedded <beans /> elements inside the main <beans /> element.  This is a new feature of Spring 3.1 that allows different configurations to be easily specified within one configuration file. Here we’ve defined a bean called dataSource as a JDBC datasource and as a CloudFoundry.com datasource.  The profile attribute allows us to specify which profile the bean is to be instantiated in.  So, in the "default" profile, i.e. a local profile where development and testing is most likely to be performed, a JDBC datasource is defined.  The “cloud” profile specifies a datasource for CloudFoundry.com.  A bean profile can be set to cover multiple profiles, but in this example, the dataSource bean is either a local JDBC datasource or a CloudFoundry.com datasource and can never be defined in both cases.

For a detailed description of Spring’s bean definition profiles, check out Chris Beams blog post.

Choosing a Profile at Runtime
The final stage of changing an application to use the bean definition profiles defined above is to add a class that implements the org.springframework.context.ApplicationContextInitializer interface.  This interface allows the spring container to be customised before it in initialized. In our instance, we can hook into this and, depending on the environment, set the active profile to be the "default", local JDBC datasource, or the "cloud" CloudFoundry.com datasource.

public class Initializer implements
     
  ApplicationContextInitializer<ConfigurableWebApplicationContext> {
 
  protected final Log logger = LogFactory.getLog(getClass());
 
  public void initialize(ConfigurableWebApplicationContext ctx) {
    ConfigurableEnvironment environment = ctx.getEnvironment();
 
    ApplicationInstanceInfo instanceInfo = new CloudEnvironment()
      .getInstanceInfo();
 
    if (instanceInfo == null) {
      // We are running locally.
      logger.info("Setting default profile.");
      environment.setActiveProfiles("default");
    } else {
      // We are running in the cloud.
      logger.info("Setting cloud profile.");
      environment.setActiveProfiles("cloud");
    }
  }
}

In this class, we attempt to get the instanceInfo of the CloudEnvironment class.  If this returns null, the application is not running on CloudFoundry.com and the local “default” bean definition profile is set as the active profile.  If, however, a valid instance is returned, then the app is running on CloudFoundry.com and the "cloud" bean definition profile is set as the active profile.

That’s all there is to it and now the application can be developed and deployed as easily locally as it can on CloudFoundry.com

The sample code used in this post can be found on GitHib at https://github.com/daveys/spring-todo

Comments

Popular posts from this blog

A Simple Makefile for a GTK/GTKMM Project

When compiling small applications, its fairly easy just to compile using g++ from the command line. If you’re compiling anything more complex than a single file, its probably easier to use a Makefile. This example Makefile demonstrates how to compile an application that uses the GTKMM library. NAME=my-app CFLAGS=-g -Wall -o $(NAME) GTKFLAGS=`pkg-config --cflags --libs gtkmm-3.0` SRCS=main.cc myapp.cc CC=g++ # Do all all: main # Compile main: $(SRCS) $(CC) $(CFLAGS) $(SRCS) $(GTKFLAGS) # Clean clean: rm -f $(NAME) rm -f *.h~ rm -f *.cc~ rm -f Makefile~ rm -f *.glade~

Changing Default Search Provider in Firefox on Linux Mint

On Linux Mint, the default version of Firefox is installed and configured to allow the following search engines to be queried directly from the address bar: Yahoo! Startpage DuckDuckGo Wikipedia Mint defines these as the default available set of search engines based upon 3 criteria (funding to Linux Mint, privacy support and whether the search engine is non-commercial). Other search engines such as Google, Bing or Twitter, etc. can easily be added into the default version of Firefox however. To add a different search provider, browse to Search Engines At the bottom of the page, click on the icon of the requested search engine, then click on the ... button in the URL bar and select the Add Search Engine option. You then have the option to change the default search engine within Firefox preferences to your new choice.

Eclipse releases Ganymede

The Eclipse Foundation has  released  Ganymede, the latest annual release this time containing 23 Eclipse projects including the Eclipse IDE version 3.4. This latest version of the annual Eclipse release contains many new features including: Equinox P2  - a system to make installations and updated to Eclipse easier JSDT  - A new JavaScript editor Improved JavaScript support for the Business Intelligence and Reporting Tools,  BIRT Graphical database query tools Improved support for Java EE 5 SOA support and many other features. Further information, inclusing webinars and demos can be found on the  project website  . This new release can be downloaded from the  Eclipse web site  .