MemeStorm

Exploring the Spring Framework and Application Development

Loading resources from files or the classpath

Posted in All by Jon on the February 19th, 2006

You want to load resources from the file system or classpath from
within beans initialized by a Spring context.

Background

Our HSQLDB utility class needs to load the SQL to create the database every time our application starts, as outlined in a Embedded Database Starting Up With Web Context. How does this bean get access to the file? Well, in the context configuration we supplied a file location, for example:

<bean id="databaseUtils" class="com.memestorm.utils.db.HSQLDB">
  <property name="location“>
    <value>/db/init.sql</value>
  </property>
</bean>

So, how can we actually get to the file?

How to do it

The easiest way is to have your bean implement the ResourceLoaderAware interface. This will then ensure that the setResourceLoader(ResourceLoader resourceLoader) method will get called on your bean, with a magic resource loader. (Look here for more information on the aware interfaces.)

The ResourceLoader
class is a fantastic utility class provided by Spring, that allows you
to load resources from all sorts of locations. Given the location above, the resource loader will look for the file db/init.sql relative to the root of the web application (when used from a web context). Our bean simply uses the location as follows:

Resource sql = this.resourceLoader.getResource(this.location);
JdbcTemplate jt = new JdbcTemplate(this.dataSource);
jt.execute(IOUtils.toString(sql.getInputStream()));

It’s so simply it belies how easy this makes life! To load from an arbitrary file location, use the file: prefix instead. For example, file:///temp/foobar.sql. You can also try and locate something in the classpath using the classpath prefix. For example, classpath:config.xml.

Have fun.


Print This Post Print This Post

Use Spring’s bean lifecycle callback methods to control your destiny

Posted in All by Jon on the February 19th, 2006

You want to run an initialize or destroy method on a bean after the context creates it. These lifecycle methods allow you to grab and release resources.

How to do it

Well, we did this in the previous blog entry, making use of an ApplicationListener and InitializingBean. This was overkill! There’s a better way that doesn’t require these interfaces. To have a method execute after the bean is initialized, or just before it’s destroyed (ie. at context start up or shutdown), simply modify your configuration file as follows:

<bean id="databaseUtils" class="com.memestorm.utils.db.HSQLDB"
  init-method=”initialize” destroy-method=”destroy”>
</bean>

You can of course omit either one, or both, of these attributes. The values of the attributes indicate the method that should be invoked. So for example, given the above definition the initialize() and destroy() method of the HSQLDB object will be invoked. This is great, and avoids any dependence on Spring interfaces.

If you’d like the same functionality relying on interfaces instead, then simply have the class implement InitializingBean and DisposableBean instead. In this case the configuration file will not have a init-method or destory-method attribute.


Print This Post Print This Post

Embedded Database Starting Up With Web Context

Posted in All by Jon on the February 17th, 2006

We want to introduce a database into our sample application, in an
unobtrusive way requiring little in the way of configuration. We’ll do this with an all-Java in-memory database, and along the way learn a little about Aware interfaces, and running methods on context startup or shutdown. The result is a deployed WAR that has an in-built database.

Background

I was thinking about how to introduce databases without requiring you lot to do a lot of downloads, installation and configuration. Then it came to me - an in-memory database would be great. The full Spring distribution comes with HSQLDB, which is what we’ve used below. We’ve also got this working with Apache Derby.

Because we’ve opted for in-memory, and non-persistence, we have to essentially create the database and the tables every time we start up our application. This takes no time at all, but does force us to look a little at how a configuration context starts up and shuts down.

How to do it: Configuration

We’ll walk through the configuration by looking at the changes made to skeleton1, introduced in Basic Spring Web MVC Example.

First, let’s look at changes to our build.xml. The only thing you’ll notice is the addition of several libraries:

<include name="hsqldb.jar" />
<include name="commons-dbcp.jar" />
<include name="commons-pool.jar" />
<include name="commons-io.jar" />

The first is the database engine itself, the next two are for interfacing to the database, and the last is simply a utility library that we use later.

