One of our requirements was to use FreeMarker to generate the HTML of our UI. This is a requirement because we're using FreeMarker in other areas and we've created a development tool that uses FreeMarker in addition to other front end technologies (JS, SASS).
The problem is that Grails wants to use GSPs (Grails Server Pages), which are like JSPs (and, in fact, compile down to JSPs). Grails has the ability to incorporate third-party plugins into your project, and there's a FreeMarker plugin for Grails. Unfortunately, the plugin was made for Grails 1.2 and we're trying to use Grails 2.2.1. I tried for two days to try to get the FreeMarker plugin to work, but it just didn't seem to do anything. It was a frustrating situation.
Having read a lot of Grails documentation over the last few days, I found that you could configure Grails similarly to how you configure a Spring application. You put that configuration in the resources.groovy file.
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer import org.springframework.web.servlet.view.freemarker.FreeMarkerViewResolver // Place your Spring DSL code here beans = { freemarkerConfig(FreeMarkerConfigurer) { templateLoaderPath = "/" } viewResolver(FreeMarkerViewResolver) { cache = "false" prefix = "bin/freemarker" suffix = ".ftl" exposeSpringMacroHelpers = "true" } }
Spring configuration is, of course, XML and this is a Grails closure. That part wasn't hard to convert. You can find an example of how to configure FreeMarker in a Spring app looks like, here. The only other thing we had to do was to put the line below into our BuildConfig.groovy file.
dependencies { ... runtime "org.freemarker:freemarker:latest.release" ... }
Now, the only thing we had to figure out was where to put the FreeMarker templates. At first, we had them in our views folder where the GSPs went, but we were getting 404s when we ran the app. After some debugging (thanks Roy for helping debug!) we figured out that the template loader was looking for the templates in the web-app folder. That was easy enough to fix, we copied our templates from the views folder over to the web-app folder. After that, everything worked just fine!
So, to recap, we added a typical Spring configuration to the resources.groovy file, added the FreeMarker jar as a runtime dependency in the BuildConfig.groovy file and put our templates into the web-app folder (in the folder configured in the prefix of the viewResolver).
The solution was frustratingly simple after we figured it out. I wrote this post because I researched and experimented on whether this was possible or not for over two days without any success. Hopefully this helps anyone else who is trying to use FreeMarker in their Grails app.
If you're like me, though, you want to see more. Here's an example of a generic Controller:
class ApplicationController { static defaultAction = "show" GrailsApplication grailsApplication def show() { [model: [version: getAppVersion()]] } private getAppVersion() { def metadata = grailsApplication.metadata return metadata['app.version'] } }
It has one public method, show. We want that when you navigate to /app-name/application or /app-name/application/show that it displays the version of the app. I created a template, /web-app/application/show.ftl. Now, the template contents are:
hello world<br> ${model.version}
When I navigate to /app-name/application/show, I get:
Which is as expected. Pretty slick. We're still at the beginning, but this should allow us to borrow front -end devs from other teams since they'll already understand the view technology and we'll be using the same tools that their teams use.
Hi.
ReplyDeleteI'm just curious ('cause I don't work with Groovy and Grails anymore): did you also tried the branch (1.0-prep)?
https://github.com/grails-plugins/grails-freemarker/branches
Best regards,
Daniel.