Spring MVC Controller Plugin

  • Tags : other frameworks, spring-mvc
  • Latest : 0.2
  • Last Updated: 17 December 2012
  • Grails version : 2.0 > *
0 vote
Dependency :
compile ":springmvc:0.2"

Documentation Source Issues

Summary

Enables the use of Spring MVC controllers

Description

The SpringMVC plugin allows you to use controllers written in Java using Spring MVC and use JSPs to render output.

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. But for the case where you're concerned about controller performance, or to help migrate a traditional Spring/Hibernate to Grails, this plugin allows you to define or reuse Java controllers.

Installation

To install the plugin, add a dependency in the plugins section of BuildConfig.groovy, e.g.

plugins {
   compile ':springmvc:0.2'
}

The install script will create a web-app/WEB-INF/jsp folder if it doesn't exist, and copy the sample error.jsp there if it doesn't exist. It also creates an empty web-app/WEB-INF/SpringMVC-servlet.xml - the file has to exist but all beans are defined by the plugin, in the app's resources.groovy and/or resources.xml, or by using Spring annotations.

Configuration

There are a few configuration options available - all are optional. They're defined in a springmvc block in Config.groovy:

NameDefault ValueDescription
urlSuffix'action', i.e. *.actionthe URL pattern for Spring MVC controller URLs
exceptionMappingsnoneMap with exception class names as keys and JSP names as values
defaultErrorView'error', i.e. web-app/WEB-INF/jsp/error.jspthe default error page if there's no corresponding mapping for the exception class
interceptorsnonebean names of HandlerInterceptors to apply to Spring MVC URLs
controllerPackagesnonea list of package names to scan for annotated controllers; similar to grails.spring.bean.packages

So a configuration block that defines a single interceptor, uses *.action for URLs, searches in the com.mycompany.myapp.springmvc package for annotated controllers, and defines a default error JSP and two exeption-specific exception mappings (note that the values for urlSuffix and defaultErrorView are redundant since they're the default values) would be:

springmvc {
   interceptors = ['loggingInterceptor']
   exceptionMappings = ['java.io.IOException': 'ioexception', 'com.myapp.MyException': 'myex']
   defaultErrorView = 'error'
   urlSuffix = 'action'
   controllerPackages = ['com.mycompany.myapp.springmvc']
}

Application Beans

Unlike in Grails, there's no automatic URL mapping via UrlMappings.groovy. To connect a controller to a URL you can define a Spring bean (in resources.groovy or resources.xml) whose name is the url and the bean class is the controller, e.g.:

'/test.action'(com.burtbeckwith.mvctest.controller.TestController) {
   cacheSeconds = 0
   bookService = ref('bookService')
}

This will map http://localhost:8080/yourapp/test.action to TestController. Setting cacheSeconds to 0 instructs Spring to send headers to disable caching. And 'bookService' is a dependency injection for BookService to access Book domain instances. The controller returns 'books' as its view name - this is prefixed by '/WEB-INF/jsp/' and suffixed by '.jsp' to define the JSP that will render the response (i.e. '/WEB-INF/jsp/books.jsp').

You can also use annotated controllers that specify the url mappings using RequestMapping annotations, e.g.

@Controller
@RequestMapping("/theUrl.action")
public class SomeController {

private IBookService bookService;

@Autowired public void setBookService(IBookService bookService) { this.bookService = bookService; }

@RequestMapping(method = RequestMethod.GET) public String bookForm(ModelMap model) { model.addAttribute(new Book()); return "bookForm"; }

@RequestMapping(method = RequestMethod.POST) public String onSubmit(@ModelAttribute("book") Book book) { bookService.create(book); return "redirect:viewBooks.action"; } }

In addition, you can define HandlerInterceptors in resources.groovy. They should extend HandlerInterceptorAdapter or implement HandlerInterceptor directly. Add their bean names to the 'interceptors' list and Spring MVC requests will be intercepted. Note that these interceptors are in addition to the standard Hibernate OSIV interceptor and a locale change interceptor.

For example:

loggingInterceptor(com.burtbeckwith.mvctest.interceptor.LoggingInterceptor)

Resources plugin issues

The resources plugin adds /static/ to static resource URLs, so you have to do a bit more work to reference images, JavaScript, and CSS files in JSPs. Ordinarily you would use the c:url tag which adds the context to the URL, but this isn't aware of the resources plugin. You can call Grails taglibs from JSPs but there is a wrapper layer required and it hasn't been updated in a while. So you need to add a TLD declaration to your JSP:

<%@taglib prefix='g' uri='http://grails.org/tags' %>

and then you can call the resource tag like this:

<link rel='stylesheet' href='<g:resource dir='css' file='main.css'/>' type='text/css' />

Sample App

You can download a sample app here. It's pretty simple - it has a single domain class, and three controllers; a standard Grails controller, an annotated Java controller, and a Java controller that extends org.springframework.web.servlet.mvc.AbstractController and is wired up in resources.groovy. There's a Grails service to load and save domain instances that implements a Java interface so it's callable by the MVC controllers. There's also a sample interceptor (it just logs requests) and a sample JSP 2.0 tag file, date.tag.

The app creates six books in BootStrap. Navigate to http://localhost:8080/springmvctest/ to view the index page with links to the three controllers.

Author

Burt Beckwith burt@burtbeckwith.com

Please report any issues to the Grails User mailing list and/or write up an issue in JIRA.

History

  • December 17, 2012
    • released version 0.2
  • September 7, 2008
    • released initial version 0.1
See this blog post for more information.