Now the way you typically integrate a database with a Spring application, is to introduce a data source bean. Data sources are the bridge between your application and the database. Even though you may use different database implementations, the data source will hide the details. Here’s our implementation:

<bean id="dataSource"
class="org.apache.commons.dbcp.BasicDataSource“>
<property name=”driverClassName”>
<value>${jdbc.driverClassName}</value>
</property>
<property name=”url”>
<value>${jdbc.url}</value>
</property>
</bean>

You’ll note we’ve externalized (see Parameterizing Spring’s Configuration Files, and BeanFactoryPostProcessors) the name of the database driver and URL used for connecting to the database. You’ll find them in jdbc.properties:

jdbc.driverClassName=org.hsqldb.jdbcDriver
jdbc.url=jdbc:hsqldb:mem:exampledb

The bean dataSource is an instance of BasicDataSource supplied by the DBCP library, which in turn implements the necessary interface, javax.sql.DataSource. Any interface with a database generally needs a bean that implements this interface. The DBCP version, which we’ve used, creates a data source by wrapping the necessary functionality around a database driver, which you can see we’ve supplied as a parameter. DBCP can add additional functionality such as connection pooling, which we’ll see in a later story.

This is pretty much standard - the details of what kind of data source to create, and which database driver to use, will vary - but the intent will remain no matter what db you connect to.

The database we’re using has a special driver class - normally a driver class allows you to connect to a running database. This driver class allows the same, but it also starts the database! So this database runs in the same VM as your code.

How to do it: Using the database

At this point (ignoring creating tables), we’re ready to use our database. Typically you would do this by making sure some data access objects have access to the data source. We’re not there yet. Instead, we’re going to make sure our controller has access to the data source. In that way we can add another handler method, which will in turn query the database:

<bean id="dispatchController"
class="com.memestorm.web.DispatchController">
<property name="dataSource"><ref bean="dataSource“/></property>
</bean>

As you can see, we simply pass in the data source bean defined above. We’ve added an additional method to our dispatch controller too:

public ModelAndView listFromDB(HttpServletRequest request,
HttpServletResponse response) throws Exception {
JdbcTemplate jt;
jt = new JdbcTemplate(this.dataSource);
jt.update(”insert into myTable values (’jon’,31)”);
List rows = jt.queryForList(”select * from myTable”);
ModelAndView mav = new ModelAndView(”listview”);
mav.addObject(”rows”, rows);
return mav;
}

Spring provides a really nice templating approach to interfacing with a database, which we’ll describe in a later story. You should be able to figure it out though. You use the data source to construct a JdbcTemplate object, and then use this to execute SQL. In this case, we execute an SQL update - inserting a row into the database. We then perform a query (an SQL select), and pass the results to our view (listview). What does the view look like?

<body>
Here are the results from the database:<br />
<%= request.getAttribute("rows") %>
</body>

It simply prints out the result! So, if we invoke our handler method:

http://localhost:8080/skeleton2/send/listFromDB

twice, then we’ll see this as output:

Here are the results from the database:
[{NAME=jon,AGE=31},{NAME=jon,AGE=31}]

Neat.

How to do it: Setting up the database

As mentioned, we start up with a clean database every time the web application is deployed. We also want to shut the database down nicely when we shut the application down. You’ll be astounded how easy this is. We’ll simply define one more bean:

<!--  can be used to initialize and shutdown the database instance -->
<bean id="databaseUtils" class="com.memestorm.utils.db.HSQLDB">
<property name="dataSource">
<ref local="dataSource" />
</property>
<property name="location">
<value>${db.sql.init}</value>
</property>
</bean>

That’s it! That’s pretty unobtrusive. The magic happens in HSQLDB (note how we pass it the data source, and a file location). Let’s explore this class:

public class HSQLDB  implements ApplicationListener … {
…
}

The first thing to note is that it implements ApplicationListener. Any bean that you register in the configuration context which implements this interface will automatically get sent important lifecycle events. All you have to do is then implement an onApplicationEvent() method. Here is our implementation:

public void onApplicationEvent(ApplicationEvent event) {
if (event instanceof ContextClosedEvent) {
shutdownDB();
}
}

