Spring MVC Controller Plugin
Dependency :
compile ":springmvc:0.2"
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.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.
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:
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 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:
and then you can call the
Installation
To install the plugin, add a dependency in the plugins section of BuildConfig.groovy, e.g.plugins {
compile ':springmvc:0.2'
}Configuration
There are a few configuration options available - all are optional. They're defined in a springmvc block in Config.groovy:| Name | Default Value | Description |
|---|---|---|
| urlSuffix | 'action', i.e. *.action | the URL pattern for Spring MVC controller URLs |
| exceptionMappings | none | Map with exception class names as keys and JSP names as values |
| defaultErrorView | 'error', i.e. web-app/WEB-INF/jsp/error.jsp | the default error page if there's no corresponding mapping for the exception class |
| interceptors | none | bean names of HandlerInterceptors to apply to Spring MVC URLs |
| controllerPackages | none | a list of package names to scan for annotated controllers; similar to grails.spring.bean.packages |
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')
}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"; } }
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' %>
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 extendsorg.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.comPlease 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