Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

With grails, can I specify the controller, action, and view in UrlMappings.groovy?

With Grails, in UrlMappings.groovy, it seems I can specify the controller and action:

"/someURL" (controller: "Some", action: "someAction")

Or I can specify the view:

"/someURL" (view: "someView")

But I can't specify the controller, action, and view:

"/someURL" (controller: "Some", action: "someAction", view: "someView")

Instead, I have to specify the view in the controller. Is there a way to specify the view in the UrlMappings.groovy? Or is it just not possible?

like image 291
drew Avatar asked Dec 25 '22 13:12

drew


1 Answers

To do this, you would first need to know that Grails uses Spring Web under the hood. Spring Web is the most complex web framework I can think of (capable of doing anything AFAIK). At any rate, the important thing to know is how Spring Web's Request Life Cycle works. You can get a feel for it by reading the documentation of the "DispatcherServlet" which is the main Servlet in Spring Web (and consequently in Grails): http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/servlet/DispatcherServlet.html

Here is a great article from the grails team about how grails is really just spring: http://spring.io/blog/2010/06/08/spring-the-foundation-for-grails/

The important part relevant to this question are these two lines from that documentation:

  • Its view resolution strategy can be specified via a ViewResolver implementation, resolving symbolic view names into View objects. Default is InternalResourceViewResolver. ViewResolver objects can be added as beans in the application context, overriding the default ViewResolver. ViewResolvers can be given any bean name (they are tested by type).
  • If a View or view name is not supplied by the user, then the configured RequestToViewNameTranslator will translate the current request into a view name. The corresponding bean name is "viewNameTranslator"; the default is DefaultRequestToViewNameTranslator.

What you really want to do is create a customized ViewResolver or RequestToViewNameTranslator. The world is quite complex - if a View is supplied by the user in the Grails Controller explicitly, then you would want a ViewResolver. If instead a Map is returned (or some other custom object), then you want a RequestToViewNameTranslator.

Don't forget that grails has customized these two things already, to use the whole "convention over configuration" idea. So, you have to be careful in how you implement yours - I would recommend looking at the grails default implementations of these things.

Source for the GrailsViewResolver is here: https://github.com/grails/grails-core/blob/master/grails-web/src/main/groovy/org/codehaus/groovy/grails/web/servlet/view/GrailsViewResolver.java

Now, the real fun begins. The grails team didn't just provide custom implementations of spring web's default life cycle, they completely customized the dispatcher servlet as well. This means you need to be aware of how their universe differs from the spring universe (thus rendering many helpful spring forum questions irrelevant). Here is a link to the GrailsDispatcherServlet source code: https://github.com/grails/grails-core/blob/master/grails-web/src/main/groovy/org/codehaus/groovy/grails/web/servlet/GrailsDispatcherServlet.java

So if you managed to read this far, you can probably envision how to write a customized view resolver to return the view you want, but how to get access to the URL Mappings configuration data, so you can define views in there (however you see fit). The UrlMappings file relates to a spring bean, which will be available to autowire using the property "grailsUrlMappingsHolderBean" - see http://grails.org/doc/2.3.4/ref/Plug-ins/URL%20mappings.html

From that bean, you can access UrlMappings object, which you can get access to all UrlMapping definitions. See: https://github.com/grails/grails-core/blob/master/grails-web/src/main/groovy/org/codehaus/groovy/grails/web/mapping/UrlMappings.java https://github.com/grails/grails-core/blob/master/grails-web/src/main/groovy/org/codehaus/groovy/grails/web/mapping/UrlMapping.java

I'm not entirely convinced whether you can just throw anything in there, but since it's groovy I'd think you can. If not, you would have at least 2 options:

  1. Create a new config file for just controller/view mappings your custom view/viewname resolver would use
  2. Customize the URLMappings based on the grails source to interpret your custom configuration

A little off topic, here is an interesting article about removing the default mappings file and home-rolling your own: http://mrhaki.blogspot.com/2011/12/grails-goodness-customize-url-format.html

Again, I found several posts online where people went down this path, and it ended up being too hard because of the numerous configuration pieces need to make it function. Thus, I highly recommend against it. To a certain degree, I agree with the response on this page (which is what you will see alot trying to do something out of the grails universe): Bypassing grails view resolvers?

like image 69
Brad Lee Avatar answered May 12 '23 21:05

Brad Lee