Simple URL mapping and factory beans in Spring
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
Parameterizing Spring’s Configuration Files, and BeanFactoryPostProcessors
You have a few Spring context configuration files, say dispatch-servlet.xml as in the Basic Spring Web MVC Example, and you want to avoid hardcoding property values. Instead of embedding them in the XML files, you want to place them in a simple property file, making life much easier for folk who use and deploy your application. In what follows, we’ll show you how to do this, and explain how it works by diving into the IoC container.
How to do it
Say for example you are configuring a data source bean. You know that its configuration is dependent on a JDBC driver’s classname, and you know that this classname will differ, depending on what your client uses. So it makes sense to put it in an external property file. So, for the value of the property, insert a property placeholder instead:
class=”org.springframework.jdbc.datasource.DriverManagerDataSource”>
Now create a property file that defines the value, for example here is our jdbc.properties file:
jdbc.driverClassName=com.memestorm.JDBCDriver other.properies=othervalues
Now the only thing left is to somehow tell the context configuration file to substitute the property placeholders with the values defined in the property file. You do that by adding the following to your context configuration file (for example dispatch-servlet.xml):
class=”org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”>
That’s it. It doesn’t matter if you put this before or after the definition of the dataSource bean for example, it will still work. Spring will magically read the configuration file and substitue the values in the beans that you define.
How it works
We’re not going to explain how the
PropertyPlaceholderConfigurer reads the configuration
file, parses out the properties, and applies them. Instead, we’re
going to tell you how it gets activated at all and how it gets access to
your beans.
The key is that PropertyPlaceholderConfigurer
implements a special interface,
BeanFactoryPostProcessor,
which has a single method:
void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory)
throws BeansException;
The next key is that any application context (such as the servlet web
application context, or a root application context that you may
define), after it has read the configuration, looks through all the beans for any that
implement the BeanFactoryPostProcessor interface. That’s
right, it automatically checks all the beans that are defined, looking
for those that implement BeanFactoryPostProcessor. It
then invokes the postProcessBeanFactory() method on those
beans. [Aside:This kind of processing doesn’t happen in a BeanFactory - this is what distinguishes a BeanFactory from a Context]
You should now have an idea of what happens: Spring’s core IoC
system (let’s call it AbstractApplicationContext) loads
the context configuration file, it searches for beans implementing
BeanFactoryPostProcessor and will find our property
configurer, as PropertyPlaceholderConfigurer implements
this interface. The application context then runs the postProcessBeanFactory() method in all appropriate beans; in our case this means that thePropertyPlaceholderConfigurer bean (well, actually a
subclass but no matter) then loads the properties from the configured
location. Since this method gets passed the list of parsed beans in the configuration file (see the beanFactory parameter), it can then operate on them, substituting the place holders with the appropriate values. After the AbstractApplicationContext has run all the BeanFactoryPostProcessors, it continues with its job of setting up the context. Here’s a snippet from the internals:
// Invoke factory processors registered as beans in the context. invokeBeanFactoryPostProcessors(); // Register bean processors that intercept bean creation. registerBeanPostProcessors(); // Initialize message source for this context. initMessageSource(); // Initialize event multicaster for this context. initApplicationEventMulticaster(); // Initialize other special beans in specific context subclasses. onRefresh(); // Check for listener beans and register them. registerListeners(); // Instantiate singletons this late to allow them to access the message source. beanFactory.preInstantiateSingletons(); // Last step: publish corresponding event. publishEvent(new ContextRefreshedEvent(this));
As you can see, the bean factory processors are run first, before the rest of the magic happens (including instantiating singleton beans).
Neat hey!
Advanced
You can write your own bean factory processors quite easily. Perhaps, as suggested in Spring’s documentation, you can use it to unencrypt/encrypt some bean values. Simply make sure it implements the appropriate interface and it will then run as explained before. (In fact, you can even apply some order to them). Here’s a simple example. Just reference this bean from your context:
package com.memestorm;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
public class MyPostProcessor implements BeanFactoryPostProcessor {
Log logger = LogFactory.getLog(getClass());
public void postProcessBeanFactory(
ConfigurableListableBeanFactory beanFactory) throws BeansException {
logger.info("In postProcessBeanFactory. The following beans are available:");
String [] n = beanFactory.getBeanDefinitionNames();
for (int i=0; i < n.length; i++) {
logger.info("Bean = " + n[i]);
}
}
}
Print This Post
Basic Web MVC Example - In Pictures
It seems that some of you would like a graphical depiction of what’s going on in the Basic Spring Web MVC Example. Here it is:

Here’s a summary, though I urge you to read the original blog entry and view the source for more details:
- A request comes in from the web cloud and your web container, Tomcat say, will examine its configuration
web.xmlto determine what to do with it. - Here we’ve assumed that
web.xmlwas configured to map to a dispatcher servlet (in the example, it mapped/send/*requests. There can be any number of dispatcher servlets configured. - Once a dispatcher servlet receives a request, it needs to know which controller to send it to. It does this with a URL mapper. The URL mapper will typically send a request to one of many configured controllers. In our example, we mapped everything (
/*) that arrives at the dispatch servlet to a singledispatchController. - Incoming requests at a controller actually need to invoke a method on the controller. We’re using a
MultiActionControllerin our example, and this uses aMethodNameResolverto determine which method to invoke. The default resolver simply takes what’s to the right of the last “/” in the incoming URL. - Once the action has executed, the result has to be sent to a view. Which view, is determined by a
ViewResolver. In our example, we used aInternalResourceViewResolverwith a configuration such that given a view name of “foo“, will look for a JSP file “foo.jsp“. - The view is rendered.
As you can tell, everything is very flexible. We can configure which dispatcher servlets are invoked when, we can configure which controller is invoked, we can configure which methods on the controller are invoked, and we can configure how the view is selected. What’s more, we can use all of the defaults to get a pretty flexible application up and running in no time.
Print This Post
Basic Spring Web MVC Example
You want to get started with a simple web application that utilizes Spring’s web MVC framework. Here’s a simple project that provides such a start. It doesn’t use all of Spring’s features, nor even the best, but it will serve as a discussion point for future blog entries.
Background
When you’re putting together a simple web application, you need a few essentials:
- A dispatcher servlet, which will intercept incoming requests.
- A configuration that instructs the web container to route requests to the dispatcher servlet (ie. a servlet mapping)
- Controllers (the C in MVC) that can perform the business logic and route to particular views (the V) perhaps conveying information models (the M).
- A way for the dispatcher servlet to know which URLs to map to which controllers - called a url mapping
- A way to determine, when a controller has done its job, how to get to the view - called a view resolver
The simple application here, skeleton1, doesn’t have a model at all, has a single controller (web.DispatchController), and a single view (myview.jsp)
How to do it and How it works
Download the source for the details. First, we want to use Spring’s DispatcherServlet as the entry point to our web application. You configure this simply in your web.xml:
<servlet> <servlet-name>dispatch</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> <servlet> <servlet-mapping> <servlet-name>dispatch</servlet-name> <url-pattern>/send/*</url-pattern> </servlet-mapping>
Get it? This says: Create the servlet for me, call it dispatch, and map all incoming URLs that start with send to the dispatch servlet. So for example, a URL such as http://.../skeleton1/send/foobar would activate the dispatch servlet.
The rest of the configuration you do in a Spring web application context. Spring automatically looks for it using the name of the servlet as a hint. Since our servlet is called dispatch, it looks for a file called dispatch-servlet.xml in your WEB-INF directory. This configuration file will have three bits to it: the controller(s), the url mapping and the view resolver. First, the controller:
<bean id="dispatchController" class="com.memestorm.web.DispatchController"> </bean>
No rocket science there. It’s simply a bean implementing the appropriate interface, which we’ll look at later.
The view resolver tells us how to render the output from a controller. Here’s the one I chose:
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="prefix"> <value>/WEB-INF/views/</value> </property> <property name="suffix"> <value>.jsp</value> </property> </bean>
This uses a Spring-implemented InternalResourceViewResolver which basically maps to like-named views in the /WEB-INF/views directory, adding a .jsp. So for example, if our controller said “Please go to view myview,” then the above resolver would try to find the file myview.jsp in /WEB-INF/views. This is easy and extensible.
The final configuration is the URL mapping, which essentially tells the dispatcher servlet how to behave: Which incoming requests should it map to which controllers? We’ve chickened out:
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping"> <property name="mappings"> <props> <prop key="/*">dispatchController</prop> </props> </property> </bean>
This again uses a Spring-supplied URL mapper (isn’t it great, you don’t have to write any code) which, as you can see, maps all requests (/*) to the controller called dispatchController (which we defined above).
The last key to the puzzle is the controller itself. We know now that appropriate URLs (that are mapped to our dispatcher servlet) will be intercepted by the dispatcher servlet. It will then look at the URL, and on the basis of the URL mapper, map it to a particular controller (in this case, it maps all incoming URLs to the same controller), and to do this operationally it needs to invoke a method on the controller. Which method? Well, this particular URL mapper looks at the URL and “lops off” the start bit and uses what’s left. For example, if you went to http:.../skeleton1/send/actionName then it will try to invoke the method actionName() on dispatchController. Nothing too it. So, let’s check out the controller!
public class DispatchController extends MultiActionController {
public ModelAndView actionName(HttpServletRequest request,
HttpServletResponse response) throws Exception {
ModelAndView mav = new ModelAndView("myview");
mav.addObject("message", "Hiya");
return mav;
}
}
Pretty simple. This class implements the Spring MultiActionController (which really means we can have multiple control methods defined here), and provides a single control action method called actionName(). Check out the parameters - pretty much like a servlet which isn’t too surprising. The result is: ModelAndView. This is really a wrapper that tells Spring what the model data is (what data do you want to send to your view) and which view to actually send it to. In this case, we want to go to the view myview and send a string along too.
If you’ve been paying attention, you’ll know that our view resolver will look for myview.jsp, and yes, that’s what we have. Here’s a look at it:
Hello, you're in myview.jsp! <br />
The controller sent me some data,
here it is: <%=request.getAttribute("message") %>
Nothing too it. It prints a message, and grabs the model from the appropriately named attribute in the request.
So, if we now invoked http://../skeleton1/send/actionName our action will get invoked, which will eventually forward to this JSP page. You can extend at will, adding additional action methods for example, additional controllers if you like, and of course, additional views.
Downloading
Download the source
skeleton1.zip
and read the installation instructions. Short version: Download Spring (with dependencies, I’m using Spring 2M2), modify one property in our build file to point to the unzipped Spring distribution, run the build with ant, deploy on a web container (I use Tomcat).
Advanced
You’ll note that the code does just a little more than described above. In particular, we create an additional root application context with two beans a,b, and we make sure that we access and call these beans from the controller. Oh, and we use the logging described in Refreshable log4j configuration files.
Print This Post
« Previous Page — Next Page »