annia316
Photo credit: annia316
del.icio.us Digg DZone Reddit StumbleUpon
Software Development

Annotation-Based MVC in Spring 2.5

Simplify Spring 2.5 MVC configuration with Java annotations.

Spring 2.5 introduces annotation-based configuration for MVC controllers. In this short article I'll describe at a high level what you need to do to migrate your Spring 2.0 app over to Spring 2.5, at least as far as MVC is concerned. For information on migrating the other tiers, please see my article Annotation-Based Autowiring in Spring 2.5.

First make sure you drop spring-webmvc.jar onto your classpath. The DispatcherServlet is no longer part of spring.jar; it's in a separate module now.

Any given controller class can be set up in one of two ways. (And you can use both approaches in a single app.) Either the controller can handle a single action or else it can handle multiple actions. Usually a form "action", which really includes initially serving up the form and then accepting submissions of that form, would be handled with the first sort of controller, and non-form actions can be combined into a single controller, with actions being represented by methods.

Here's an extremely basic multi-action controller that handles three separate actions (mapped to methods). The actions don't do anything at all other than serve up the requested page.

package demo;
    
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
    
@Controller
public class SimpleController {
    
    @RequestMapping("/index.html")
    public void indexHandler() {
    }
    
    @RequestMapping("/about.html")
    public void aboutHandler() {
    }
    
    @RequestMapping("/admin.html")
    public void adminHandler() {
    }
}

Even though this is just about the simplest possible controller, there are still a few important points to highlight, especially if you're coming from earlier versions of Spring. First you will note that the controller is a POJO. It does not extend AbstractController or any of the other controller classes that you would have extended with Spring 2.0 or earlier. Second, notice the annotations. I've marked the controller itself with a @Controller annotation and the individual methods with @RequestMapping annotations. (I mentioned above that you can also map a controller to a single action; in that case you would attach the @RequestMapping annotation to the controller class itself. I'm not doing that here though.) Note also that I'm doing the URL mapping with the annotation. Pretty cool to have this option. Finally, though you can't tell from the controller, I'm using the request URL to specify the logical view name. Unless you specify otherwise, the DispatcherServlet will automatically assume that /index.html maps to the logical name "index", that /admin.html maps to the logical name "admin", etc. (Internally, it creates an instance of DefaultRequestToViewNameTranslator, though you don't see this unless you want to.) This is an example of Spring's movement toward the convention-over-configuration philosophy.

Now you need to make sure your application context config file is set up. Here's what I have:

<?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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-2.5.xsd">
    
    <context:component-scan base-package="demo"/>
    
    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <property name="prefix" value="/WEB-INF/jsp/"/>
        <property name="suffix" value=".jsp"/>
    </bean>
</beans>

The <component-scan> thing runs through your classes to find controllers and their annotation-based configuration. It knows which classes are controllers, as you may have guessed, because you used the @Controller annotation to label the controllers. Spring also supports @Repository for DAO layers, @Service for service layers, and @Component as a general stereotype over @Controller, @Repository and @Service.) The view resolver is just like it was with Spring 2.0.

Those are the basics. Of course there's a lot more you're going to want to do; for example, you'll want to pass in request parameters, process requests, return model objects, etc. But hopefully you'll find it useful to have a minimalistic example that gets you off the ground. Good luck!

Social bookmarks: del.icio.us Digg DZone Reddit StumbleUpon

Comments (16)

For your model, the M in your MVC you may consider using SQLOrm along with Spring JDBC.
See
http://sqlorm.sourceforge.net/
By Kasper Graversen on Feb 26, 2008 at 2:34 PM PST
in case of viewResolver, here we assume that we dump all the jsp files inside /WEB-INF/jsp.
what if we have different folder inside jsp folder. how do we access those files.

I tried doing.
@RequestMapping("admin/admin.html")
public void adminHandler() {
}
but it didn't work. (i am just trying to show the page by directly typing the URL).

Thanks
By puran on Mar 18, 2008 at 11:45 AM PDT
Hi Puran. Try using

@RequestMapping("/admin/admin.html")

Note the leading slash. Let me know if that doesn't work.
By Willie Wheeler on Mar 18, 2008 at 10:28 PM PDT
I am fascinated by this feature, all the sudden <a hre="http://www.polarsoftinc.com">Spring and Spring application builing </a> has become neat and easier
By John Young on Oct 25, 2008 at 9:11 AM PDT
I am new to spring.
im my controler class which is given as @controller i have
@Autowired
private FruitService fruitService;
getters and setters of the same are there and the service class is @ service . but when i try to access fruitService from getFruitService i m getting null pointer exception. what might have went wrong?
By prathibha on Nov 4, 2008 at 4:39 AM PST
@prathibha: The most likely things I can think of would be the following:

1) Did you forget to include the <component-scan .../> element to pick up your service? (Either that, or you need to declare the bean explicitly.)

