4

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?

tim_yates
  • 167,322
  • 27
  • 342
  • 338
drew
  • 2,949
  • 3
  • 25
  • 27
  • 3
    can you explain what you are trying to reach ? maybe you rather need a generic route that will be handled by one controller, so you will define the view in controller only once, but this one controller can handle every route, otherwise it doesnt make much sense, because the controller should build up the model that is rendered to a view – john Smith Feb 18 '14 at 22:21
  • I don't want to specify the view within the code for the controller; I'd rather the controller return the model alone, so that I can specify with view within the UrlMappings.groovy file. – drew Feb 19 '14 at 18:00
  • sorry, that doesnt make sense to me, i think its not possible. but i think its absolutely possible what you are trying to reach, but not that way, maybe you should provide some further info about the dependency of the view to the controller – john Smith Feb 19 '14 at 22:10
  • It's against the grails' paradigm: `convention over configuration`, if you need to hack something like this, you must be doing this the wrong way – injecteer Mar 04 '14 at 20:16
  • @injecteer How is this a convention over configuration thing? Specifying two out of the three is convention, but all three is configuration? Specifying anything in UrlMappings.groovy is configuration, but grails still allows it. If you want to talk about the grails paradigm, convention is letting grails do default URLs based on the controller's class and methods names. – Steven Byks Jun 09 '16 at 13:35

1 Answers1

10

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?

Community
  • 1
  • 1
Brad Lee
  • 629
  • 7
  • 11