We wait for a particular event, and when we get it, invoke shutdown. Simple! So in contrast, how do we do something when the context starts up? Well, we implement another interface:

public class HSQLDB  implements InitializingBean, ApplicationListener … {
…
}

What happens then is that when the context is initialized, and all properties are set, the context will invoke the afterPropertiesSet() method on all beans that implement the interface. How simple is that? Here is what we do:

public void afterPropertiesSet() throws Exception {
Resource sql = new ServletContextResource(this.servletContext, getLocation());
JdbcTemplate jt = new JdbcTemplate(this.dataSource);
jt.execute(IOUtils.toString(sql.getInputStream()));
}

As you can see, we simply grab the file given by the location variable, grab its contents, and execute it as SQL. Our file contains the following:

create table myTable (name varchar(40), age int);

You’ll notice that to grab the file at the location (which is relative to the root of the web application), we actually need the servlet context. So how can any bean get access to the servlet context in which it is running? Well, again, you just implement an interface!

public class HSQLDB  implements InitializingBean, ApplicationListener
ServletContextAware {
…
}

If you do this, Spring will again automatically invoke the setServletContext(ServletContext servletContext) on your bean, passing you the context which you can store. Neat hey? That’s it!

Recap

We’ve covered quite a bit here, so let’s recap:

  • Implementing ServletContextAware, one of the “Aware” interfaces, will result in the context telling your bean what the servlet context is. This is a service provided by any web application context
  • Implementing ApplicationListener allows you to listen to context life cycle events. Another interesting event is ContextRefreshedEvent and RequestHandledEvent
  • Implementing InitializingBean allows our beans to do somem work after all their properties have been set by the Bean Factory.

Additional Material

Our sample does just a little more than this. Instead of mixing in our database configuration with our dispatch configuration (dispatch-servlet.xml), we’ve put them in a separate file, jdbcContext.xml. To load this, we’ve introduced a new configuration to our dispatcher servlet (in web.xml):

<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/applicationContext.xml  /WEB-INF/jdbcContext.xml
</param-value>
</context-param>

This does what it says on the tin - it loads a number of configurations from a “space separated” list of files. In this way you can keep a number of configuration files, keeping them all neat and tidy.

Download

It’s been a long journey, but hopefully a rewarding one. You’re probably keen to download the code and build your own WAR. Here it is:

skeleton2.zip


Print This Post Print This Post

Simple URL mapping and factory beans in Spring

Posted in All by Jon on the February 16th, 2006

As explained in Basic Spring Web MVC Example and Basic Web MVC Example - In Pictures, Spring’s dispatcher servlet uses a URL mapper to map requests that come into the dispatcher servlet to appropriate handlers. Indeed, the example application used a ’simple URL mapper’ that mapped all requests to the same handler. Despite its name, this is one of the better handlers, so in this entry we will explore how to configure the URL handler. Along the way we’ll learn about factory beans, and the PropertiesFactoryBean in particular.

Background

Our sample skeleton1 application had the following hander mapping:

<bean id="urlMapping"
      class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
 <property name="mappings">
  <props>
  <prop key="/*">dispatchController</prop>
  </props>
 </property>
</bean>

As explained in the blog entries above, this maps all incoming requests to the same handler, dispatchController. In fact, Spring’s handler infrastructure is pretty flexible, allowing you great control over what gets mapped where. Even when. Yes, when. You can, for example, define handler interceptors - perhaps you’ll only allow URL’s to go through to a particular handler when the user is authenticated for example, or if the moon is full. We’ll examine those in a later show. Now, however, let’s look at ways to configure the URL mapper.

How to do it

