Dynamically Finding Views in Grails

Posted by David Estes on Mar 31, 2014

Filed under Grails

Over the past few weeks. I've been working on and off at creating a fully functional CMS Engine for Grails. A few things have come into play that I could find little documentation on and would like to mention for those that may not know about them.

In this particular use case. I need to be able to reference all layout views within a project in both development mode as well as warDeployed. This can seem confusing because in war mode your GSP files are compiled. However, a non compiled version is also kept in the war. These can be resolved universally in both modes by using 2 very useful beans. They are groovyPageLocator and groovyPageResourceLoader. The first step is to find your view. To do this you simply call:

def groovyPage = groovyPageLocator.findPage('/layouts/page.gsp')

This will return a GroovyScriptSource which has a getURI() method.

Now to reference the contents of this file we simply load it as a resource:

groovyPageResourceLoader.getResource(groovyPage.URI).inputStream.text

Now you have the uncompiled contents of a view. Pretty nifty eh? Very small use case, but still good to be aware of.

UPDATE: Apparently the groovyPageResourceLoader only exists in you have an external views folder from your WAR. You still want to reference it but if it does not exist you need to scan your war WEB-INF folder.

def servletContext = ServletContextHolder.servletContext

def resourcePaths = ["/WEB-INF/grails-app/views/"]

resourcePaths += grailsApplication.parentContext.getResourcePaths("/WEB-INF/plugins").collect { path ->
  return "${pluginResource}grails-app/views/"
}

for( resourcePath in resourcePaths ) {
  def layoutResource = grailsApplication.parentContext.getResource(resourcePath + "layouts/${name}.gsp")
  if(layoutResource.exists()) {
    return layoutResource.inputStream.text
  }
}