10 Reasons to Replace Your JSPs With FreeMarker Templates
Still using Java Server Pages? I was too, but a few years ago I ditched them and haven’t looked back since. JSPs are a fine concept, but they take the joy out of web development. For me, it was the little things, like having to breakup my page templates into separate files: header.jsp and footer.jsp, not being able to call methods in the expression language, and not being able to combine and arrange page parts at runtime. FreeMarker templates are what I turned to. FreeMarker has been around for a while, but if you haven’t looked at them recently, here are a few reasons to consider them for your next web app.
1. No Classloading PermGen Issues
You’re probably no stranger to the JVM’s PermGen issues if you’ve developed Java web apps for a while. Since FreeMarker templates aren’t compiled to classes, they don’t take up permgen space and don’t require a new class loader to reload.
2. Template Loaders
Wouldn’t it be nice to load your pages and templates from a central place? Maybe from a CMS or database. Maybe you just want to put them on a file mount where they can be updated without redeploying the whole app. Well with JSPs you’re in for a hard time, but FreeMarker provides template loaders for just this purpose. You can create your own implementation or use one of the built-in classes.
- ClassTemplateLoader – loads templates from the classpath.
- FileTemplateLoader – loads templates from a specific folder in the file system.
- StringTemplateLoader – loads templates from a Map of strings.
- URLTemplateLoader – loads templates from a URL. You’ll have to implement the getURL method, but that should be easy to do.
- WebappTemplateLoader – loads templates from a servlet context.
FreeMarker also has a multi loader to chain together a series of template loaders.
I typically use the WebappTemplateLoader to point to a content folder under WEB-INF.
1 2 3 |
Configuration configuration = new Configuration(); configuration.setTemplateLoader( new WebappTemplateLoader(servletContext, "WEB-INF/content")); |
3. Templates Can Be Nested At Runtime
FreeMarker let’s you create real templates, not just fragments — remember the header and footer JSPs? It does this by allowing you to take one template (head.ftl in this case).
1 2 3 |
<head> <title>${title}</title> </head> |
And add it to a placeholder of another template (the body region of site.ftl).
1 2 3 |
<html> ${body} </html> |
You can choose which template goes into the body region programmatically. You can also add multiple templates together into the same region. You can even put a string or calculated value into the body region instead. Try doing that in a JSP.
4. No Imports
JSPs requires you to import every class you intend to use, just like a regular Java class. FreeMarker templates on-the-other-hand are just, well, templates. You can include one template in another, but there are no classes that need to be imported.
5. Supports JSP Tags
One argument for using JSPs is the availability of tag libraries out there. The good news is that FreeMarker supports JSP tags. The bad news is they’re referenced using FreeMarker syntax, not JSP syntax.
6. Method Calls in the Expression Language
Unless you’re targeting a Servlet 3.0/EL 2.2 container, method calls in the expression language are out. Not everyone agrees that method calls in the EL are a good thing, but when you really need them, the JSP workarounds were painful.
FreeMarker, however, treats each of these references the same.
1 |
${customer.address.country} |
1 |
${customer.getAddress().country} |
7. Built-in Null And Empty String Handling
Both FreeMarker and JSPs can handle null values in their expression languages, but FreeMarker goes a step further in usability.
1 |
Invoice Date: ${(customer.invoice.date)!} |
The exclamation symbol tells FreeMarker to do automatic null and empty string checking on the attached expression. If any of customer, invoice, or date are either null or empty string, you’ll just get the label:
1 |
Invoice Date: |
Another option is to include your default text after the exclamation.
1 |
Invoice Date: ${(customer.invoice.date)!'No Invoice Available'} |
Again, if any of the values are missing, you get back:
1 |
Invoice Date: No Invoice Available |
See Handling missing values for more details.
8. Shared Variables
FreeMarker’s shared variables are one of my favourite “hidden” features. This feature let’s you set values that are automatically added to all templates.
For example you can set your app’s name as a shared variable.
1 2 |
Configuration configuration = new Configuration(); configuration.setSharedVariable("app", "StackHunter"); |
Then access it like any other variable.
1 |
App: ${app} |
I’ve used shared variables in the past to reference resource bundles using expressions like ${i18n.resourceBundle.key}.
1 2 3 |
${i18n.countries.CA} ${i18n.countries['CA']} ${i18n.countries[countryCode]} |
The above lines all refer to the the key “CA” inside the countries_en.properties resource bundle. You’ll need to implement your own TemplateHashModel then add it as a shared variable to achieve this.
9. JSON Support
FreeMarker has built-in JSON support.
Let’s say you have the following JSON stored as a String in variable named user.
1 |
{ 'firstName': 'John', 'lastName': 'Smith', 'age': 25, 'address': { 'streetAddress': '21 2nd Street', 'city': 'New York', 'state': 'NY', 'postalCode': 10021 }} |
Use ?eval to convert it from a string to a JSON object, then use it in expressions as you would any other data.
1 2 |
<#assign user = user?eval> User: ${user.firstName}, ${user.address.city} |
10. Not Just for the Web
Finally, unlike JSPs, FreeMarker templates can be used outside of a servlet container. You can use them to generate emails, config files, XML mapping, etc. You can even use them to generate and save your web pages in a server-side cache.
Try using FreeMarker on your next web project and put the fun back into web development.
Read about How To Build Template Driven Java Websites with FreeMarker and RESTEasy.
You can also try http://trimou.org/. It’s a Mustache implementation written in Java with some additional features. And the feature set is very similar to freemarker (or velocity) but a little bit “logic-less”.
And compared to your 10 reasons:
1. Templates are not compiled to classes as well
2. There’s a similar concept – TemplateLocator
3. Template inheritance and partials (aka includes) are supported
4. No imports as well
5. No JSP tag support
6. Should work too
7. Supports custom MissingValueHandler component
8. Yes, but we call it “global data” 🙂
9. There’s a built-in JSON extension
10. The same applies to Trimou 🙂
Hi Martin,
That’s awesome, thanks for sharing.
I took a quick scan of the docs, Trimou looks like a promising alternative. The lambdas and use of the builder pattern are cool. I also kinda like the double brace.
At this point, I’m pretty invested in FreeMarker, but I’ll take a closer look when time permits.
Cheers.
Hi Taylor,
Have you do a performance test between JSP and freemarker ?
Thanks,
Joe
Hi Joe,
You can test JSPs and Freemarker sites the same way you test other websites.
Here are some tools:
http://jmeter.apache.org/
https://developers.google.com/speed/pagespeed/
http://yslow.org/
http://tools.pingdom.com/fpt/
Hope that helps.
Well, I’m pretty sure JSP tech is faster because they’re converted into classes and then compiled. What to use? Well, that depends on what you need: more speed or easy updates.
Not that updating a JSP cannot be easy, but they are usually deployed as part of a war package, which makes it more complicated. Think about a team where your ui designer has to open a maven project, compile it, run it, etc. only for testing a new tag in the header.
Best,
Andres
Andres — I agree with you, JSPs are probably faster to render than any templating language.
But how much faster? And does it matter?
Trade offs, like the one you mentioned, make our job difficult. Not only do we want to choose the fastest, newest, sexiest tech, but we also have to make sure it fits into our organization.
Happy coding!
What about compared to JSF?
That’s a fair question Eric, but I wonder what’s driving our desire to use server-side component frameworks?
Back when I developed using GWT, I argued that GWT made it easier for back-end Java developers to create rich web applications. Unfortunately, the server-side framework approach doesn’t lend itself to using modern UI frameworks (Bootstrap, AngularJS, NVD3, etc). It doesn’t work well for non-Java developers — like web designers. And it can’t easily leverage templates from other languages/platforms (like WordPress).
An experienced developer can manage these challenges, but it’s a lot of work without much return.
These days I much prefer working with a web designer who’s good at HTML, CSS, Javascript, plus a front-end framework. If I’m in rush, I’ll skip the designer and use an off-the-shelf WordPress theme as my Java site template 😀
It’s not really meaningful to compare FreeMarker to JSF, because FreeMarker isn’t a UI framework. You might render some of the UI components with FreeMarker, but I guess what you meant is rendering a whole page with FreeMarker. Perhaps you could work out some intricate system of custom directives that build a component tree instead of rendering directly and such, but FreeMarker doesn’t have anything like that out of box, and I suspect it wouldn’t be the right tool for this job either. It just generates text, with one pass.
ddekany – you’re 100% correct. FreeMarker and JSF are completely different creatures with different goals.
I wouldn’t build a component tree on the server at all. Instead, I’d use a client-side framework like Bootstrap + JQuery.
As a developer/architect, you have to decide whether you’ll treat web apps as composed of components or content fragments.
Coming from an AWT/Swing/SWT background (and Borland’s Turbo Vision before that :D), I’ve used the component model in web apps many times. But it usually seems to end up causing performance and maintenance challenges down the road.
I may try the web components approach again, but for now I’m build web apps on content fragments.
Cheers.
Hi, nice article!
I’ve used freemarker with spring mvc with sucess, but know on a project using straight MCV with servlets and freemarker i can’t seem to import a external css file on my base.ftl.
Do you know a working example for this?
PS: css inline works, but i need it to be external.
Sorry, I don’t have an example, but I have a suggestion. Whenever I run into this kind of import or URL-not-loading-as-expected issue, I pull out Firebug’s Net panel to see where the browser’s trying to pull things from.
If you’re not using Firefox, other browsers have something similar. This link talks about the JavaScript console, but their network panels are usually in the same place.
http://stackoverflow.com/questions/4743730/what-is-console-log-and-how-do-i-use-it/11663507#11663507
Good luck.
At my new job, we are using Freemarker 1.6, but I have to say that it seems to behave in ways that are not documented.
Maybe you know where it is documented that (apparently) modules can be imported in one FTL but still defined/accessable in other imported (not included) FTL files. I.E. import namespaces sometimes “leak” into an FTL file’s scope (and Im not talking about #GLOBAL nor java defined data model namespace).
Is that really FreeMarker 1.6? That has little to do with today’s FreeMarker (2.x), and so with its documentation…
Hai
this is kannathasan .. i want to learn JAVA.. now i am begining java program so can you help me..
Hi Kannathasan,
Your best bets are to follow a tutorial:
http://docs.oracle.com/javase/tutorial/tutorialLearningPaths.html
And post your specific questions on Reddit:
http://www.reddit.com/r/javahelp
Good luck.
Even Freemarker is outdated, think of Underscore JS template.. Simply Powerful…
how to add custom Jsp tags/pages int freemarker template.can anyone guide me through this
How far did you get with http://freemarker.org/docs/pgui_misc_servlet.html#autoid_56 ?
Does it make sense to still use Tiles if you move to FreeMarker?
I’m biased, but I recommend you look at the next blog on how to create templated websites with FreeMarker. Once you go with an approach like this, you won’t ever want to compose your pages using an external XML definitions file 😉
http://blog.stackhunter.com/2014/01/21/build-template-driven-java-websites-freemarker-resteasy/
Cheers.