They easiest way to get started is to use the SimpleUrlHandlerMapping class and a property listing the mapping. As the name suggests, this handler lets you map simple URLs to handlers. In fact, the URLs aren’t that simple. They can be “Ant-style pattern matches” - for example /f* will match /foo and /flumoxed, /menu/* matches anything in the /menu/ directory (for example, /menu/foo but not /menu/foo/bar), and /menu/** matches any kind of URL that starts with /menu/, including /menu/foo/bar. Here’s a simple set of mappings:

<property name="mappings“>
  <props>
    <prop key=”/bar/*”>dispatchController</prop>
    <prop key=”/fum/**”>someOtherDispatchController</prop>
  </props>
</property>

As have probably figured out, the SimpleUrlHandlerMapping class has a setMappings(Properties p) method that allows you to configure it. It also has setUrlMap(Map urls) method, which allows for a more bean-like approach:

<property name="urlMap“>
<map>
  <entry key=”/bar/*”><ref local=”dispatchController”/></entry>
  <entry key=”/fum/**”><ref local=”dispatchController2″/></entry>
</map>
</property>

Here we’re obviously referring to the dispatchController bean, which we will have defined in the context configuration file. It’s slightly more verbose than the previous listing, but some folk like this stronger notion of bean references.

One final approach is to place the mapping in an external file—we prefer this approach. For example, create a properties files mapping.properties and put it in /WEB-INF/. It can look like this:

/foo/*=dispatchController
/bar/*=dispatchController2

Then, modify your dispatch-servlet.xml like this:

<bean id="mappedProperties”
      class=”org.springframework.beans.factory.config.PropertiesFactoryBean”>
  <property name=”location”>
     <value>/WEB-INF/mapping.properties</value>
  </property>
</bean>

<bean id=”urlMapping”
      class=”org.springframework.web.servlet.handler.SimpleUrlHandlerMapping”>
  <property name=”mappings”><ref local=”mappedProperties“/></property>
</bean>

That’s it. Note that the urlMapping bean now takes its mapping from a referenced property, mappedProperties, and this bean, instead of listing out each property individually, instead utilizes PropertiesFactoryBean to populate the properties from the referenced file.

Advanced

You may be scratching your head at this stage saying, “okay, I can see that it works, and I know how to use it, but how does it work?” How indeed. PropertiesFactoryBean does not implement the Properties interface, so how could this possibly substitute as something of type Properties?

It turns out that PropertiesFactoryBean is a Factory Bean - it is a bean that generates beans. In this case, its a bean that generates other beans of type Properties. Let’s see how it works by looking at its definition:

public class PropertiesFactoryBean extends PropertiesLoaderSupport
           implements FactoryBean, InitializingBean {
 …
 Object getObject() { return this.singletonInstance; }
 Class getObjectType() { return Properties.class; }
 boolean isSingleton() { return true; }
 …
}

I’ve highlighted the methods it has to implement because it’s a FactoryBean. isSingleton() provides us with a little control over object creation. When I generate a bean, should I make a new instance every time (prototype), or simply use one I created earlier (singleton). getObject() returns the actual object, in this case a Properties object that’s been populated from the file. getObjectType() returns the type of the object that we’re generating. So how does all this work?

It turns out that deep in the bowels of Spring’s IoC container, you have a getBean() method - which returns a bean instance given its name. [This is called when you have something like this for example: . This forces Spring’s container to go look for a bean called beanname, which eventually calls getBean().]

This eventually calls down into another method (getObjectForSharedInstance()) which retrieves the bean (say from the context of beans that you created), and examines it to see if its a factory instead of a normal bean. If it’s a ‘normal’ bean, it simply returns the instance. If it’s a factory bean, it instead asks the factory to generate an instance to return. See:

beanInstance = /* some instance from the list of beans we've configured */
if (beanInstance instanceof FactoryBean) {
  // Return bean instance from factory.
  FactoryBean factory = (FactoryBean) beanInstance;
  beanInstance = factory.getObject();
}
return beanInstance;

As you can see, it’s pretty straightforward. If we are trying to grab an ordinary bean, we simply return the instance that we’ve found. If, however, it’s a factory bean, we ask the factory to generate the instance that we return. Voila!

This FactoryBean mojo is used all over Spring - for example, especially where Spring has to bridge to another technology. The code that does the bridging can be stuffed in a factory bean, and it in turn can generate beans of the required type when called to do so. We’ll encounter it many times in the future, so read this again if you didn’t get it all the first time!


Print This Post Print This Post « Previous PageNext Page »