Please ensure Javascript is enabled for purposes of website accessibility
Home AppDev Groovy Server Pages (GSP): What They Are and How They Work in...

Groovy Server Pages (GSP): What They Are and How They Work in the Grails Framework

Groovy Server Pages

Groovy Server Pages are the engine behind the view layer in the Grails framework. If you’ve worked with JSP before, GSP will feel familiar, but faster to write, easier to maintain, and far more expressive thanks to the Groovy language beneath it.

Here I will explain everything you need to know: from GSP syntax and built-in tags to Sitemesh layouts, XSS prevention, and how Groovy server pages compare to modern alternatives. Whether you’re starting a new Grails project or evaluating GSP for server-side rendering, this post gives you the exact details to get started and go deep.

Key Takeaways

  • Groovy server pages (GSP) serve as the view layer in the Grails framework, allowing for dynamic web content using HTML and Groovy code.
  • GSP files, with a .gsp extension, reside in the grails-app/views directory and benefit from Java’s performance on the JVM.
  • Key syntax elements include expressions, scriptlets, comments, and tags starting with ‘g:’.
  • GSP supports features like reusable templates, layouts with Sitemesh, and form handling for user input.
  • It’s well-suited for rapid MVP development, particularly for teams with a Java background, offering server-side rendering by default.

What Are Groovy Server Pages?

Groovy Server Pages (GSP) is the primary view rendering technology in the Grails framework. A GSP file is a mix of HTML markup and Groovy code, processed server-side to generate dynamic web content.

Key facts:

  • GSP files use the .gsp extension and live in the grails-app/views directory
  • As of Grails 3.3, GSP is an independent plugin, not bundled in the core framework
  • It runs on the Java Virtual Machine (JVM), inheriting Java’s security and performance characteristics
  • It is designed to be familiar to ASP and JSP developers, but more flexible and intuitive

To add GSP to a Grails project, declare the dependency in build.gradle:

dependencies {
implementation "org.grails.plugins:gsp:6.2.3"
}

For production compilation, apply the Gradle plugin:

apply plugin: "org.grails.grails-gsp"
Groovy Server Pages

How GSP Fits the Grails MVC Architecture

Grails follows the MVC Design Pattern (Model-View-Controller), and Groovy server pages serve as the View layer.

Here’s how the flow works:

  1. A browser sends a request to a Grails controller
  2. The controller queries the database via GORM (Grails Object Relational Mapping) and builds a model, a map of key-value data
  3. That model is passed to a GSP view
  4. The GSP renders the model into HTML and sends it back to the browser

Example controller action:

def show() {
[book: Book.get(params.id)]
}

Corresponding GSP expression:

${book.title}

The Grails framework uses Convention over Configuration: if a controller action is named list()Grails automatically looks for grails-app/views/[controller]/list.gsp, no manual wiring required.

GSP Syntax: The Core Elements

Understanding Groovy server page elements starts with four building blocks.

1. Expressions ${expr}

The most common form of GSP is Groovy server pages code. Any Groovy expression goes inside ${}:

<p>Welcome, ${user.name}!</p>
<p>Today is: ${new Date()}</p>

Expressions are automatically HTML-encoded by default (more on that in the security section).

2. Scriptlets <% %> and <%= %>

Scriptlets (<% %>) embed raw Groovy code blocks. Output scriptlets (<%= %>) print a value directly:

<% out << "Hello from a scriptlet" %>
<%= "Output this string" %>

Important: The official Groovy server pages documentation strongly discourages scriptlets. Use GSP tags or custom tag libraries instead to maintain clean separation of concerns.

3. Server-Side Comments <%-- --%>

Groovy server pages comments use JSP-style syntax and are never sent to the client:

<%-- This comment is stripped at compile time --%>

