Using Spring MVC Controllers in Grails

Update 03/22/2010: As of version 1.2 Grails has support for Spring MVC controllers; check out the 1.2 release notes

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.

15 Responses to “Using Spring MVC Controllers in Grails”

  1. Robert O'Connor
    March 27th, 2008 21:50
    1

    Please — Keep me up to date!!

  2. Josh
    March 27th, 2008 22:47
    2

    Very interesting, was considering the same approach today as well. Nice to see some helpful examples. Keep updating your blog especially if you push this approach to production, would be interested to hear your experiences…

    Josh

  3. Jon Chase
    March 28th, 2008 08:07
    3

    Very cool – I’ve been thinking about a Spring MVC + Grails combo for a while, glad to see a write up on how it’s done.

    Please post again as you move this into production (or anything else of interest happens)! I’m guessing there are a lot of people in the same boat as myself – an entire app developed in SpringMVC and Hibernate looking for a bit more productivity but not ready to throw everything thing out and start from scratch.

    BTW, couldn’t you reuse Spring’s ParameterizableViewController instead of your JspController?

  4. Burt
    March 28th, 2008 08:16
    4

    Jon – thanks for the ParameterizableViewController pointer. It seemed unnecessary to create such a simple controller but I didn’t see that there was one already.

  5. Jose Noheda
    March 28th, 2008 09:45
    5

    Have you tried IWebMvc? It’s still Milestone 2 but it may be worth a look if you’re considering Grails + Spring MVC. You can download it from http://code.google.com/p/internna/downloads/list. Please log about your experiences if you try it :-)

  6. Recent URLs tagged Groovy - Urlrecorder
    August 29th, 2008 01:30
    6

    [...] recorded first by o0AnimeMeisje0o on 2008-08-17→ Using Spring MVC Controllers in Grails [...]

  7. ayrusna
    April 1st, 2009 13:46
    7

    Is this code worked for anybody?

    S

  8. Burt
    April 1st, 2009 13:52
    8

    I created a Grails plugin based on this work, see http://grails.org/plugin/springmvc

    I haven’t tried it in 1.1, but it was working in 1.0.x

  9. ayrusna
    April 1st, 2009 13:57
    9

    I dont want to use JDK 1.5 or grails 1.1, I want to use grails 1.0.4 with jdk 1.4.2. In that case @override annnotation is complaining. How to go about that? My deployment environment is Tomcat 5.5

  10. Burt
    April 1st, 2009 14:53
    10

    You can delete the @Override annotations.

  11. ayrusna
    April 2nd, 2009 13:21
    11

    Burt

    Is TestController code is same as JspController?

  12. ayrusna
    April 2nd, 2009 13:22
    12

    Burt

    Is TestController code is similar as JspController?

  13. ayrusna
    April 2nd, 2009 13:29
    13

    Getting this error:

    Caused by: org.springframework.beans.InvalidPropertyException: Invalid property
    ‘applicationContext’ of bean class [org.aarp.ones.JspController]: Getter for pro
    perty ‘applicationContext’ threw exception; nested exception is java.lang.reflec
    t.InvocationTargetException

    any idea?

  14. ayrusna
    April 3rd, 2009 12:37
    14

    Do I need to do any changes to applicationContext.xml for SpringMVC configuration?

  15. Burt
    April 3rd, 2009 19:28
    15

    @ayrusna you wouldn’t edit applicationContext.xml, that creates Spring’s parent application context. Your beans go in resources.groovy/resources.xml. The original work was done with Grails 1.0.3 but I just created test apps in 1.0.4 and 1.1 and both worked fine. Could you email your org.aarp.ones.JspController to me (burt at burtbeckwith dot com) and I’ll take a look.

Leave a Reply

Creative Commons License
This work is licensed under a Creative Commons Attribution-ShareAlike 2.5 License.