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.

16 Responses to “Using Spring MVC Controllers in Grails”

  1. Please — Keep me up to date!!

  2. Josh says:

    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 says:

    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 says:

    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 says:

    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. […] recorded first by o0AnimeMeisje0o on 2008-08-17→ Using Spring MVC Controllers in Grails […]

  7. ayrusna says:

    Is this code worked for anybody?

    S

  8. Burt says:

    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 says:

    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 says:

    You can delete the @Override annotations.

  11. ayrusna says:

    Burt

    Is TestController code is same as JspController?

  12. ayrusna says:

    Burt

    Is TestController code is similar as JspController?

  13. ayrusna says:

    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 says:

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

  15. Burt says:

    @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.

  16. Travis says:

    Old post but I’m hoping you still monitor it. I’ve used the steps here to begin using the Java & JSP code from my Spring MVC app in a new Grails app. It works great. But now I am trying to expand my Grails app and all was going well until I created a GORM domain object. When I run integration tests against my GORM domain object, they work great. But when I run my application in a container (JBoss but I doubt that matters), I run into issues when trying to use any dynamic methods on the object (like findAll for instance). I get a MissingMethodException. Have you run into something like this or have some knowledge that would lead you to expect this? Any solutions you might have? I’m banging my head against my desk over here. . . Thanks.

Creative Commons License
This work is licensed under a Creative Commons Attribution 3.0 License.