Unlike HTML comments (<!-- --> These are invisible in the browser's source.

4. Page Directives

Groovy server pages import statements and content-type declarations use the directive syntax:

<%@ page import="java.text.SimpleDateFormat" %>
<%@ page contentType="application/json" %>

Groovy imports most standard classes automatically, so explicit imports are rarely needed.

Essential Built-in GSP Tags

All GSP tags in Grails use the g: prefix and require no import declarations.

Here are the ones you’ll use most.

Conditional Logic <g:if> and <g:else>

<g:if test="${session.role == 'admin'}">
<a href="/admin">Admin Panel</a>
</g:if>
<g:else>
<p>Access restricted.</p>
</g:else>

Iterative Tags <g:each>

The <g:each> tag iterates over any Groovy collection:

<g:each in="${bookList}" var="book">
<li>${book.title} by ${book.author}</li>
</g:each>

The <g:link> tag builds URLs based on controller and action names, not hardcoded paths:

<g:link controller="book" action="show" id="${book.id}">
View Book
</g:link>

Pagination <g:paginate>

The GSP pagination tag generates full next/previous navigation with a breadcrumb trail:

<g:paginate controller="book" action="list" total="${bookCount}" />

Key attributes for <g:paginate> (per the official Grails 7.0.0 documentation):

AttributeRequiredDefaultDescription
total✅ YesTotal number of results
maxNo10Records per page
maxstepsNo10Number of pagination step links
prevNo“Previous”Label for previous link
nextNo“Next”Label for next link
omitFirstNofalseHide the first page link when not in range
omitLastNofalseHide the last page link when not in range
Groovy Server Pages

Working with Forms and User Input

Groovy server pages form handling is clean and controller-aware.

Here’s a full example with a Groovy server pages text field:

<g:form controller="employee" action="save">
First Name: <g:textField name="fName" value="${emp.fName}" />
Last Name: <g:textField name="lName" value="${emp.lName}" />
Active: <g:checkBox name="active" value="${emp.active}" />
Department: <g:select name="dept" value="${emp.dept}"
from="['Engineering', 'Sales', 'HR']" />
<g:submitButton name="submit" value="Save" />
</g:form>

GSP also provides <g:passwordField>, <g:hiddenField>, <g:radio>, and <g:actionSubmit> for forms with multiple submit buttons.

Handling Scopes and Parameters

GSP has direct access to five variable scopes:

ScopeUsage
paramsURL and form request parameters
requestPer-request attributes
sessionPer-user session data
flashShort-lived data (survives one redirect)
applicationApplication-wide shared state

Use <g:set> to define variables within a GSP:

<g:set var="now" value="${new Date()}" scope="request" />

Advanced View Techniques

Templates for Reusability

GSP templates and layouts start with reusable partial views. By convention, template filenames begin with an underscore:

grails-app/views/book/_bookCard.gsp

Render a template with:

<g:render template="bookCard" model="[book: myBook]" />

To render a collection in one call:

<g:render template="bookCard" var="book" collection="${bookList}" />

Sitemesh Layouts and Decorators

Grails Sitemesh layouts live in grails-app/views/layouts/. A layout wraps your individual views with shared structure, headers, footers, and navigation:

<html>
<head>
<title><g:layoutTitle default="My App" /></title>
<g:layoutHead />
</head>
<body>
<div class="nav"><!-- shared nav --></div>
<div class="content">
<g:layoutBody />
</div>
</body>
</html>

Three ways to trigger a Sitemesh layout:

  1. Meta tag in the view, <meta name="layout" content="main" />
  2. Controller-level declaration, static layout = 'customer'
  3. Convention, Grails looks for grails-app/views/layouts/BookController.gsp automatically

The default application layout is grails-app/views/layouts/application.gsp. Override it in application.yml:

grails:
sitemesh:
default.layout: myLayoutName

Use <g:applyLayout> for an inline layout application to sections or templates:

<g:applyLayout name="myLayout" template="bookTemplate" collection="${books}" />

Custom Tag Libraries (TagLib)

Custom Tag Libraries in GSP let you encapsulate complex view logic into clean, reusable tags. Create a Groovy class in grails-app/taglib/ with a name ending in TagLib:

class FormatTagLib {
def sayHi = { attrs ->
out << "Hello, ${attrs.name}!"
}
}

Use it in any GSP without imports:

<g:sayHi name="${user.name}" />

Performance and Security

GSP Compilation to Java Servlets

Groovy server pages compile into Java classes at runtime via the GroovyPagesTemplateEngine and GroovyPagesServlet. This means GSP benefits from JVM-level performance once compiled, not interpreted on each request.

For production deployments, pre-compile all GSPs at build time using the grails-gsp Gradle plugin. This eliminates first-request compilation overhead entirely.

GSP reload configuration (development only):

grails.gsp.enable.reload = true
grails.gsp.reload.interval = 5000 // ms between last-modified checks
grails.gsp.reload.granularity = 1000 // ms leeway for last-modified comparison

Note: Frequent GSP reloading in long-running development sessions can cause PermGen (or Metaspace) exhaustion—restart the server if memory issues arise.

XSS Prevention (Cross-Site Scripting)

GSP’s security defaults are strict. As of Grails 2.3, all ${}expressions are HTML-encoded by default. The default codec configuration application.yml is:

grails:
views:
gsp:
encoding: UTF-8
htmlcodec: xml
codecs:
expression: html # escapes values inside ${}
scriptlets: html # escapes scriptlet output
taglib: none # tag authors control their own encoding
staticparts: none # raw markup is not re-encoded

To output trusted HTML content without encoding, use raw():

<section>${raw(page.content)}</section>

Use this only for content you control. Never call raw() on user-supplied data.

Additional built-in protections:

  • GORM automatically escapes SQL to prevent SQL injection
  • <g:link>, <g:form>, and <g:createLink> apply URL encoding automatically
  • Custom codecs like encodeAsHTML(), encodeAsURL(), and encodeAsJavaScript() are available for edge cases
Groovy Server Pages

GSP vs. JSP vs. Modern Frontend Frameworks

FeatureGSP (Grails)JSP (Spring MVC)React / Angular
LanguageGroovyJava / ELJavaScript / TypeScript
Templating StyleTags + expressionsTags + scriptletsComponent-based
Server-Side Rendering (SSR)✅ Native✅ Native⚠️ Requires configuration
HTML Auto-Escaping✅ Default (since 2.3)❌ Manual✅ Default
Layout EngineSitemeshTiles / ThymeleafCSS frameworks
Convention over Config✅ Strong❌ Weak❌ N/A
GORM Integration✅ Built-in❌ Requires setup❌ N/A
Learning Curve (Java devs)LowLowMedium–High
Best ForRapid MVPs, full-stack GrailsSpring appsSPAs, complex UI

Running Groovy Server Pages Without Grails

Running Groovy server pages without Grails is technically possible using groovy.servlet.TemplateServlet with a standard servlet container. However, the tag library ecosystem, Sitemesh integration, and GORM connectivity are all Grails-specific. Outside of Grails, GSP loses most of what makes it productive.

For Groovy server pages Spring MVC integration (non-Grails), the GSP plugin can be wired into a Spring Boot project, but the setup requires manual configuration of the GroovyPagesTemplateEngine bean. Official Groovy server pages documentation for this use case is limited.

Why GSP Still Makes Sense in 2026

Groovy server pages remain a practical choice for specific scenarios:

  • Rapid MVP development: Grails scaffolding generates create.gsp, edit.gsp, index.gsp, and show.gsp automatically with grails generate-views
  • Full-stack JVM projects: Tight integration between GORM, controllers, and views reduces boilerplate
  • Teams with Java backgrounds: The learning curve is shallow compared to React or Angular
  • Server-side rendering by default: No client-side hydration, no JavaScript bundle size concerns

As noted in the Grails community, GSP is one of the best ways to build and demonstrate a product quickly in early-stage startups, especially when backend and frontend need to move in lockstep.

FAQs

What is the difference between GSP and JSP?

Both are server-side templating technologies. GSP uses Groovy expressions and g: tag libraries with automatic HTML encoding by default. JSP uses Java EL and custom tag libraries but lacks Grails’ convention-based view resolution and tight GORM integration. For a detailed breakdown, see the comparison table above.

Where do Groovy server pages live in a Grails project?

GSP files live in the grails-app/views/ directory. Templates (reusable partials) use an underscore prefix (e.g., _bookCard.gsp). Layout files go in grails-app/views/layouts/.

Is Groovy Server Pages documentation available for Grails 7.x?

Yes. The official GSP plugin documentation for the 7.0.0-SNAPSHOT is at https://grails.apache.org/docs-legacy-gsp/snapshot/guide/. The main Grails 7.0.0 security and web layer docs are at https://grails.apache.org/docs/7.0.0/.

How do I prevent XSS attacks in Groovy server pages?

By default, Grails HTML-encodes all ${} expressions since version 2.3. Avoid using raw() user-supplied input. Configure the filteringCodecForContentType option application.yml for maximum output encoding at the response level.

Can I use Groovy server pages with Angular or React?

Yes. GSP can serve the initial HTML shell that loads a JavaScript frontend. The two are independent layers. You can build REST APIs in Grails controllers and consume them from Angular or React while still using GSP for pages that benefit from server-side rendering.

Subscribe

* indicates required