- 🛠️ GSP remains maintained: the Apache Grails plugin catalog lists GSP 7.2.2 as released on August 2, 2026, while Grails 8 development continues in milestone form.
- ⚙️ The core model is simple: a Grails controller returns a model, a .gsp file in grails-app/views reads that model, and the server renders markup before the response reaches the browser.
- 🧩 The safest design keeps business logic outside the view. Built-in tags such as g:if, g:each, g:form, g:link, and g:render express presentation flow without turning templates into application code.
- 🔎 A key 2026 finding is that Groovy Server Pages are not obsolete, but their strongest fit is server-rendered Grails UI where the team already benefits from Grails conventions and tag libraries.
- 🔌 JSON Views are usually a better boundary for API-first or JavaScript-heavy clients, while Jakarta Pages remains a standards-based option for Jakarta EE applications rather than a drop-in Grails replacement.
- ✅ Teams should choose GSP when it shortens the delivery path, and move away from it when browser-side state, independent front-end deployment, or API reuse becomes the dominant requirement.
Groovy Server Pages are still a supported server-side view layer in Apache Grails in 2026, even as API-first front ends dominate many new web stacks. The telling detail is that the Apache Grails plugin catalog lists GSP 7.2.2 as released on August 2, 2026, alongside active Grails 7 maintenance, so GSP is not abandoned legacy code. Its best use is simply narrower than it once was. For teams building a conventional Grails application, it remains a direct way to turn controller models into HTML without adding a separate JavaScript application, build pipeline, and client-side state layer (Apache Grails, 2026a).
The practical question is not whether server rendering is old. It is whether the rendering boundary matches the product. A form-heavy admin portal, internal workflow tool, or content-oriented application can benefit from a view technology that already understands Grails URL mappings, validation messages, forms, layouts, and tag libraries. Developers who need a refresher on the programming building blocks behind expressions, conditionals, loops, and functions can use the linked foundation guide before moving into GSP-specific syntax.
Our desk reviewed the current Apache Grails documentation, the live GSP plugin catalog, recent Grails release history, Jakarta Pages 4.0, and related Grails security guidance. We did not find a credible, current market-share figure for GSP usage, so this article does not invent one. Instead, it evaluates what the framework officially supports, how the view pipeline works, where maintainability problems appear, and when a different rendering model is the more sensible engineering choice.
How the Grails View Pipeline Actually Works
GSP sits at the view end of Grails’ model-view-controller flow. A controller action can return a map such as [book: Book.get(params.id)]. By convention, Grails can render the matching view, or the controller can name a view explicitly with render(view: ‘show’). The template then reads model values with expressions such as ${book.title}. Current Grails documentation places GSP files in grails-app/views and describes GSP as the framework’s view technology for server-rendered markup (Apache Grails, 2026b).
For Groovy Server Pages, that convention is more than a directory preference. It reduces the amount of routing and template plumbing a team has to maintain. In a small application, a request can move from URL mapping to controller to model to view with very little ceremony. The same simplicity is why developers should understand the local server process itself. The site’s localhost:8080 guide is useful background for recognizing the difference between a template bug, a server startup failure, and a port-level connectivity problem during development.
A minimal controller and view make the boundary clear. The controller fetches or assembles data. The GSP renders it. Once database queries, authorization policy, pricing calculations, or network calls start appearing in the template, the boundary has already failed.
class BookController {
def show() {
[book: Book.get(params.id)]
}
}
<html>
<head><title>${book.title}</title></head>
<body>
<h1>${book.title}</h1>
<p>Author: ${book.author}</p>
<g:if test=”${book.available}”>
<span>Available</span>
</g:if>
<g:else>
<span>Checked out</span>
</g:else>
</body>
</html>
The Syntax That Matters Most
The most useful GSP syntax is deliberately small. Expressions output values. Tags control presentation flow. Templates and layouts keep repeated markup out of individual pages. Scriptlets exist, but the official guide discourages embedding Groovy logic directly in GSP because mixed application code and markup becomes difficult to test and maintain (Apache Grails, 2026b).
Built-in tags use the g: namespace. g:if and g:else handle conditional display, g:each iterates over collections, g:link generates application links that respect URL mappings, g:form builds controller-aware forms, and g:render inserts reusable templates. Tags can also be called as methods in GSPs, controllers, and tag libraries, which gives Grails a compact way to reuse rendering behavior without introducing another templating language.
Custom tag libraries are valuable when repeated presentation behavior has a stable meaning across the application. Current documentation recommends method-based tag definitions in classes placed under grails-app/taglib. The design test is the same one that applies to Java architecture: extract a boundary when it reduces repeated change or clarifies responsibility, not simply because abstraction is possible. The site’s SOLID principles Java guide develops that trade-off in more depth.
| Syntax | Purpose | Use it for |
| ${expression} | Outputs a Groovy expression | Values already prepared in the model |
| <% … %> | Runs embedded Groovy code | Legacy or exceptional cases; avoid complex logic |
| <%– … –%> | Server-side GSP comment | Notes that should not reach the HTML response |
| <g:if> / <g:else> | Conditional rendering | Presentation decisions |
| <g:each> | Iteration | Lists and repeated markup |
| <g:link> | Application-aware link | Links that follow Grails URL mappings |
| <g:form> | Controller-aware form | Server-rendered form submission |
| <g:render> | Renders a template | Reusable fragments |
Templates, Layouts, and the Point Where Reuse Pays Off
Grails templates use an underscore-prefixed file convention, such as _book.gsp, and can be rendered with g:render. They are a good fit for repeated fragments such as table rows, cards, navigation elements, or form groups. A template can receive a model, so the parent view does not need to expose every local variable globally.
Layouts solve a different problem. They wrap whole pages with shared structure such as the document head, global navigation, and content shell. Grails 7 moved to SiteMesh 3 as part of its modernized web stack, and the Grails 7 release line continues to document layout support in the web layer (Apache Grails, 2025; Apache Grails, 2026b). The practical benefit is consistent page chrome without duplicating the same outer HTML in every view.
The hidden cost appears when a project creates too many tiny fragments with unclear ownership. If opening one page requires tracing five templates, three tags, and a layout to understand a single field, reuse has become navigation overhead. A useful rule is to extract markup when it is repeated, conceptually named, or independently testable. Otherwise, local clarity can be more valuable than maximum reuse.
GSP vs JSP vs JSON Views
Groovy Server Pages are often compared with JSP because both render on the server and mix markup with expressions and tags. The similarity is real, but the ecosystem boundary is different. GSP is Grails-specific and uses Groovy semantics plus Grails tags. Jakarta Pages 4.0, the modern specification behind JSP, is a Jakarta EE standard that compiles page templates into Jakarta Servlets and integrates with Jakarta Expression Language and tag libraries (Eclipse Foundation, 2024).
JSON Views solve a different problem. Grails documentation positions them as the preferred view technology when the response is JSON rather than markup. For an application whose browser, mobile client, and partner integrations all need the same API, JSON Views can create a cleaner contract than rendering HTML and then building a second API beside it. For a server-driven web UI, GSP can still be the shorter path.
| Dimension | GSP | Jakarta Pages (JSP) | Grails JSON Views |
| Primary output | HTML or other markup | HTML/XML or textual templates | JSON |
| Main ecosystem | Apache Grails | Jakarta EE | Apache Grails |
| Expression model | Groovy expressions | Jakarta Expression Language plus page features | Groovy-based JSON view DSL |
| Best fit | Server-driven Grails UI | Jakarta EE server pages | API-first Grails applications |
| Framework coupling | High to Grails | High to Jakarta servlet stack | High to Grails, low to browser UI |
| Client independence | Lower | Lower | Higher |
Security Is Mostly About Output Boundaries
The security risk in any server-side template is not the presence of an expression. It is whether untrusted data crosses into HTML, JavaScript, URLs, or attributes without the correct encoding. Grails security documentation states that values in ${} expressions are HTML-escaped by default in current generated applications and that standard GSP tags are designed to escape relevant values. It also warns that developers can still create XSS exposure by disabling or bypassing encoding (Apache Grails, 2026c).
That makes raw output a code-review event, not a convenience. If trusted HTML must be rendered, the trust decision should happen before the template, with clear provenance and sanitization rules. A view should not decide that user-provided content is safe because it happens to look like markup.
Forms deserve the same discipline. Grails provides controller-aware form tags and supports synchronizer-token handling for duplicate submissions. Newer Grails 7 work also added CSRF-aware behavior to g:form when Spring Security CSRF protection is enabled. These features reduce boilerplate, but they do not replace authorization checks, server-side validation, secure cookies, or threat-focused testing.
Where GSP Becomes Expensive
The first cost is coupling. A GSP normally assumes a Grails controller model and Grails tag environment. That is productive inside a Grails monolith, but it means the view is not a neutral artifact that can be moved to another runtime. Teams planning an independent front-end organization or multi-client API should treat that coupling as an architectural choice, not an incidental implementation detail.
The second cost is mixed responsibility. Scriptlets make it easy to place calculations beside markup, and convenience can hide the problem until testing becomes painful. The official guidance discourages complex embedded logic for exactly this reason. Put domain decisions in services, request coordination in controllers, and presentation-specific branching in the view.
The third cost is front-end interaction density. If a page needs substantial browser-side state, offline behavior, real-time synchronization, component-level routing, or independent deployment, a server template can become a shell around a JavaScript application rather than the real UI layer. At that point, maintaining both GSP conventions and a full client framework can be more expensive than choosing one clear primary rendering model. AI-assisted coding tools can accelerate either path, but the site’s AI pair programmer guide shows why narrow tasks, repository context, and tests matter more than raw generation speed.
A fourth cost is build and upgrade awareness. Since Grails 3.3, GSP has been an independent plugin rather than part of Grails core. That separation is healthy because it gives the view layer its own release lifecycle, but it also means upgrades should verify the Grails, GSP, Gradle, Groovy, Spring Boot, and SiteMesh combinations actually used by the application. The Apache plugin catalog is the most reliable place to check supported GSP versions before a framework upgrade.
A Maintainable GSP Workflow for 2026
A maintainable workflow starts with a thin view contract. Give each page a deliberate model rather than exposing large domain graphs by accident. That reduces hidden database access, makes null handling explicit, and makes controller tests easier to understand.
Next, keep GSP logic presentation-shaped. A conditional that decides whether to show an ‘Available’ badge belongs in the view when the underlying availability state is already computed. A conditional that calculates availability from inventory records does not. This boundary lowers the number of reasons a template changes.
Then use templates and tag libraries in stages. Start local. Extract repeated fragments only after the repetition is visible or the concept has a stable name. Test custom tag libraries directly, and keep layouts focused on shared page structure. For Java-heavy backend workflows around the same application, the site’s JAVE2 guide is a useful example of keeping a focused library behind a clear application boundary rather than scattering shell-level concerns across controllers and views.
Finally, test rendered behavior at the right layer. Unit tests should cover controllers, services, and tag libraries. Integration or functional tests should verify critical page rendering, forms, authorization, and navigation. Browser tests are especially important for output that mixes server rendering with client scripts because escaping, DOM insertion, and timing bugs can cross framework boundaries.
| Layer | Keep here | Avoid here |
| Controller | Request coordination, model assembly, redirects | Heavy domain rules and view markup |
| Service/domain | Business rules, transactions, integration logic | HTML presentation decisions |
| GSP view | Markup, simple display conditions, tag use | Queries, network calls, authorization policy |
| Tag library | Reusable presentation behavior | General business services |
| Template/layout | Reusable markup and page shell | Hidden application workflow |
The Future of Groovy Server Pages in 2027
The most credible 2027 outlook is continuity with a narrower center of gravity. Apache Grails remains actively maintained, the GSP plugin had current 7.1.x and 7.2.x releases in August 2026, and Grails 8 is being developed in milestone releases. That is evidence of ongoing engineering, not evidence that every new Grails UI should use GSP (Apache Grails, 2026a).
Two trends will shape the decision. First, Java and Groovy back ends increasingly serve several clients, which favors explicit JSON contracts. Second, server rendering remains attractive for applications where fast first response, simpler deployment, forms, and low front-end state are more important than independent client release cycles. GSP fits the second category well because it is deeply integrated with Grails conventions.
The technical roadmap also matters. Grails 8 milestones raise the platform baseline and continue work around the web layer and GSP rendering. Teams should expect compatibility work around newer Java, Spring Boot, Gradle, and Jakarta versions rather than a frozen template engine. The uncertainty is feature emphasis. A maintained GSP plugin does not guarantee that ecosystem investment will shift back from API-first architectures. The sensible 2027 strategy is therefore to treat GSP as a supported Grails capability with a clear use case, not as the default answer to every user interface problem.
Current Maintenance Signals
For Groovy Server Pages, release activity is more useful than vague claims that a templating technology is either ‘modern’ or ‘legacy.’ The current project records show an active maintenance line and an active next-major line. Those signals support continued use for existing Grails applications while still leaving architecture choice open for new products.
| Signal | Verified 2026 status | Why it matters |
| GSP stable line | GSP 7.2.2 listed August 2, 2026 | The view plugin is receiving current releases. |
| GSP next-major line | GSP 8.0.0-M5 listed August 2, 2026 | Work continues alongside Grails 8 milestones. |
| Grails release activity | 7.2.x release workflow active in August 2026 | The parent framework remains under active maintenance. |
| Architecture alternatives | JSON Views remain documented beside GSP | Grails supports more than one view boundary. |
Takeaways
- Groovy Server Pages remain actively maintained within Apache Grails, with GSP 7.2.2 listed in August 2026.
- Keep the controller responsible for request coordination and the GSP responsible for presentation, not business decisions.
- Prefer GSP tags, templates, and layouts over scriptlets when they make presentation intent clearer and easier to test.
- Use JSON Views when the same data must serve multiple clients or a JavaScript front end owns most application state.
- Treat raw output, custom encoding, and client-side DOM insertion as security review points because XSS risk crosses rendering layers.
- Upgrade Grails and the GSP plugin as a compatibility set rather than assuming the view layer is inseparable from core.
- Choose the rendering model that minimizes total system complexity, not the one that appears newest.
Conclusion
GSP still makes sense when a Grails application benefits from server-rendered HTML, conventional controller-to-view flow, built-in tags, layouts, and a single deployment unit. Its strength is integration. The same strength creates its main limitation: the view is intentionally coupled to Grails, so it becomes less attractive when the product needs an independently deployed front end or a shared API for several clients.
The best architecture is therefore conditional rather than ideological. Groovy Server Pages work best for pages whose complexity stays on the server and whose interactivity can remain modest. Keep business rules outside the template, make escaping decisions explicit, and extract reusable fragments only when they improve clarity. Choose JSON Views or another client architecture when data contracts and browser-side state become the center of the system. In 2026, the evidence supports a balanced conclusion: GSP is maintained, useful, and mature, but valuable precisely because teams can identify where it fits and where it does not.
Frequently Asked Questions
What are Groovy Server Pages used for?
They are Grails view templates used to render HTML and other markup on the server. A controller usually supplies a model, and the GSP reads that model with expressions and Grails tags. They are especially practical for server-driven web interfaces that already use Grails routing, forms, validation, and layouts.
What is the difference between JSP and GSP?
JSP, now standardized as Jakarta Pages, is part of the Jakarta EE ecosystem and compiles page templates into servlets. GSP is specific to Grails, uses Groovy expressions, and integrates directly with Grails tags, URL mappings, controllers, layouts, and plugins. The concepts overlap, but the runtime and framework contracts differ.
How do g:each and g:if work in GSP?
g:if conditionally renders its body when its test expression is true. g:each iterates over a collection and exposes each item through a variable. They are presentation tags, so complex domain calculations should happen before the model reaches the view.
How does Grails layout decoration work with SiteMesh?
A Grails layout provides shared outer page structure such as the head, navigation, and content shell. Views can select a layout, and Grails also supports convention-based layout resolution. Modern Grails 7 uses SiteMesh 3 in its web stack, keeping page decoration separate from individual view content.
How do you build custom tag libraries in Grails?
Create a Groovy class ending in TagLib under grails-app/taglib and define tag methods using supported signatures. Current Grails documentation recommends method-based tags. Use custom tags for stable, repeated presentation behavior, and keep larger HTML fragments in templates when markup is the primary concern.
Are JSON Views better than GSP in Grails?
Not universally. JSON Views are better when the application is API-first, serves several clients, or gives a JavaScript front end ownership of most UI state. GSP is often simpler when Grails itself owns the page lifecycle and the product benefits from server-rendered forms and navigation.
Is GSP secure against cross-site scripting by default?
Current Grails guidance states that GSP expressions in generated applications use HTML encoding by default and standard tags escape relevant values. That lowers risk but does not eliminate it. Raw output, disabled codecs, unsafe DOM insertion, and untrusted HTML still require explicit review and testing.
Methodology
This article was researched on August 24, 2026. Primary validation used Apache Grails documentation for the web layer, configuration, security, and current plugin listings; Apache Grails release announcements and release records; and the Eclipse Foundation’s Jakarta Pages 4.0 specification page for the JSP comparison. Current release signals were cross-checked against Apache Grails project release activity.
The analysis has limits. No reliable, current public figure for GSP market share or installed production applications was found, so no adoption percentage is claimed. We also did not benchmark GSP rendering throughput against modern JavaScript frameworks because that result would depend heavily on application shape, caching, database behavior, client hydration, and deployment topology.
References
Apache Grails. (2025, October 18). Apache Grails 7.0.0 release announcement.
Apache Grails. (2026a). Grails plugins: GSP release catalog.
Apache Grails. (2026b). The Grails Framework: The Web Layer, Groovy Server Pages.
Apache Grails. (2026c). The Grails Framework: Security and cross-site scripting prevention.
Apache Grails. (2026d). The Grails Framework: Configuration.
Eclipse Foundation. (2024). Jakarta Pages 4.0.