Saturday, September 27, 2008

Configuring applications with Spring

If you’ve used Spring before, you’ve almost definitely used a PropertyPlaceholderConfigurer to inject settings from external sources — most likely properties files — into your application context. The most common use cases include JDBC and Hibernate settings, but it’s not that uncommon to also configure Lucene index, temp file, or image cache directories as well. The simplest case looks something like this:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="classpath:application.properties"/>
</bean>   <!-- A sample bean that needs some settings. -->
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

And application.properties might look like this:

jdbc.driver=org.h2.Driver
jdbc.url=jdbc:h2:mem:example
jdbc.username=sa
jdbc.password=

Note, you can achieve the same simple configuration using the new spring 2.x style schema configuration, but it doesn’t allow for any further customization so we’re going to use the old style.

<!-- Example of new Spring 2.x style -->
<context:property-placeholder location="classpath:application.properties"/>

This handles the simple case of replacing placeholders (e.g. ${jdbc.url}) with values found in a properties files (e.g. jdbc.url=jdbc:h2:mem:example). In a real-world application, we not only need to collect settings, but also override them in different environments. Many of our applications are deployed in 4 or more environments (developer machine, build server, staging server, and production), each requiring different databases at the very least.

There are a few ways to enable overriding of properties. Let’s take a look at them in turn:

1. Setting the system properties mode to override (default is fallback)
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="location" value="classpath:application.properties"/>
</bean>

When configured in this mode, any value specified as a system property to the JVM will override any values set in properties files. For example, adding -Djdbc.url=jdbc:h2:mem:cheesewhiz to the JVM arguments would override the value in the file (jdbc:h2:mem:example). On a Java 1.5 or newer platform, Spring will also look for an environment variable called jdbc.url is no system property was found.

2. Specifying an optional properties file
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="locations">
        <list>
            <value>classpath:application.properties</value>
            <value>classpath:local.properties</value>
        </list>
    </property>
</bean>

When ignoreResourceNotFound is set to true, Spring will ignore resources that don’t exist. You can imagine application.properties, containing all of the default settings, versioned in your SCM system. Developers have the option of creating a properties file called local.properties to override any settings that differ in their environment. This file should be unversioned and ignored by your SCM system. This works because properties are loaded in order and replace previous values.

3. Web Application overrides

In a web application environment, Spring also supports specifying values in web.xml as context params or in your application server specific meta-data as servlet attributes. For example, if you’re using Tomcat you can specify one or more parameter elements in your context.xml, and Spring will can inject those values into placeholders.

<bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
    <property name="location" value="classpath:application.properties"/>
</bean>

The ServletContextPropertyPlaceholderConfigurer conveniently works in non servlet environments by falling back to the behavior of a PropertyPlaceholderConfigurer. This is great when running unit tests.

4. Combining techniques

There’s no reason why these techniques can’t be combined. Technique #1 is great for overriding a few values while #2 is better for overriding many. #3 just expands the field of view when Spring goes to resolve placeholders. When combined, system properties override those in files. When using technique #3, there are some settings available for adjusting the override behavior (see contextOverride). Test the resolution order when combining to ensure it’s behaving as expected.

Optional External Properties

There’s another use case that applies to some projects. Often in non-developer environments, system admins want to keep properties for the environment outside of the deployable archive or the application server, and they don’t want to deal with keeping those files in a Tomcat context file; they prefer a simple properties file. They also don’t want to have to place the file in a hard-coded location (e.g. /var/acmeapp/application.properties) or they may keep configuration for multiple servers in the same network directory, each file names after the server. With a little trickery, it’s easy to support an optional external properties file that isn’t in a hard-coded location. The location of the file is passed as a single system property to the JVM, for example: -Dconfig=file://var/acmeapp/server1.properties. Here’s the configuration to make it happen:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>   <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="location" value="${config}"/>
</bean>

The first definition enables basic property resolution through system properties (in fallback mode). The second bean loads the resource from the location resolved from the system property -Dconfig. All spring resource urls are supported, making this very flexible.

Putting it all together

Here’s a configuration that does more than most people would need, but allows for ultimate flexibility:

<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="ignoreUnresolvablePlaceholders" value="true"/>
</bean>   <bean class="org.springframework.web.context.support.ServletContextPropertyPlaceholderConfigurer">
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE"/>
    <property name="searchContextAttributes" value="true"/>
    <property name="contextOverride" value="true"/>
    <property name="ignoreResourceNotFound" value="true"/>
    <property name="locations">
        <list>
            <value>classpath:application.properties</value>
            <value>classpath:local.properties</value>
            <value>${config}</value>
        </list>
    </property>