2) Did you forget to declare the context namespace in your application context configuration file?

3) Did you choose the right @base-package in your <component-scan .../> definition?

4) Are you using Spring 2.5.x?

Those are just some ideas. Let me know if any of those helps out or if something else is going on. You may need to post the relevant bits of code.
By Willie Wheler on Nov 4, 2008 at 6:45 AM PST
hi willie
i dont have a <component-scan../> element my service is a seperate bean.context name space is there.
i am using 2.5.x.
@Controller and @RequestMapping are working.I have seen that control is not going to getters and setters of the variable declared as service in control class.
By prathibha on Nov 5, 2008 at 3:11 AM PST
@prathibha: When you say your service is a separate bean, I assume you mean that you've used a <bean ... /> element to create it in the application context. Is that correct?

How about your controller--are you using <bean .../> there as well, or are you using <component-scan .../>? Have you turned autowiring on (you can do this using either the beans/@default-autowire attribute, or else using bean/@autowire attribute if you're using <bean .../> to define the controller)? If you're autowiring by name, have you set the correct ID on your service bean? Those are more areas to check. Again I'd offer that you post the relevant part of your applicationContext.xml file--that might be easier.
By Willie Wheeler on Nov 5, 2008 at 7:50 AM PST
The relevant part of my application context file is only <context:annotation-config/>.
i havent declared a bean id for my service class. but my serviceImpl is marked as @Service. i have only one implementation of service interface .

in my controller
if(getFruitService()==null){System.out.println("null");} null is getting printed. but according to my knowledge if fruitService is autowired then getfruitService() should return the instance of actual class. is it?
By prathibha on Nov 6, 2008 at 12:03 AM PST
hi willi
the version i use is 2.5.5.
do i have to declre all the details in application context?
By prathibha on Nov 6, 2008 at 1:16 AM PST
Hi Prathibha. I can't really help out much without seeing your config file I'm afraid. There's lots more that's relevant to making this work than you are thinking. Please post your config minus everything other than the beans you are trying to wire... :-)
By Willie Wheeler on Nov 6, 2008 at 1:21 AM PST
Cool Article Willie! Thank you so much. It helped me understand the concept clearly
By praveen on Nov 8, 2008 at 10:12 PM PST
@praveen: Glad to hear it. ;-)
By Willie Wheeler on Nov 8, 2008 at 10:23 PM PST

kool man! so easy to understand...thanks much for the hard work

By batswon on Jan 11, 2009 at 1:45 PM PST

Hi Willie, Just wanted to say great article. I just converted a lot of the Struts actions at work to Spring annotated controllers, but I was wondering if you knew if you can use AOP to advise these controllers? I think I might've applied AOP to a Controller in the old hierarchy, but for some reason in Spring 2.5, the advice was not executing at my specified joinpoints. Do you have any ideas? Thanks.

By Ken on Jan 14, 2009 at 6:20 PM PST

Is this thread safe? As you sad a bean serve more clients and I know that a bean is singleton...

By psw on Feb 22, 2009 at 4:19 PM PST

Post a comment

Your name:
Your e-mail address (won't be displayed):
Your web site (optional):
example: www.xyz.com
Your comment:
Preview:
By You
Please help us reduce comment spam:
Spring Annotations RefCard
Check out the new DZone Spring Annotations Refcard by Craig Walls!

What's New?

2009-03-25 - My new article Getting Started with Spring Batch 2.0 is available on DZone.
2008-12-14 - We've just submitted a few more chapters of the book for review, so we're about halfway done.
2008-10-20 - I've added a new mailing list feature to the site. Sign up to receive e-mail updates about new articles.
Home | Consulting | Tech Articles | Mailing List | Contact | Spring Blog
Copyright © 2008 Wheeler Software, LLC.