</bean>

Every placeholder goes through the following resolution process. Once a value is found it’s set and the next placeholder is resolved:

  1. (optional) Property value specified as a system or environment property; useful for overriding specific placeholders (e.g. -Djdbc.host=devdb / -Djdbc.username=carbon5)
  2. (optional) Context parameters located in web.xml or context attributes specified in application server meta-data (e.g. a Tomcat context.xml).
  3. (optional) Properties file located by the system/environment variable called “config”; useful for externalizing configuration. All URL types are supported (e.g. -Dconfig=c://hmc.properties).
  4. (optional) Properties file identified by classpath:local.properties; useful for specific developer overrides.
  5. (required) Properties file identified by classpath:application.properties, which contains default settings for our application.
Best Practices
  • Deploy the same exact artifact (e.g. war, ear, etc) across all environments by externalizing configuration. This may seem daunting, but the emergent benefits are huge in terms of simplicity.
  • Only make things that can safely change across environments configurable. Also, only things that need to be configurable should be configurable, it’s easy to go overboard.
  • Configure the minimal properties search path that meets your requirements.
  • When looking for properties files in the project tree, use classpath resources whenever possible. This makes finding those files easy, consistent, and insensitive to the working-dir, which is great when running tests from your IDE and command line.
  • Aim for a zero-configuration check-out, build, run-tests cycle for the environment where its happens most: development.

What other interesting configuration scenarios have you seen?

by christian

Wednesday, September 10, 2008

Lazy loading vs. pre-loading beans with Spring Framework

Spring framework can instantiate and bind (called loading) related Java objects (called beans) according to a given configuration. An XML file can easily be used to define these bindings. Spring framework supports two different types of loading methods; lazy loading and pre-loading respectively managed by BeanFactory and ApplicationContext containers.

Lazy Loading

A bean is loaded only when an instance of that Java class is requested by any other method or a class. org.springframework.beans.factory.BeanFactory (and subclasses) container loads beans lazily. Following code snippet demonstrate lazy loading, concentrate on how "beans.xml" spring configuration file is loaded by BeanFactory container class.
BeanFactory factory = new XmlBeanFactory(
new InputStreamResource(
new FileInputStream("beans.xml"))); // 1
Employee emp = (Employee) factory.getBean("employeeBean"); // 2

Even though "beans.xml" configuration file is loaded with BeanFactory container in line number 1, none of the beans will be instantiated. Instantiation takes place only at line number 2, where bean called "employeeBean" is requested from container. Since the class is instantiated at getBean() method call, time spend to return this method will vary depending on the instantiated object.

Pre-loading

All beans are instantiated as soon as the spring configuration is loaded by a container. org.springframework.context.ApplicationContext container follows pre-loading methodology.
ApplicationContext context =
new ClassPathXmlApplicationContext("beans.xml"); // 1
Employee emp = (Employee) context.getBean("employeeBean"); // 2

As all singleton beans are instantiated by container at line number 1, this line will take some considerable time to complete. However line number 2 will return the bean instance immediately since instances are already available inside the container.

Point to note

Decision to choose one from these two methods would depend solely on application specific requirements. Some applications need to load as soon as possible while many others would probably willing to spend more time at startup but serve client requests faster. However some of the beans defined in a configuration may only be used rarely, so instantiating such classes at start up would not be a wise decision. Similarly, some Java instances would be highly resource consuming; leading not to instantiate at start up.

By Kamal Mettananda

Monday, September 8, 2008

Using Spring MVC Controllers in Grails

Groovy is slower than Java and sometimes dramatically slower. Realistically, this has little impact on a web application since response time is affected more by the database and network latency, so as long as the slowdown isn't too dramatic, the benefits of Groovy and Grails far outweigh these concerns. And Grails is still way faster than Rails :)

But having said that, I was wondering how to use a regular Java Spring MVC controller and JSP instead of a Grails controller and a GSP (both of which use Groovy). Turns out it's pretty easy:

  • Register the traditional Spring dispatcher servlet in web.xml (you'll need to have run grails install-templates). In this example the name (SpringMVC) isn't important, use whatever you want, and I've chosen to map *.action URLs to this controller and let Grails handle the rest:

<servlet>
<servlet-name>SpringMVC</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>SpringMVC</servlet-name>
<url-pattern>*.action</url-pattern>
</servlet-mapping>

  • Generate web-app/WEB-INF/SpringMVC-servlet.xml:

<?xml version='1.0' encoding='UTF-8'?>

<beans xmlns='http://www.springframework.org/schema/beans'
   xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
   xmlns:p='http://www.springframework.org/schema/p'
   xmlns:lang='http://www.springframework.org/schema/lang'
   xsi:schemaLocation='
      http://www.springframework.org/schema/beans
      http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
      http://www.springframework.org/schema/lang
      http://www.springframework.org/schema/lang/spring-lang-2.5.xsd'>

<bean id='mvcHandlerMapping'
class='org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping'
      p:order='1'>
<property name='interceptors'>
<list>
<ref bean='openSessionInViewInterceptor' />
<ref bean='localeChangeInterceptor' />
</list>
</property>
</bean>

<bean id='mvcViewResolver'
class='org.springframework.web.servlet.view.UrlBasedViewResolver'
      p:viewClass='org.springframework.web.servlet.view.InternalResourceView'
      p:order='1'
      p:prefix='/WEB-INF/jsp/'
      p:suffix='.jsp'
/>

<bean name='baseSimpleController' abstract='true' p:cacheSeconds='0'/>

<bean name='jspController'
class='com.foo.spring.controller.JspController'
parent='baseSimpleController'
abstract='true'
/>

<!-- actions -->

<bean name='/test.action'
class='com.foo.spring.controller.TestController'
parent='baseSimpleController'
      p:successView='test'
/>

<bean name='/other.action' parent='jspController' p:successView='other' />

</beans>

And that's it. Some notes:

  • the handler mapping uses the id mvcHandlerMapping since Grails will create one using the standard name of handlerMapping
  • since handler mappings are auto-discovered by default, you need to set the order attribute to something lower than the Grails mapping's (which uses the default value of Integer.MAX_VALUE) so this mapping is accessed first
  • the HandlerInterceptors that are configured for the Grails mapping (OpenSessionInView, LocaleChange) won't be automatically available to this mapping, but it's simple to borrow them since they're registered as beans; you can also add other custom interceptors to the list
  • I've created an optional abstract parent controller bean (baseSimpleController) for simple controllers (single-page, i.e. not form or wizard controllers)
  • I've also created a simple controller that just shows a JSP – this is useful for pages that don't have any controller logic:

    package com.foo.spring.controller;

    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;

    import org.springframework.web.servlet.ModelAndView;
    import org.springframework.web.servlet.mvc.AbstractController;

    public class JspController extends AbstractController {

    private String _successView;

       @Override
    protected ModelAndView handleRequestInternal(
    final HttpServletRequest request,
    final HttpServletResponse response) {

    return new ModelAndView(_successView);
    }

    public void setSuccessView(final String view) {
          _successView = view;
    }
    }

I've mapped two sample URLs – /test.action, which uses a controller, and /other.action, which uses JspController to just show other.jsp.

Note that it is possible to use JSPs with Grails; Grails looks for a GSP using the specified name, but if it doesn't find one it looks for a JSP (under /WEB-INF/grails-app/views/) and uses that if it exists. So another option is to use Grails controllers and JSP.

Big caveat: I haven't used this in production yet – I'm just prototyping so I'll have this available in the future just in case.

original post

Tuesday, September 2, 2008

RESTful URLs with Spring MVC and UrlRewriteFilter

While Spring 3.0 promises to support REST style URLs out of the box, it won’t ship until sometime later this year. Spring 3.0 M1 will offer this functionality for anyone brave enough to work with potentially unstable technologies and should be available soon. And while this is good news for those starting out on new projects (or those willing to undergo a significant refactoring), most won’t want to migrate their applications just for RESTful URLs. All hope is not lost though, thanks to Paul Tuckey’s UrlRewriteFilter.

With this short tutorial, I’ll demonstrate how easy it is to configure UrlRewriteFilter for use within your Spring MVC application. I should mention that this technique will work well for just about any Java-based web framework, like JSF or Struts.

For those of you that want to skip to the end, I’ve created a small, functional sample application which demonstrates the techniques described in this tutorial. It can be downloaded here.

Getting started, we need to register the filter within our application’s web.xml file.

web.xml

Code:

    <!-- UrlRewriteFilter -->
    <filter>
        <filter-name>UrlRewriteFilter</filter-name>
        <filter-class>
            org.tuckey.web.filters.urlrewrite.UrlRewriteFilter
        </filter-class>
        <init-param>
            <param-name>logLevel</param-name>
            <param-value>WARN</param-value>
        </init-param>
    </filter>

    <!-- UrlRewriteFilter Mapping -->
    <filter-mapping>
        <filter-name>UrlRewriteFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>

That out of the way, we can dig into the application itself. Let’s review an example controller class as it might exist in your application today.

SprocketsController.java

Code:

@Controller
public class SprocketsController {

    private final SprocketService service;

    @Autowired
    public SprocketsController(SprocketService service) {
        this.service = service;
    }

    @RequestMapping("/sprockets/list.do")
    public String list(ModelMap model) {
        model.addAttribute("sprockets", service.list());
        return "sprocket/list";
    }

    @RequestMapping("/sprocket/display.do")
    public String display(@RequestParam("sprocketId") int sprocketId, ModelMap model) {
        model.addAttribute("sprocket", service.find(sprocketId));
        return "sprocket/display";
    }

    @RequestMapping("/sprocket/edit.do")
    public String edit(@RequestParam("sprocketId") int sprocketId, ModelMap model) {
        model.addAttribute("sprocket", service.find(sprocketId));
        return "sprocket/edit";
    }
}

Our controller contains actions for displaying a list of sprockets, drilling down into each sprocket’s details and editing an individual sprocket. Each action is mapped to a URI path via the @RequestMapping annotation and, as you can see, all three defined here handle requests mapped to the *.do extension. The beauty of the solution I’m demonstrating here is that you should not need to make any changes to your application code at all. That in mind, let’s move on to the interesting part, configuring our application to respond to a REST style URL like http://localhost:8080/sprocket/1234/edit instead of what we’ve got now: http://localhost:8080/sprocket/edit.do?sprocketId=1234. You’ll need to create a new configuration file named urlrewrite.xml and make it available on the classpath. (For those with a distaste for XML based configuration, the latest version of the filter offers a means to generate the configuration via annotations. Details on that can be found here.) We’ll start our configuration by defining a few rules to handle the incoming requests.

urlrewrite.xml

Code:

    <rule>
        <from>^/sprockets/$</from>
        <to>/sprockets/list.do</to>
    </rule>
    <rule>
        <from>^/sprocket/([a-z0-9]+)/$</from>
        <to>/sprocket/display.do?sprocketId=$1</to>
    </rule>
    <rule>
        <from>^/sprocket/([a-z0-9]+)/edit$</from>
        <to>/sprocket/edit.do?sprocketId=$1</to>
    </rule>

Let’s take a look at what each one of these rules does. The first rule states that the UrlRewriteFilter should transparently forward each request for http://localhost:8080/sprockets/ to the existing application URL of http://localhost:8080/sprockets/list.do. The second and third rules handle the display and edit requests. These 2 rules define simple regular expressions that are parsed out and appended to the destination URI as query string parameters. If you have more than 1 query string parameter, you’ll need to use & XML entity. (It should be noted that you can use wildcard matching (*) instead, however it lacks some of the flexibility offered by regular expressions.)

That takes care of the inbound URLs, but we still have a problem. Within our application, we have a number of links which point to the old URL structure. No worries, UrlRewriteFilter tackles this issue with ease. By examining the response, the filter can rewrite the existing links defined within anchor tags, i.e. <a href=”<c:url value=’/sprockets/list.do’/>”>Return to the list.</a>. Let’s take a look at the rule definitions to handle this.

urlrewrite.xml

Code:

    <outbound-rule>
        <from>^/sprockets/list.do$</from>
        <to>/sprockets/</to>
    </outbound-rule>
    <outbound-rule>
        <from>^/sprocket/display.do\?sprocketId=([a-z0-9]+)$</from>
        <to>/sprocket/$1/</to>
    </outbound-rule>
    <outbound-rule>
        <from>^/sprocket/edit.do\?sprocketId=([a-z0-9]+)$</from>
        <to>/sprocket/$1/edit</to>
    </outbound-rule>

More or less, these outbound rules are just the inverse of the inbound rule definitions. All it takes is a simple regular expression to parse out the sprocketId. One common gotcha to note here is that you need to add the \ character before the start of the query string marked by the question mark. If you don’t do this, the filter won’t be able to process your links.

Pretty easy, right? With your rules in place, fire up your application and give it a try. You can always examine the status of the filter by visiting http://127.0.0.1:8080/rewrite-status. If you’re a bit hesitant to try this out on your own app, fret not, I’ve created a simple, yet functional sample application which you can use to experiment with. The example source code can be downloaded here.

by Carl Sziebert