<?xml version="1.0" encoding="UTF-8"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0"><channel><title>Blog | Grails Framework</title><link>https://grails.apache.org</link><description>A powerful Groovy-based web application framework for the JVM built on top of Spring Boot</description><pubDate>Wed, 08 Apr 2026 08:35:29 GMT</pubDate><item><title>James Daugherty and Mattias Reichel Named 2026 Grails® Community Rock Stars</title><link>https://grails.apache.org/blog/2026-02-03-grails-community-rockstars.html</link><description><![CDATA[</p>
<p>The Grails Community is thrilled to kick off 2026 by recognizing two outstanding volunteers for their exceptional contributions. As we continue to build on the momentum from Grails 7 and look ahead to future innovations, it's community leaders like these who drive the framework forward.</p>
<p>This year, we're proud to award the <a href="/community.html">Grails Community Rock Star</a> honors to <a href="https://github.com/jdaugherty">James Daugherty</a> and <a href="https://github.com/matrei">Mattias Reichel</a>. Both have demonstrated unwavering dedication through code contributions, build improvements, documentation, plugin development, community support, and leadership in advancing Grails. Without their thousands of hours of volunteer work, Grails 7 and the successful transition to The Apache Software Foundation would not have been possible.</p>
<h2>Mattias Reichel</h2>
<p><a href="https://github.com/matrei">Mattias Reichel</a> has made significant impacts across key repositories, including grails-core, grails-spring-security, grails-redis, grails-static-website, and many more. His technical contributions span critical areas of the framework, from security enhancements to performance optimizations and modern tooling integrations. He brought deep historical knowledge of the framework's architecture and design principles to help guide our work.</p>
<p>Mattias played a crucial role in Grails 7 development, contributing to dependency updates, build system improvements, and feature enhancements that strengthen the framework's foundation. His work on Geb, Gradle, Develocity, and GitHub Workflows moved all of those areas significantly forward.</p>
<p>As a volunteer contributor, Mattias consistently supports the Grails community through thoughtful code reviews, comprehensive testing, and detailed issue reporting. He actively participates in technical discussions and weekly community meetings, offering insights that shape the framework's direction. His ability to identify and address edge cases, propose feature improvements, and open well-researched issues in grails-core demonstrates both technical depth and a user-focused mindset.</p>
<p>Beyond code contributions, Mattias helps maintain the project's infrastructure and documentation, ensuring that the Grails ecosystem remains accessible and welcoming to developers at all levels. His collaborative approach and willingness to mentor others make him an invaluable community member.</p>
<p>We're deeply appreciative of his passion, technical excellence, collaborative spirit, and leadership in making Grails stronger for everyone.</p>
<h2>James Daugherty</h2>
<p><a href="https://github.com/jdaugherty">James Daugherty</a> has been a pivotal force in the Grails ecosystem, particularly in driving Grails 7 development. His technical expertise shines through in numerous contributions to grails-core, asset-pipeline, grails-quartz, grails-github-actions, grails-gradle-publish, grails-website, and many more, including critical updates that make the framework modern and robust.</p>
<p>James played instrumental roles in Grails 7.x releases, streamlining dependencies, enhancing performance, fixing critical issues, and supporting features like reproducible builds, SBOMs, and the comprehensive build system overhaul. His deep understanding of the framework's architecture enables him to tackle complex challenges that benefit the entire community.</p>
<p>As a volunteer leader, James exemplifies how leadership naturally emerges from dedicated contributors. He serves as a caring and supportive steward of the technology, guiding technical discussions to productive outcomes even when opinions differ. In community channels like Grails Slack and mailing lists, he provides guidance on migrations and integrations, answers user questions with patience and clarity, and actively mentors developers navigating complex scenarios.</p>
<p>James' contributions extend far beyond code, demonstrating exceptional leadership and character in fostering the project's success. His efforts boost productivity across the ecosystem and position Grails for long-term success. We're deeply appreciative of his commitment to both the codebase and community, making him a true Grails leader and an invaluable teammate.</p>
<h2>Thank You, James and Mattias!</h2>
<p>On behalf of the entire Grails community, thank you, James and Mattias, for your passion and tireless dedication. Your contributions in code, collaboration, and innovation make Grails stronger for everyone. You are true Grails leaders and invaluable assets to our community. Please keep up the fantastic work!</p>
<p>We invite the entire community to join us in congratulating James and Mattias. Share your thanks on the mailing list, GitHub, Grails Slack, LinkedIn, or X.</p>
<p>If you're inspired to contribute to Grails, check out our <a href="https://github.com/apache/grails-core/blob/HEAD/CONTRIBUTING.md">contribution guidelines</a> and help shape the future of the framework!</p>]]></description><author>James Fredley</author><guid>2026-02-03-grails-community-rockstars</guid><pubDate>Tue, 03 Feb 2026 00:00:00 GMT</pubDate></item><item><title>Apache Grails [%version] - Release Announcement</title><link>https://grails.apache.org/blog/2025-10-18-introducing-grails-7.html</link><description><![CDATA[</p>
<p>The Apache Grails community is excited to announce the 7.0.0 release of the Apache Grails Framework!</p>
<p>This achievement reflects the dedication of our community and underscores the strength of the ASF's open source ecosystems.</p>
<p>Thousands, upon thousands, of hours have gone into this release, and we are incredibly grateful to everyone who contributed their time and expertise to make it happen.</p>
<p>Additionally, Grails has officially graduated from incubation, under the Apache Groovy project, to become a Top-Level Project (TLP) at The Apache Software Foundation (ASF).  Read more about this milestone in our <a href="/blog/2025-10-07-apache-grails-graduation-top-level-project.html">announcement blog post</a>.</p>
<h2>Why use Grails?</h2>
<ul>
<li>Rapid application development with high developer productivity</li>
<li>Full-stack web framework with everything included</li>
<li>DRY &amp; Convention-Over-Configuration: Less boilerplate, sensible defaults</li>
<li>Gentle learning curve with Apache Groovy for productivity</li>
<li>&quot;Framework of frameworks&quot; built on Apache Groovy, Spring Boot, Spring Framework, Jakarta EE, and Hibernate for enterprise foundations</li>
</ul>
<h2>Download Source Code and Binary Distributions</h2>
<p><a href="/download.html">Apache Grails Downloads</a></p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0, check out the following blog posts:</p>
<ul>
<li><a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1</a></li>
<li><a href="/blog/2025-03-05-grails-7-m3.html">Grails 7.0.0-M3</a></li>
<li><a href="/blog/2025-06-10-grails-7-m4.html">Grails 7.0.0-M4</a></li>
<li><a href="/blog/2025-07-15-grails-7-m5.html">Grails 7.0.0-M5</a></li>
<li><a href="/blog/2025-08-10-grails-7-rc1.html">Grails 7.0.0-RC1</a></li>
<li><a href="/blog/2025-09-11-grails-7-rc2.html">Grails 7.0.0-RC2</a></li>
</ul>
<h3>7.0.0 Changes:</h3>
<ul>
<li><code>org.apache.grails:grails-i18n</code> has been changed to <code>org.apache.grails.i18n:grails-i18n</code> and is provided transitively, remove <code>org.apache.grails:grails-i18n</code> from your dependency list</li>
<li>Bump github/codeql-action from 3 to 4 @dependabot[bot] (#15135)</li>
<li>Take snapshot prior to mongo update then mark any changes during beforeUpdate and update events as dirty. @codeconsole (#15143)</li>
<li>Remove method from GradleUtils @matrei (#15126)</li>
<li>Update grails-publish and add organization to pom @matrei (#15138)</li>
<li>Add kapa.ai AI assistant widget to docs templates @jamesfredley (#15134)</li>
<li>Update documentation links to grails.apache.org/docs @jamesfredley (#15131)</li>
<li>Update release workflow to publish doc to grails-website @jamesfredley (#15128)</li>
<li>Use consistent ISO-8601 formatting for rendering JSON Date, Calendar, LocalDateTime, and Instant properties @codeconsole (#15121)</li>
<li>Centralizing Gradle Logic @jdaugherty (#15114)</li>
<li>Instant should persist the same way (BsonType.DATE_TIME) as LocalDateTime and Date @codeconsole (#15111)</li>
<li>Add additional Sitemesh -&gt; grails-layout class and property moves/changes to docs @jamesfredley (#15112)</li>
<li>Docs GSP Javascript: Removed deprecated example @dauer (#15106)</li>
<li>15100 - remove previous optimization for older JDKs &amp; larger projects @jdaugherty (#15104)</li>
<li>Update cyclonedx to 2.4.1 @matrei (#15099)</li>
<li>#14993 - Remove spring loaded @jdaugherty (#15096)</li>
<li>Update asset-pipeline and bom versions to 5.0.19 @jamesfredley (#15092)</li>
<li>Update asset-pipeline and bom versions to 5.0.18 @jamesfredley (#15089)</li>
<li>Add 'migrations' to grailsAppResourceDirs resolve duplicates @jamesfredley (#15084)</li>
<li>Gorm service enhancements @codeconsole (#15070)</li>
<li>Update spring-boot.version to 3.5.6 @jamesfredley (#15080)</li>
<li>Issue-15061 Grails-doc bug in render example @dauer (#15072)</li>
<li>Support for Gorm Entities with same name, but different packages @codeconsole (#15036)</li>
<li>Merge v7.0.0-RC2 &amp; Back to snapshot @jdaugherty (#15068)</li>
<li>Remove additivity attribute from StackTrace logger @jamesfredley (#15066)</li>
<li>Add upgrade notes for hibernate.cache.region.factory_class @jamesfredley (#15063)</li>
<li>Issue-14172 Out Of Date Instructions For Creating A Plugin @dauer (#15062)</li>
<li>Revise upgrading guide for Grails 7: grails-i18n plugin @jamesfredley (#15060)</li>
<li>Add external references for dependency graph @jamesfredley (#15054)</li>
<li>Update GitHub references and default project slug for documentation @jamesfredley (#15053)</li>
<li>Update gradleToolingApiVersion to 8.14.3 @jamesfredley (#15047)</li>
<li>Update grails-publish-plugin version to 0.0.1-SNAPSHOT @jamesfredley (#15050)</li>
</ul>
<p>🚀 Features</p>
<ul>
<li>Remove Neo4j Forge Feature @jamesfredley (#15107)</li>
<li>Remove LogbackGroovy logging feature temporarily for 7.0.0 @jamesfredley (#15098)</li>
<li>15048 - feature: reproducible gorm service implementations @jdaugherty (#15097)</li>
<li>15085 - set banner in constructor so commands &amp; scripts have it defaulted @jdaugherty (#15094)</li>
<li>feature: generate sboms for all published binary jar files @jdaugherty (#15087)</li>
<li>14977 - multiproject reloading support @jdaugherty (#15076)</li>
<li>feature: allow disabling micronaut configuration by the grails plugin @jdaugherty (#15069)</li>
</ul>
<p>💡 Improvements</p>
<ul>
<li>15079 - grails-micronaut improvements @jdaugherty (#15105)</li>
<li>fix(geb): minor improvements @matrei (#15103)</li>
</ul>
<p>🐛 Bug Fixes</p>
<ul>
<li>chore: Fix 15102 Removed traces of incubation and PPMC @sbglasius (#15115)</li>
<li>fix(geb): minor improvements @matrei (#15103)</li>
<li>fix: 13851 - move GrailsMessageSourceUtils @matrei (#15101)</li>
<li>Geb 8 @matrei (#15067)</li>
<li>fix: wrapper should only consider release types that are a higher priority than the wrapper version when packaged @jdaugherty (#15052)</li>
<li>fix: remove leftover grails-doc plugin declaration @matrei (#15051)</li>
<li>🔧 Maintenance</li>
<li>Test Demonstrating Mongo beforeUpdate changes are not persisted @codeconsole (#15142)</li>
<li>gson views date/calendar should have millisecond precision to match standard rendering @codeconsole (#15130)</li>
<li>Web profile jar artifact restore @jamesfredley (#15125)</li>
<li>Test publishing docs to /docs on apache/grails-website @jamesfredley (#15123)</li>
<li>First Step in optimizing GSP Performance on Grails 7. Safe small optimizations to start @davydotcom (#15109)</li>
<li>chore: Fix 15102 Removed traces of incubation and PPMC @sbglasius (#15115)</li>
<li>15048 - feature: reproducible gorm service implementations @jdaugherty (#15097)</li>
<li>build reproducibility &amp; verification issues after testing 7.0.0-RC2 @jdaugherty (#15055)</li>
</ul>
<p>Full Changelog: <a href="https://github.com/apache/grails-core/compare/v7.0.0-RC2...v7.0.0">v7.0.0-RC2...v7.0.0</a></p>
<p>Upgrade instructions are available in the <a href="https://grails.apache.org/docs/7.0.0/guide/upgrading.html#upgrading60x">documentation</a>.</p>
<h2>Additional Releases</h2>
<p>The following plugins and tools are being released alongside Grails 7.0.0:</p>
<h3>Grails Spring Security 7.0.0</h3>
<p>See the release page: <a href="https://github.com/apache/grails-spring-security/releases/tag/v7.0.0">https://github.com/apache/grails-spring-security/releases/tag/v7.0.0</a></p>
<h3>Grails Quartz 4.0.0</h3>
<p>See the release page: <a href="https://github.com/apache/grails-quartz/releases/tag/v4.0.0">https://github.com/apache/grails-quartz/releases/tag/v4.0.0</a></p>
<h3>Grails Redis 5.0.0</h3>
<p>See the release page: <a href="https://github.com/apache/grails-redis/releases/tag/v5.0.0">https://github.com/apache/grails-redis/releases/tag/v5.0.0</a></p>
<h3>Grails GitHub Actions 1.0.1</h3>
<p>See the release page: <a href="https://github.com/apache/grails-github-actions/releases/tag/v1.0.1">https://github.com/apache/grails-github-actions/releases/tag/v1.0.0</a></p>
<h3>Grails Gradle Publish 0.0.2</h3>
<p>See the release page: <a href="https://github.com/apache/grails-gradle-publish/releases/tag/v0.0.2">https://github.com/apache/grails-gradle-publish/releases/tag/v0.0.2</a></p>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.19 (now cloud.wondrify.asset-pipeline)</li>
<li>Spring Framework 6.2.11</li>
<li>Spring Boot 3.5.6</li>
<li>See all in the <a href="https://grails.apache.org/docs/7.0.0/ref/Versions/Grails%20BOM.html">grails-bom</a>.</li>
</ul>
<h2>Generating a new Grails 7.0.0 application with Grails Forge</h2>
<p>Try out Grails today by visiting our online application generator <a href="https://start.grails.org">Grails Forge</a>. This is the quickest and the recommended way to get started with Grails.</p>
<p>After installing JetBrains' IntelliJ IDEA 2025.2 or later and the <a href="https://plugins.jetbrains.com/plugin/18504-grails">Grails Plugin</a>, the Grails Application Forge will also be available under New Project in IntelliJ IDEA.</p>
<p>Within your newly generated project you can access the Grails CLIs with the Grails Wrapper.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<p>grail-shell-cli</p>
<pre><code class="language-shell">grailsw
</code></pre>
<p>grails-forge-cli</p>
<pre><code class="language-shell">grailsw -t forge
</code></pre>
<h2>Installing Grails CLIs 7.0.0 with SDKMan</h2>
<p>Alternatively, you can quickly install Grails 7.0.0 CLIs (grails-shell-cli and grails-forge-cli) using <a href="https://sdkman.io">SDKMan</a>.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0:</p>
<pre><code class="language-shell">sdk install grails 7.0.0
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<p>The Grails Shell CLI can be accessed as:</p>
<pre><code class="language-shell">grails
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-shell-cli
</code></pre>
<p>The Grails Forge CLI can be accessed as:</p>
<pre><code class="language-shell">grails -t forge
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-forge-cli
</code></pre>
<h2>Upgrading Your Existing Applications to Grails 7.0.0</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA 2025.2 or later).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. <a href="https://grails.apache.org/docs/7.0.0/guide/upgrading.html#upgrading60x">See Upgrade Guide</a></p>
<ul>
<li>remove <code>org.apache.grails:grails-i18n</code> from your dependency list, it has changed to <code>org.apache.grails.i18n:grails-i18n</code> and is provided transitively by default</li>
</ul>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com">Renovate</a> or
<a href="https://dependabot.com">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0.</p>
<h2>Why should you try out Grails 7.0.0?</h2>
<ul>
<li><strong>Leverage cutting-edge foundations</strong>: Built on the latest Groovy 4.0.28, Spring Framework 6.2.11, Spring Boot 3.5.6, Jakarta EE, and an optimized Asset Pipeline for seamless, modern web development.</li>
<li><strong>Boost productivity with fresh enhancements</strong>: Packed with bug fixes, performance tweaks, and innovative features like containerized browser testing via Geb, external configuration integration streamlining your workflow.</li>
<li><strong>Celebrate a historic milestone</strong>: As the inaugural release under Grails' new status as an Apache Top-Level Project, it underscores two decades of innovation and the vibrant open-source community's unwavering commitment.</li>
<li><strong>Invest in the future</strong>: This version drives ongoing innovation, backed by an active Grails community ensuring support, updates, and evolving capabilities tailored to your needs.</li>
</ul>
<h2>Grails Release Schedule</h2>
<ul>
<li><strong>Grails 7.0.0 Release</strong>: Officially released on <span class="date">October 18, 2025</span>, as the first stable version under the Apache Software Foundation (ASF).</li>
<li><strong>Grails 7.0.x Patch Releases</strong>: Scheduled at least monthly to align with Spring Boot's monthly cadence; additional releases may occur as needed for urgent fixes.</li>
<li><strong>Grails 7.0.x Support Period</strong>: Full updates and maintenance available until the Spring Boot 3.5.x end-of-life on June 30, 2026.</li>
<li><strong>Grails 8.0.x Development</strong>: Set to commence in late November 2025, immediately following the Spring Boot 4.0.0 general availability release.</li>
<li><strong>Grails 6.x End-of-Life</strong>: Version 6.2.3 (released January 3, 2025) marks the final 6.2.x update and the last pre-ASF release, driven by the Spring Boot 2.7.x end-of-life.</li>
</ul>
<h2>Apache Grails Mailing Lists</h2>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 20 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
<li><a href="https://github.com/puneetbehl">Puneet Behl</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/rainboyan">Michael Yan</a></li>
<li><a href="https://github.com/JudeRV">Jude Vargas</a></li>
<li><a href="https://github.com/dauer">Thomas Rasmussen</a></li>
<li><a href="https://github.com/irllyliketoast">Laura Estremera</a></li>
<li><a href="https://github.com/shadowchaser000">Hallie Uczen</a></li>
<li><a href="https://github.com/jprinet">Jérôme Prinet</a></li>
<li><a href="https://github.com/lynchie14">Stephen Lynch</a></li>
<li><a href="https://github.com/dreewh">Andrew Herring</a></li>
<li><a href="https://github.com/nobeans">Yasuharu Nakano</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/felixscheinost">Felix Scheinost</a></li>
<li><a href="https://github.com/cbmarcum">Carl Marcum</a></li>
<li><a href="https://github.com/eugene-kamenev">Eugene Kamenev</a></li>
<li><a href="https://github.com/huangyucaigit">yucai</a></li>
<li><a href="https://github.com/gandharvas">gandharvas</a></li>
<li><a href="https://github.com/ihuangyucai">ihuangyucai</a></li>
<li><a href="https://github.com/zyro23">zyro</a></li>
</ul>
<p>Recent Contributors by Project:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-core</a></li>
<li><a href="https://github.com/apache/grails-spring-security/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-spring-security</a></li>
<li><a href="https://github.com/apache/grails-static-website/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-static-website</a></li>
<li><a href="https://github.com/apache/grails-forge-ui/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-forge-ui</a></li>
<li><a href="https://github.com/apache/grails-quartz/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-quartz</a></li>
<li><a href="https://github.com/apache/grails-gradle-publish/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-gradle-publish</a></li>
<li><a href="https://github.com/apache/grails-redis/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-redis</a></li>
<li><a href="https://github.com/apache/grails-github-actions/graphs/contributors?from=April+18%2C+2025&amp;to=October+18%2C+2025">grails-github-actions</a></li>
</ul>
<p><a href="https://github.com/search?q=repo%3Aapache%2Fgrails-core+repo%3Aapache%2Fgrails-spring-security+repo%3Aapache%2Fgrails-static-website+repo%3Aapache%2Fgrails-forge-ui+repo%3Aapache%2Fgrails-quartz+repo%3Aapache%2Fgrails-gradle-publish+repo%3Agrails-redis+repo%3Agrails-github-actions+is%3Apublic&amp;type=commits&amp;s=committer-date&amp;o=desc">Combined Commit List</a></p>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-10-18-introducing-grails-7</guid><pubDate>Sat, 18 Oct 2025 00:00:00 GMT</pubDate></item><item><title>Apache Grails Graduates to Top-Level Project at The Apache Software Foundation</title><link>https://grails.apache.org/blog/2025-10-07-apache-grails-graduation-top-level-project.html</link><description><![CDATA[</p>
<p>The Apache Grails team is excited to announce that Apache Grails has officially graduated from incubation under the Apache Groovy project to become a Top-Level Project (TLP) at The Apache Software Foundation (ASF). This achievement reflects the dedication of our community and underscores the strength of the ASF's open source ecosystems.</p>
<p><a href="https://news.apache.org/foundation/entry/the-apache-software-foundation-announces-new-top-level-projects-2">Apache Software Foundation Press Release</a></p>
<p>Apache Grails is a powerful Apache Groovy-based web application framework for the Java Virtual Machine (JVM) built on top of Spring Boot. It enables rapid application development through convention-over-configuration and Don't Repeat Yourself (DRY) principles, making it ideal for productively building full-stack applications with simplicity. Similar to Ruby on Rails, Grails has a nearly 20-year history of evolution and refinement, built on Java Enterprise foundations like Spring Framework, Jakarta EE, and Hibernate.</p>
<p>&quot;Becoming an ASF Top-Level Project signals the beginning of a new chapter for Apache Grails,&quot; said James Fredley, Apache Grails PMC Chair. &quot;With ASF’s support and a thriving contributor community, we look forward to broadening adoption and advancing the project’s capabilities.&quot;</p>
<p>We invite the community to join us in this new chapter—contribute, provide feedback, and help shape the future of Apache Grails!</p>
<h2>Why use Grails?</h2>
<ul>
<li>Rapid application development with high developer productivity</li>
<li>Full-stack web framework with everything included</li>
<li>DRY &amp; Convention-Over-Configuration: Less boilerplate, sensible defaults</li>
<li>Gentle learning curve with Groovy for productivity</li>
<li>&quot;Framework of frameworks&quot; built on Spring Boot, Spring Framework, Jakarta EE, and Hibernate for enterprise foundations</li>
</ul>
<h2>History and Migration Journey</h2>
<p>Work on the Grails framework began in July 2005, with the 0.1 release on March 29, 2006, and the 1.0 release on February 5, 2008. Over the years, ownership transitioned from G2One (2005-2008) to SpringSource (2008-2015), Object Computing (2015-2021), and the Grails Foundation/Unity Foundation (2021-2025), before joining the ASF in 2025. For much of its history, Grails was primarily led by single organizations.</p>
<p>The migration to the ASF was an 18-month process starting in late Spring 2024 alongside Grails 7 development. Motivations included shifting from single-organization dependency to a volunteer-driven model for sustainability, fostering community growth and revitalization with new energy from volunteers, aligning with open-source best practices like the Apache Way (consensus and transparency), enhancing governance through a Project Management Committee (PMC), mailing lists, and voting, and promoting vendor neutrality to encourage broader collaboration.  The key steps to becoming a TLP involved forming a volunteer team, assessing project readiness, submitting an incubation proposal, ensuring the code base met ASF policy, and issuing releases under the ASF.</p>
<p>The development team decided to use a mono-repo approach for the Grails code base to help accelerate compliance with ASF policy. This involved merging 24+ separate GitHub repositories (that also were the result of other combination efforts) into a single code base. Each of these merges required integrating separate build systems &amp; release processes over 100s of commits. Builds for a release went from 3+ weeks to approximately 30 minutes after this effort. The grails-core mono-repo now produces over 325 published jar files across 109 gradle projects with local build times taking anywhere between 2 and 10 minutes (depending on caching &amp; hardware).</p>
<p>With the ability to release, the project turned to meeting ASF policy. The initial goal: changing our maven coordinates. All of the Grails maven coordinates had to switch to a base group of <code>org.apache.grails</code>. This required agreement across the community on package names since conflicts arose due to overlapping coordinates. Significant feedback was given by the community to produce more consistent and predictable coordinate name. As part of this change, a Gradle Plugin (<code>grails-publish</code>) was written to ease publishing our packages. This plugin is now available for any project to use.</p>
<p>Next, ASF security policy requires verifiable builds for projects that use GitHub actions. This required changing the Grails build to be reproducible, upstream changes to several of our dependencies (including contributions to Apache Groovy), and the ability to verify any Grails build independently. A major benefit to the community was that Grails applications can now be made reproducible as well.</p>
<p>The last major goal was licensing compliance. First, every source file had to changed or reviewed for its license headers.  Second, 327 separate artifacts had to be reviewed to ensure we were not distributing an incompatible license. Like the mono repo merge, publishing optimizations, and verifiable builds initiatives, the dev team automated license review by adopting Software Bill of Materials for any published jar file. This ensures we stay compliant and reduces future effort to review licenses.</p>
<p>The final major initiative was automating our release process so that we could release more frequently. This involved developing new GitHub Actions that assisted in every step of the release process. The resulting work is the GitHub Release workflow that will enable future committers to help release Grails without specialized knowledge of our build.</p>
<p>Overall, the changes to Grails can be characterized as a modernization of our build system, licensing compliance, &amp; release process that will ensure Grails survives. The changes will benefit every end Grails application and ensure that Grails is enterprise ready. Over 2,000 commits were made to the grails-core mono-repo alone. 1,247,686 lines were removed from the code base with over 2,631,372 lines changing; many of these changes were incremental to ensure a stable build as significant change was made to the code base.</p>
<p>Releases for grails-core included Milestone 4 (June 2025, the first ASF release), Milestone 5 (July 2025), Release Candidate 1 (August 2025), Release Candidate 2 (September 2025), with the 7.0.0 General Availability expected in October 2025. There are also numerous other releases across the Grails Spring Security plugins, Redis plugin, Quartz plugin, and other supporting projects that were moved to the ASF.</p>
<p>The project passed the ASF board vote on September 24, 2025, officially graduating to TLP status.</p>
<p>We extend our thanks to all contributors who made these advancements possible. Special mentions go to recent contributors across various Grails repositories.</p>
<p>Takeaways from the migration process include establishing early relationships with the ASF Infrastructure team via Slack and JIRA, leveraging incubation mentors for success, planning the end state for codebase and repositories upfront to avoid duplicated efforts, addressing challenges in migrating automated Gradle and GitHub Actions workflows (now serving as a model for Gradle-based projects at the ASF), working with the community to communicate upcoming changes, and consolidating repositories from an initial 100 down to 18 (with 9 active).</p>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 20 years! We’re excited for the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
<li><a href="https://github.com/puneetbehl">Puneet Behl</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/rainboyan">Michael Yan</a></li>
<li><a href="https://github.com/JudeRV">Jude Vargas</a></li>
<li><a href="https://github.com/dauer">Thomas Rasmussen</a></li>
<li><a href="https://github.com/irllyliketoast">Laura Estremera</a></li>
<li><a href="https://github.com/shadowchaser000">Hallie Uczen</a></li>
<li><a href="https://github.com/jprinet">Jérôme Prinet</a></li>
<li><a href="https://github.com/lynchie14">Stephen Lynch</a></li>
<li><a href="https://github.com/dreewh">Andrew Herring</a></li>
<li><a href="https://github.com/nobeans">Yasuharu Nakano</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/felixscheinost">Felix Scheinost</a></li>
<li><a href="https://github.com/cbmarcum">Carl Marcum</a></li>
<li><a href="https://github.com/eugene-kamenev">Eugene Kamenev</a></li>
<li><a href="https://github.com/huangyucaigit">yucai</a></li>
<li><a href="https://github.com/gandharvas">gandharvas</a></li>
<li><a href="https://github.com/zyro23">zyro</a></li>
</ul>
<p>Recent Contributors by Project:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-core</a></li>
<li><a href="https://github.com/apache/grails-spring-security/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-spring-security</a></li>
<li><a href="https://github.com/apache/grails-static-website/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-static-website</a></li>
<li><a href="https://github.com/apache/grails-forge-ui/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-forge-ui</a></li>
<li><a href="https://github.com/apache/grails-quartz/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-quartz</a></li>
<li><a href="https://github.com/apache/incubator-grails-gradle-publish/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-gradle-publish</a></li>
<li><a href="https://github.com/apache/grails-redis/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-redis</a></li>
<li><a href="https://github.com/apache/grails-github-actions/graphs/contributors?from=April+7%2C+2025&amp;to=October+7%2C+2025">grails-github-actions</a></li>
</ul>
<p><a href="https://github.com/search?q=repo%3Aapache%2Fgrails-core+repo%3Aapache%2Fgrails-spring-security+repo%3Aapache%2Fgrails-static-website+repo%3Aapache%2Fgrails-forge-ui+repo%3Aapache%2Fgrails-quartz+repo%3Aapache%2Fincubator-grails-gradle-publish+repo%3Agrails-redis+repo%3Agrails-github-actions+is%3Apublic&amp;type=commits&amp;s=committer-date&amp;o=desc">Combined Commit List</a></p>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.</p>
<h3>Resources</h3>
<ul>
<li><a href="https://grails.apache.org/">Website</a></li>
<li><a href="https://grails.apache.org/docs/latest/">Documentation</a></li>
<li><a href="https://github.com/apache/grails-core">GitHub</a></li>
<li><a href="https://lists.apache.org/list.html?dev@grails.apache.org">Developer Mailing List</a></li>
<li><a href="https://lists.apache.org/list.html?users@grails.apache.org">Users Mailing List</a></li>
<li><a href="https://grails.slack.com/">Slack</a> (Join: <a href="https://slack.grails.org/">https://slack.grails.org/</a>)</li>
</ul>
<h2>About The Apache Software Foundation (ASF)</h2>
<p>The Apache Software Foundation (ASF) is the global home for open source software, powering some of the world’s most ubiquitous software projects, including Apache Airflow, Apache Camel, Apache Cassandra, Apache Groovy, Apache HTTP Server, and Apache Kafka. Established in 1999, The ASF is at the forefront of open source innovation, setting industry standards to advance software for the public good. Learn more at <a href="https://apache.org">https://apache.org</a>.</p>
<p>For media inquiries, contact press@apache.org.</p>]]></description><author>James Fredley</author><guid>2025-10-07-apache-grails-graduation-top-level-project</guid><pubDate>Tue, 07 Oct 2025 00:00:00 GMT</pubDate></item><item><title>Apache Grails (Incubating) [%version] - Release Announcement</title><link>https://grails.apache.org/blog/2025-09-11-grails-7-rc2.html</link><description><![CDATA[</p>
<p>The Apache Grails (incubating) community is excited to announce the Milestone 7.0.0-RC2 release of the Grails Framework! <br />
We encourage you to try this pre-release version and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>Download Source Code and Binary Distributions</h2>
<p><a href="/download.html">Apache Grails Downloads</a></p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0-RC2, check out the following blog posts:</p>
<ul>
<li><a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1</a></li>
<li><a href="/blog/2025-03-05-grails-7-m3.html">Grails 7.0.0-M3</a></li>
<li><a href="/blog/2025-06-10-grails-7-m4.html">Grails 7.0.0-M4</a></li>
<li><a href="/blog/2025-07-15-grails-7-m5.html">Grails 7.0.0-M5</a></li>
<li><a href="/blog/2025-08-10-grails-7-rc1.html">Grails 7.0.0-RC1</a></li>
</ul>
<h3>7.0.0-RC2 Changes:</h3>
<ul>
<li><code>org.apache.grails:grails-i18n</code> has been changed to <code>org.apache.grails.i18n:grails-i18n</code> and is provided transitively, remove <code>org.apache.grails:grails-i18n</code> from your dependency list</li>
<li>Remove grails-forge unused docs generation and config @jamesfredley (#15041)</li>
<li>Update to Asset Pipeline 5.0.16 @jdaugherty (#15040)</li>
<li>Formatting helpers @matrei (#15034)</li>
<li>Remove deprecation warning for dot notation access @jamesfredley (#15035)</li>
<li>Add detailed documentation for standard Grails application profiles @jamesfredley (#15018)</li>
<li>Bump com.gradle.common-custom-user-data-gradle-plugin from 2.2.1 to 2.3 @<a href="https://github.com/apps/dependabot">dependabot[bot]</a> (#14788)</li>
<li>Add profile support for Gradle dependency variants @jamesfredley (#15013)</li>
<li>Reformat code @matrei (#14925)</li>
<li>Update Feature info and Gradle templates @matrei (#14994)</li>
<li>Hide servlet features, should be selected via --servlet instead @jamesfredley (#15005)</li>
<li>Bump <code>spring-boot</code> and <code>byte-buddy</code> versions @matrei (#15006)</li>
<li>Update documentation and links to new GitHub and docs URLs @jamesfredley (#15003)</li>
<li>Remove embedded-mongodb feature and references @jamesfredley (#15004)</li>
<li>Remove grails-forge documentation guide @jamesfredley (#15000)</li>
<li>Cleanup broken documentation links, update links which have changed, standardize link syntax @jamesfredley (#14988)</li>
<li>Remove springloaded forge feature, it only works with JDK 8 or less @jamesfredley (#14992)</li>
<li>Make reloading feature switch between options @jamesfredley (#14985)</li>
<li>Update quartz and web console versions @jamesfredley (#14981)</li>
<li>Update links in docs to new internal link or updated external link @jamesfredley (#14973)</li>
<li>Add development reloading subsection to getting started section @jamesfredley (#14969)</li>
<li>fix: remove ServletContext from generated and test BootStrap.groovy files @jamesfredley (#14970)</li>
<li>Adjust core plugins artifactids in GrailsCompilerAutoConfiguration.java @jamesfredley (#14968)</li>
<li>Merge 7.0.0-RC1 tag @jamesfredley (#14964)</li>
</ul>
<h2>🚀 Features</h2>
<ul>
<li>feature - #14017 - add back Micronaut support to Grails 7 with optional plugin @jdaugherty (#14953)</li>
<li>refactor(grails-geb): Read GebConfig.groovy to allow overriding RemoteWebDriver @JonasPammer (#14987)</li>
</ul>
<h2>🐛 Bug Fixes</h2>
<ul>
<li>Restart Geb VNC Container for each Test in a Spec to get correct recordings @JonasPammer (#14995)</li>
<li>Forge fixes @matrei (#15019)</li>
<li>grails-wrapper: Fix ClosureCompleter initialization in GradleCommand @jamesfredley (#15017)</li>
<li>Add <code>.git-blame-ignore-revs</code> @matrei (#15015)</li>
<li>fix: add asset-pipeline-bom to grails bom @jdaugherty (#14999)</li>
<li>fix: sitemesh3 rendering @jdaugherty (#14989)</li>
<li>Fix Typo dataStore not dataSource @lynchie14 (#14966)</li>
<li>fix: #14951 - make groovy extension merge for shadowJar reproducible @jdaugherty (#14952)</li>
<li>Issues-14899 fixes Documentation: Cleanup missing files @dauer (#14950)</li>
<li>fix: #14947 - class cast exception due to not using local variable @jdaugherty (#14960)</li>
</ul>
<h2>🔧 Maintenance</h2>
<ul>
<li>Explicitly type render(object) to help IntelliJ ambiguous method overloading @jdaugherty (#15031)</li>
<li>chore: conform to code style @matrei (#15033)</li>
<li>Enforce code style @matrei (#15016)</li>
<li>Include sources from composite builds in Groovydoc @jamesfredley (#15012)</li>
<li>ci: use <code>grails-forge</code> as base dir for dependabot @matrei (#15028)</li>
<li>chore(deps): bump com.gradle.common-custom-user-data-gradle-plugin from 2.2.1 to 2.3 in /grails-forge @<a href="https://github.com/apps/dependabot">dependabot[bot]</a> (#15026)</li>
<li>chore(deps): bump com.gradle.develocity from 4.0.1 to 4.1.1 in /grails-forge @<a href="https://github.com/apps/dependabot">dependabot[bot]</a> (#15025)</li>
<li>ci: add <code>grails-forge</code> dir to dependabot.yml @matrei (#15024)</li>
<li>chore(deps): bump com.gradle.develocity from 4.0.1 to 4.1.1 @<a href="https://github.com/apps/dependabot">dependabot[bot]</a> (#15022)</li>
<li>Add <code>.git-blame-ignore-revs</code> @matrei (#15015)</li>
<li>Remove grails-publish plugin from build plugins @jamesfredley (#15014)</li>
<li>Forge publish - Add workaround so that release builds do not require signing credentials @jdaugherty (#14998)</li>
<li>Ensure Gradle Settings file &amp; buildSrc/build.gradle are generated during the build Phase @jamesfredley (#14971)</li>
<li>chore: add versioning section to RELEASE.md and a link in README.md  @cbmarcum (#14962)</li>
<li>fix: #14951 - make groovy extension merge for shadowJar reproducible @jdaugherty (#14952)</li>
<li>chore: move grails-publish gradle plugin to its own project @jdaugherty (#14937)</li>
<li>chore: correct wording for the voting window @matrei (#14954)</li>
</ul>
<p>Full Changelog: <a href="https://github.com/apache/grails-core/compare/v7.0.0-RC1...v7.0.0-RC2">v7.0.0-RC1...v7.0.0-RC2</a></p>
<p>Upgrade instructions are available in the <a href="https://grails.apache.org/docs/7.0.0-RC2/guide/upgrading.html#upgrading60x">documentation</a>.</p>
<h2>Additional Releases</h2>
<p>The following plugins and tools are being released alongside Grails 7.0.0-RC2:</p>
<h3>Grails Spring Security 7.0.0-RC2</h3>
<p>See the release page: <a href="https://github.com/apache/grails-spring-security/releases/tag/v7.0.0-RC2">https://github.com/apache/grails-spring-security/releases/tag/v7.0.0-RC2</a></p>
<h3>Grails Quartz 4.0.0-RC2</h3>
<p>See the release page: <a href="https://github.com/apache/grails-quartz/releases/tag/v4.0.0-RC2">https://github.com/apache/grails-quartz/releases/tag/v4.0.0-RC2</a></p>
<h3>Grails Redis 5.0.0-RC2</h3>
<p>See the release page: <a href="https://github.com/apache/grails-redis/releases/tag/v5.0.0-RC2">https://github.com/apache/grails-redis/releases/tag/v5.0.0-RC2</a></p>
<h3>Grails GitHub Actions 1.0.0</h3>
<p>See the release page: <a href="https://github.com/apache/grails-github-actions/releases/tag/v1.0.0">https://github.com/apache/grails-github-actions/releases/tag/v1.0.0</a></p>
<ul>
<li>Initial release of actions for Gradle projects' release workflows.</li>
</ul>
<p><strong>Purpose</strong><br />
The actions being released are used in gradle projects for their release workflows to handle automated version management &amp; documentation publishing.</p>
<p><strong>Actions</strong></p>
<ul>
<li>deploy-github-pages action - a GitHub Action to copy documentation files to a specified documentation branch. Works by creating a subfolder named the same as the documentation branch, checking out the documentation branch to that folder, staging files, and then pushing them. Action is configured via environment variables.</li>
<li>export-gradle-properties action - a GitHub Action that takes a Java properties file (typically gradle.properties) and exports each property as an environment variable for use in subsequent steps of your workflow.</li>
<li>post-release action - a GitHub Action that handles steps necessary to close out a GitHub Release process. Including incrementing the next version &amp; merging back to the target branch</li>
<li>pre-release - a GitHub action that handles any pre-release steps as part of a GitHub release process. Including the project version being set based on the specified GitHub tag and updating the associated tag to the release.</li>
</ul>
<h3>Grails Gradle Publish 0.0.1</h3>
<p>See the release page: <a href="https://github.com/apache/incubator-grails-gradle-publish/releases/tag/v0.0.1">https://github.com/apache/incubator-grails-gradle-publish/releases/tag/v0.0.1</a></p>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.16 (now cloud.wondrify.asset-pipeline)</li>
<li>Spring Framework 6.2.10</li>
<li>Spring Boot 3.5.5</li>
<li>See all in the <a href="https://grails.apache.org/docs/7.0.0-RC2/ref/Versions/Grails%20BOM.html">grails-bom</a>.</li>
</ul>
<h2>Generating a new Grails 7.0.0-RC2 application with Grails Forge</h2>
<p>Try out Grails today by visiting our online application generator <a href="https://start.grails.org">Grails Forge</a>. This is the quickest and the recommended way to get started with Grails.</p>
<p>After installing JetBrains' IntelliJ IDEA 2025.2 or later and the <a href="https://plugins.jetbrains.com/plugin/18504-grails">Grails Plugin</a>, the Grails Application Forge will also be available under New Project in IntelliJ IDEA.</p>
<p>Within your newly generated project you can access the Grails CLIs with the Grails Wrapper.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0-RC2/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<p>grail-shell-cli</p>
<pre><code class="language-shell">grailsw
</code></pre>
<p>grails-forge-cli</p>
<pre><code class="language-shell">grailsw -t forge
</code></pre>
<h2>Installing Grails CLIs 7.0.0-RC2 with SDKMan</h2>
<p>Alternatively, you can quickly install Grails 7.0.0-RC2 CLIs (grails-shell-cli and grails-forge-cli) using <a href="https://sdkman.io">SDKMan</a>.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0-RC2/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-RC2:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-RC2
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<p>The Grails Shell CLI can be accessed as:</p>
<pre><code class="language-shell">grails
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-shell-cli
</code></pre>
<p>The Grails Forge CLI can be accessed as:</p>
<pre><code class="language-shell">grails -t forge
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-forge-cli
</code></pre>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-RC2</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA 2025.2 or later).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-RC2 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-RC2
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. <a href="https://grails.apache.org/docs/7.0.0-RC2/guide/upgrading.html#upgrading60x">See Upgrade Guide</a></p>
<ul>
<li>remove <code>org.apache.grails:grails-i18n</code> from your dependency list, it has changed to <code>org.apache.grails.i18n:grails-i18n</code> and is provided transitively by default</li>
</ul>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0-RC2.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0-RC2.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-RC2. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com">Renovate</a> or
<a href="https://dependabot.com">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0-RC2.</p>
<h2>Why should you try out Grails 7.0.0-RC2?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/apache/projects/487/views/2">updating and fixing issues</a> over the next few
weeks.</li>
<li>Based on feedback, an Apache Grails RC or Final release is targeted for September 2025.</li>
</ul>
<h2>Apache Grails Mailing Lists</h2>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 20 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-RC2 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/rainboyan">Michael Yan</a></li>
<li><a href="https://github.com/JudeRV">Jude Vargas</a></li>
<li><a href="https://github.com/dauer">Thomas Rasmussen</a></li>
<li><a href="https://github.com/irllyliketoast">Laura Estremera</a></li>
<li><a href="https://github.com/shadowchaser000">Hallie Uczen</a></li>
<li><a href="https://github.com/jprinet">Jérôme Prinet</a></li>
<li><a href="https://github.com/lynchie14">Stephen Lynch</a></li>
<li><a href="https://github.com/dreewh">Andrew Herring</a></li>
<li><a href="https://github.com/nobeans">Yasuharu Nakano</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/felixscheinost">Felix Scheinost</a></li>
<li><a href="https://github.com/cbmarcum">Carl Marcum</a></li>
<li><a href="https://github.com/eugene-kamenev">Eugene Kamenev</a></li>
<li><a href="https://github.com/huangyucaigit">yucai</a></li>
<li><a href="https://github.com/gandharvas">gandharvas</a></li>
<li><a href="https://github.com/zyro23">zyro</a></li>
</ul>
<p>Recent Contributors by Project:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-core</a></li>
<li><a href="https://github.com/apache/grails-spring-security/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-spring-security</a></li>
<li><a href="https://github.com/apache/grails-static-website/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-static-website</a></li>
<li><a href="https://github.com/apache/grails-forge-ui/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-forge-ui</a></li>
<li><a href="https://github.com/apache/grails-quartz/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-quartz</a></li>
<li><a href="https://github.com/apache/incubator-grails-gradle-publish/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-gradle-publish</a></li>
<li><a href="https://github.com/apache/grails-redis/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-redis</a></li>
<li><a href="https://github.com/apache/grails-github-actions/graphs/contributors?from=March+11%2C+2025&amp;to=September+11%2C+2025">grails-github-actions</a></li>
</ul>
<p><a href="https://github.com/search?q=repo%3Aapache%2Fgrails-core+repo%3Aapache%2Fgrails-spring-security+repo%3Aapache%2Fgrails-static-website+repo%3Aapache%2Fgrails-forge-ui+repo%3Aapache%2Fgrails-quartz+repo%3Aapache%2Fincubator-grails-gradle-publish+repo%3Agrails-redis+repo%3Agrails-github-actions+is%3Apublic&amp;type=commits&amp;s=committer-date&amp;o=desc">Combined Commit List</a></p>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-RC2.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-09-11-grails-7-rc2</guid><pubDate>Thu, 11 Sep 2025 00:00:00 GMT</pubDate></item><item><title>Apache Grails (Incubating) [%version] - Release Announcement</title><link>https://grails.apache.org/blog/2025-08-10-grails-7-rc1.html</link><description><![CDATA[</p>
<p>The Apache Grails (incubating) community is excited to announce the Milestone 7.0.0-RC1 release of the Grails Framework! <br />
We encourage you to try this pre-release version and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>Download Source Code and Binary Distributions</h2>
<p><a href="/download.html">Apache Grails Downloads</a></p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0-RC1, check out the following blog posts:</p>
<ul>
<li><a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1</a></li>
<li><a href="/blog/2025-03-05-grails-7-m3.html">Grails 7.0.0-M3</a></li>
<li><a href="/blog/2025-06-10-grails-7-m4.html">Grails 7.0.0-M4</a></li>
<li><a href="/blog/2025-07-15-grails-7-m5.html">Grails 7.0.0-M5</a></li>
</ul>
<h3>7.0.0-RC1 Changes:</h3>
<ul>
<li>Add permissions to release environments by @jdaugherty in #14795</li>
<li>Asset plugin forking compiler @jdaugherty (#14948)</li>
<li>Update base, web and rest-api profiles to more closely match Forge @jamesfredley (#14942)</li>
<li>#14886 - add licensing to distributed shadowJar @jdaugherty (#14945)</li>
<li>Add non-default, optional virtual thread feature to Forge for Java 24+ @jamesfredley (#14941)</li>
<li>remove: pdf publishing due to licensing issues &amp; no longer using inside of Grails documentation @jdaugherty (#14940)</li>
<li>Update to spring-boot 3.5.4 &amp; groovy 4.0.28 @jamesfredley (#14934)</li>
<li>feature: add grails-dependency proposal @jdaugherty (#14924)</li>
<li>Enhance CreateReleaseDropDownTask so it can be reused by grails-spring-security @jamesfredley (#14929)</li>
<li>remove old asm &amp; AnnotationMetadataReader supporting classes; adopt SimpleMetadataReaderFactory @jdaugherty (#14922)</li>
<li>Set spring boot dev tools as a default feature in forge to match profiles @jamesfredley (#14921)</li>
<li>Use version variables + minor copy and formatting adjustments @jamesfredley (#14908)</li>
<li>Dependency minor/patch version updates before 7.0.0-RC1 @jamesfredley (#14909)</li>
<li>Fix build performance issues @jprinet (#14895)</li>
<li>Merge 7.0.0 m5 release tag @jamesfredley (#14907)</li>
<li>Enhance documentation for grails-shell vs grails-forge CLIs, plus Gra… @jamesfredley (#14906)</li>
<li>Add version support message for IntelliJ Grails Plugin @jamesfredley (#14905)</li>
<li>Update GitHub repository homepage URL @jamesfredley (#14902)</li>
<li>Deprecated Removals @jdaugherty (#14901)</li>
<li>Fix snapshot docs URL, currently only appears on snapshot docs @jamesfredley (#14900)</li>
<li>Restore Sitemesh3GrailsPlugin @jdaugherty (#14891)</li>
<li>Wrapper Improvements found by M5 Release @jdaugherty (#14896)</li>
<li>Fix issue reported by GitHub CodeQL @matrei (#14936)</li>
<li>fix: #14918 adjust the class loader used for command loading to ensure the delegating cli can find all commands @jdaugherty (#14926)</li>
<li>fix: #14910 - make property files reproducible by default (per day) @jdaugherty (#14919)</li>
<li>fix: issues found by M5 release verification @jdaugherty (#14904)</li>
<li>fix: #13705 - revert changes to Metadata from micronaut removal @jdaugherty (#14897)</li>
<li>fix: #13668 - update for SpringBoot resource split into subclass @jdaugherty (#14888)</li>
<li>#14930 - make views reproducible by sorting views always @jdaugherty (#14946)</li>
<li>build(deps): bump google-github-actions/auth from 2.1.10 to 2.1.11 @dependabot[bot] (#14939)</li>
<li>build(deps): bump google-github-actions/setup-gcloud from 2.1.4 to 2.1.5 @dependabot[bot] (#14938)</li>
<li>fix: #14910 - make property files reproducible by default (per day) @jdaugherty (#14919)</li>
<li>doc: #14892 - update RELEASE.md for workflow changes and grails-forge repo merge @jdaugherty (#14893)</li>
<li>fix: #13705 - revert changes to Metadata from micronaut removal @jdaugherty (#14897)</li>
</ul>
<p>Full Changelog: <a href="https://github.com/apache/grails-core/compare/v7.0.0-M5...v7.0.0-RC1">v7.0.0-M5...v7.0.0-RC1</a></p>
<p>Upgrade instructions are available in the <a href="https://grails.apache.org/docs/7.0.0-RC1/guide/upgrading.html#upgrading60x">documentation</a>.</p>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.12 (now cloud.wondrify.asset-pipeline)</li>
<li>Groovy 4.0.28</li>
<li>Spring Framework 6.2.9</li>
<li>Spring Boot 3.5.4</li>
<li>Gradle 8.14.3</li>
<li>See all in the <a href="https://grails.apache.org/docs/7.0.0-RC1/ref/Versions/Grails%20BOM.html">grails-bom</a>.</li>
</ul>
<h2>Generating a new Grails 7.0.0-RC1 application with Grails Forge</h2>
<p>Try out Grails today by visiting our online application generator <a href="https://start.grails.org">Grails Forge</a>. This is the quickest and the recommended way to get started with Grails.</p>
<p>After installing JetBrains' IntelliJ IDEA 2025.2 or later and the <a href="https://plugins.jetbrains.com/plugin/18504-grails">Grails Plugin</a>, the Grails Application Forge will also be available under New Project in IntelliJ IDEA.</p>
<p>Within your newly generated project you can access the Grails CLIs with the Grails Wrapper.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0-RC1/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<p>grail-shell-cli</p>
<pre><code class="language-shell">grailsw
</code></pre>
<p>grails-forge-cli</p>
<pre><code class="language-shell">grailsw -t forge
</code></pre>
<h2>Installing Grails CLIs 7.0.0-RC1 with SDKMan</h2>
<p>Alternatively, you can quickly install Grails 7.0.0-RC1 CLIs (grails-shell-cli and grails-forge-cli) using <a href="https://sdkman.io">SDKMan</a>.</p>
<p>See the <a href="https://grails.apache.org/docs/7.0.0-RC1/guide/gettingStarted.html#_types_of_command_line_interface_cli">Types of CLI</a> section in the documentation for details on each CLI.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-RC1:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-RC1
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<p>The Grails Shell CLI can be accessed as:</p>
<pre><code class="language-shell">grails
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-shell-cli
</code></pre>
<p>The Grails Forge CLI can be accessed as:</p>
<pre><code class="language-shell">grails -t forge
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-forge-cli
</code></pre>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-RC1</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA 2025.2 or later).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-RC1 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-RC1
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. <a href="https://grails.apache.org/docs/7.0.0-RC1/guide/upgrading.html#upgrading60x">See Upgrade Guide</a></p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0-RC1.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0-RC1.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-RC1. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com">Renovate</a> or
<a href="https://dependabot.com">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0-RC1.</p>
<h2>Why should you try out Grails 7.0.0-RC1?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/apache/projects/487/views/2">updating and fixing issues</a> over the next few
weeks.</li>
<li>Based on feedback, an Apache Grails RC or Final release is targeted for September 2025.</li>
</ul>
<h2>Apache Grails Mailing Lists</h2>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 20 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-RC1 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/rainboyan">Michael Yan</a></li>
<li><a href="https://github.com/JudeRV">Jude Vargas</a></li>
<li><a href="https://github.com/dauer">Thomas Rasmussen</a></li>
<li><a href="https://github.com/irllyliketoast">Laura Estremera</a></li>
<li><a href="https://github.com/shadowchaser000">Hallie Uczen</a></li>
<li><a href="https://github.com/jprinet">Jérôme Prinet</a></li>
<li><a href="https://github.com/lynchie14">Stephen Lynch</a></li>
<li><a href="https://github.com/dreewh">Andrew Herring</a></li>
<li><a href="https://github.com/nobeans">Yasuharu Nakano</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/felixscheinost">Felix Scheinost</a></li>
<li><a href="https://github.com/gandharvas">gandharvas</a></li>
<li><a href="https://github.com/zyro23">zyro</a></li>
</ul>
<p>Recent Contributors by Project:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-core</a></li>
<li><a href="https://github.com/apache/grails-spring-security/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-spring-security</a></li>
<li><a href="https://github.com/apache/grails-static-website/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-static-website</a></li>
<li><a href="https://github.com/apache/grails-forge-ui/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-forge-ui</a></li>
<li><a href="https://github.com/apache/grails-quartz/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-quartz</a></li>
<li><a href="https://github.com/apache/incubator-grails-gradle-publish/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-gradle-publish</a></li>
<li><a href="https://github.com/apache/grails-redis/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-redis</a></li>
<li><a href="https://github.com/apache/grails-github-actions/graphs/contributors?from=February+10%2C+2025&amp;to=August+10%2C+2025">grails-github-actions</a></li>
</ul>
<p><a href="https://github.com/search?q=repo%3Aapache%2Fgrails-core+repo%3Aapache%2Fgrails-spring-security+repo%3Aapache%2Fgrails-static-website+repo%3Aapache%2Fgrails-forge-ui+repo%3Aapache%2Fgrails-quartz+repo%3Aapache%2Fincubator-grails-gradle-publish+repo%3Agrails-redis+repo%3Agrails-github-actions+is%3Apublic&amp;type=commits&amp;s=committer-date&amp;o=desc">Combined Commit List</a></p>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-RC1.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-08-10-grails-7-rc1</guid><pubDate>Sun, 10 Aug 2025 00:00:00 GMT</pubDate></item><item><title>Apache Grails (Incubating) [%version] - Release Announcement</title><link>https://grails.apache.org/blog/2025-07-15-grails-7-m5.html</link><description><![CDATA[</p>
<p>The Apache Grails (incubating) community is excited to announce the Milestone 7.0.0-M5 release of the Grails Framework! <br />
We encourage you to try this pre-release version and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>Download Source Code and Binary Distributions</h2>
<p><a href="/download.html">Apache Grails Downloads</a></p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0-M5, check out the following blog posts:</p>
<ul>
<li><a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1</a></li>
<li><a href="/blog/2025-03-05-grails-7-m3.html">Grails 7.0.0-M3</a></li>
<li><a href="/blog/2025-06-10-grails-7-m4.html">Grails 7.0.0-M4</a></li>
</ul>
<h3>7.0.0-M5 Changes:</h3>
<ul>
<li>Add permissions to release environments by @jdaugherty in #14795</li>
<li>Force update asf.yaml by @jdaugherty in #14796</li>
<li>explicitly add jdaugherty as approver by @jdaugherty in #14797</li>
<li>back to snapshot by @jdaugherty in #14800</li>
<li>Add add-license scripts for .raw, .java and .groovy by @jamesfredley in #14794</li>
<li>Fixes found as part of the second attempt at M2 by @jdaugherty in #14782</li>
<li>Verify build explanation and minor fix by @sbglasius in #14781</li>
<li>initial attempt at GitHub -&gt; Mailing List notifications by @jamesfredley in #14784</li>
<li>Update Geb documentation changes in Breaking Changes Section by @jamesfredley in #14793</li>
<li>Update grails-forge - google cloud run deploy documentation by @jamesfredley in #14803</li>
<li>Unnest the snapshot zip uploaded to workflow results by @jamesfredley in #14808</li>
<li>Gradle deprecations by @jdaugherty in #14805</li>
<li>Update grails-static-website section on RELEASE.md by @jamesfredley in #14807</li>
<li>Support specifying the publication name so that gradle plugins can be published by @jdaugherty in #14812</li>
<li>Use developmentOnly Gradle configuration scope for webjars by @jamesfredley in #14811</li>
<li>Rework mainClass gradle find logic by @jdaugherty in #14816</li>
<li>fix: #14818 - ensure plugin is the base for web-plugin by @jdaugherty in #14819</li>
<li>Fixing Issue #14173 – Update grails Command Documentation for Grails 7 by @irllyliketoast in #14809</li>
<li>Update to new asset pipeline coordinates by @jdaugherty in #14813</li>
<li>fix: update grails-docs coords in GrailsDocGradlePlugin by @matrei in #14826</li>
<li>Support not adding components from the grails publish plugin by @jdaugherty in #14827</li>
<li>fix: scope webjars as testAndDevelopmentOnly by @jamesfredley in #14829</li>
<li>Update to Spring Boot 3.5.3 which uses Groovy 4.0.27 by @jamesfredley in #14824</li>
<li>database-migration mapped to grails-data-hibernate5-dbmigration by @jamesfredley in #14831</li>
<li>#14832 - support findMainTask caching with plugins &amp; boot tasks in the task graph by @jdaugherty in #14833</li>
<li>Add Documentation: Tomcat 10.1.42 multipart/form-data part count and header size limit by @jamesfredley in #14838</li>
<li>chore(tests): move tests to the correct module by @matrei in #14839</li>
<li>Merge grails-forge into grails-core by @jdaugherty in #14836</li>
<li>Replace google analytics with Matomo, analytics.apache.org by @jamesfredley in #14842</li>
<li>Correct dependency to grails-codecs-core by @matrei in #14844</li>
<li>chore: update to 5.0.12 for the asset pipeline by @jdaugherty in #14879</li>
<li>Fix spelling by @jdaugherty in #14881</li>
<li>fix: #14854 - remove duplicate repo definition (restricted contains maven central) by @jdaugherty in #14882</li>
<li>chore: #14779 - add better instructions on how to build &amp; use the source distribution by @jdaugherty in #14880</li>
<li>chore: #14877 - add DISCLAIMER, LICENSE, &amp; NOTICE files to jar files by @jdaugherty in #14878</li>
<li>Various Cleanup prior to Sitemesh 2 revert by @jdaugherty in #14876</li>
<li>fix: #14090 - fix baseUrl returning the wrong result when forwardPort is null by @jdaugherty in #14884</li>
<li>Revert to Sitemesh 2 for Grails 7 by @jdaugherty in #14875</li>
<li>Issue #14748 - upgrade notes for gradle plugin / task changes by @jdaugherty in #14883</li>
<li>#14316 Use local repo commands instead of the github api for Release Drop Down population by @JudeRV in #14834</li>
</ul>
<p>Full Changelog: <a href="https://github.com/apache/grails-core/compare/v7.0.0-M4...v7.0.0-M5">v7.0.0-M4...v7.0.0-M5</a></p>
<p>Upgrade instructions are available in the <a href="https://grails.apache.org/docs/7.0.0-M5/guide/upgrading.html#upgrading60x">documentation</a>.</p>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.12 (now cloud.wondrify.asset-pipeline)</li>
<li>Groovy 4.0.27</li>
<li>Spring Framework 6.2.8</li>
<li>Spring Boot 3.5.3</li>
<li>Gradle 8.14.2</li>
<li>See all in the <a href="https://grails.apache.org/docs/7.0.0-M5/ref/Versions/Grails%20BOM.html">grails-bom</a>.</li>
</ul>
<h2>Generating a new Grails 7.0.0-M5 application with Grails Forge</h2>
<p>Try out Grails today by visiting our online application generator <a href="https://start.grails.org/">Grails Forge</a>.  This is the quickest and the recommended way to get started with Grails.</p>
<p>After installing the JetBrains' IntelliJ IDEA <a href="https://plugins.jetbrains.com/plugin/18504-grails">Grails Plugin</a>, the Grails Application Forge will also be available under New Project in IntelliJ IDEA.</p>
<p>Within your newly generated project you can access the Grails CLIs with the grails wrapper</p>
<p>See <a href="https://grails.apache.org/docs/7.0.0-M5/guide/gettingStarted.html#downloadingAndInstalling">Types of CLI</a> for details on each CLI</p>
<p>grail-shell-cli</p>
<pre><code class="language-shell">grailsw
</code></pre>
<p>grails-forge-cli</p>
<pre><code class="language-shell">grailsw -t forge
</code></pre>
<h2>Installing Grails CLIs 7.0.0-M5 with SDKMan</h2>
<p>Alternatively, you can quickly install Grails 7.0.0-M5 CLIs (grails-shell-cli and grails-forge-cli) using <a href="https://sdkman.io/">SDKMan</a>.</p>
<p>See <a href="https://grails.apache.org/docs/7.0.0-M5/guide/gettingStarted.html#downloadingAndInstalling">Types of CLI</a> for details on each CLI</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a>
to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-M5:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-M5
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<p>The Grails Shell CLI can be accessed as:</p>
<pre><code class="language-shell">grails
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-shell-cli
</code></pre>
<p>The Grails Forge CLI can be accessed as:</p>
<pre><code class="language-shell">grails -t forge
</code></pre>
<p>or</p>
<pre><code class="language-shell">grails-forge-cli
</code></pre>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-M5</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-M5 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-M5
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. <a href="https://grails.apache.org/docs/7.0.0-M5/guide/upgrading.html#upgrading60x">See Upgrade Guide</a></p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0-M5.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0-M5.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-M5. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or
<a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0-M5.</p>
<h2>Why should you try out Grails 7.0.0-M5?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/apache/projects/487">updating and fixing issues</a> over the next few
weeks.</li>
<li>Based on feedback, an Apache Grails RC release is targeted for July/August 2025.</li>
</ul>
<h2>Apache Grails Mailing Lists</h2>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 19 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-M5 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/rainboyan">Michael Yan</a></li>
<li><a href="https://github.com/JudeRV">Jude Vargas</a></li>
<li><a href="https://github.com/dauer">Thomas Rasmussen</a></li>
<li><a href="https://github.com/irllyliketoast">Laura Estremera</a></li>
<li><a href="https://github.com/dreewh">Andrew Herring</a></li>
<li><a href="https://github.com/nobeans">Yasuharu Nakano</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/felixscheinost">Felix Scheinost</a></li>
<li><a href="https://github.com/gandharvas">gandharvas</a></li>
<li><a href="https://github.com/zyro23">zyro</a></li>
</ul>
<p>Recent Contributors by Project:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-core</a></li>
<li><a href="https://github.com/apache/grails-spring-security/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-spring-security</a></li>
<li><a href="https://github.com/apache/grails-static-website/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-static-website</a></li>
<li><a href="https://github.com/apache/grails-forge-ui/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-forge-ui</a></li>
<li><a href="https://github.com/apache/grails-quartz/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-quartz</a></li>
<li><a href="https://github.com/apache/incubator-grails-gradle-publish/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-gradle-publish</a></li>
<li><a href="https://github.com/apache/grails-redis/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-redis</a></li>
<li><a href="https://github.com/apache/grails-github-actions/graphs/contributors?from=January+15%2C+2025&amp;to=July+15%2C+2025">grails-github-actions</a></li>
</ul>
<p><a href="https://github.com/search?q=repo%3Aapache%2Fgrails-core+repo%3Aapache%2Fgrails-spring-security+repo%3Aapache%2Fgrails-static-website+repo%3Aapache%2Fgrails-forge-ui+repo%3Aapache%2Fgrails-quartz+repo%3Aapache%2Fincubator-grails-gradle-publish+repo%3Agrails-redis+repo%3Agrails-github-actions+is%3Apublic&amp;type=commits&amp;s=committer-date&amp;o=desc">Combined Commit List</a></p>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-M5.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-07-15-grails-7-m5</guid><pubDate>Tue, 15 Jul 2025 00:00:00 GMT</pubDate></item><item><title>Apache Grails (Incubating) 7.0.0-M4 - Release Announcement</title><link>https://grails.apache.org/blog/2025-06-10-grails-7-m4.html</link><description><![CDATA[</p>
<p>The Apache Grails (incubating) community is excited for the release of Grails Framework 7.0.0-M4. <br />
We encourage you to try this pre-release and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>Download Source Code and Binary Distributions</h2>
<p><a href="/download.html">Apache Grails Downloads</a></p>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0-M4, check out the <a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1 Release Blog Post</a> and <a href="/blog/2025-03-05-grails-7-m3.html">Grails 7.0.0-M3 Release Blog Post</a></p>
<p>Apache Grails (incubating) 7.0.0-M4 is the first release for Grails under the Apache Software Foundation (ASF). This release focuses first on meeting the requirements of the ASF &amp; improving the developer experience of Grails itself &amp; Grails Applications. As part of this transition, the developers moved to a mono repository, reworked the way the various Grails CLIs work, modernized its build system, modernized the various Grails Gradle Tasks, modernized the various Grails Gradle Plugins, worked towards reproducible builds, added license headers to our source code, and changed the maven coordinates of all Grails Artifacts.</p>
<h3>With the release of Grails 7.0.0-M4, we have:</h3>
<ul>
<li>PR #14750 - support non-persistent super classes for @Autotimestamp</li>
<li>Issue #14745 - remove deprecated doc method on Grails Plugins</li>
<li>Issue #14745 - remove duplicate grails.factories &amp; grails-plugin.xml files now that AST generation is working correctly</li>
<li>Issue #14745 - switch to Spring Boot 3.5.0 with Spring Framework 6.2.7 due to bug (https://github.com/spring-projects/spring-framework/issues/34796)</li>
<li>Issue #14745 - change the grails-gradle-model to export Groovy 3 due to Gradle Task isolation in later versions of Gradle</li>
<li>Issue #14745 - rework the FindMainTask to correctly set the main Application class on BootWar, BootJar, &amp; BootRun</li>
<li>Issue #14745 - remove org.grails.plugins.CodecGrailsPlugin; use org.grails.plugins.codecs.CodecsGrailsPlugin instead</li>
<li>Issue #14745 - remove the remaining pathingJar task functions</li>
<li>Issue #14745 - fix a databinding scenario in DataBindingUtils to lookup a domain object</li>
<li>PR #14749 - retire Mongo 5.0 &amp; 6.0 test pipelines since those versions are end of support</li>
<li>PR #14746 - switch to asset-pipeline-gradle 5.0.9</li>
<li>PR #14743 - remove redundant buildScript from test projects</li>
<li>Issue #14706 - rework grailsw to be usable independently of SDKMAN installs</li>
<li>Issue #14706 - rework grails-shell-cli to be usable independently of SDKMAN installs</li>
<li>Issue #14706 - rework the command cli to support a grailsw that can self-update either forge or legacy shell cli</li>
<li>Issue #14706 - distribute a delegating CLI that can call either forge or the legacy shell cli</li>
<li>Issue #14706 - rework the legacy shell cli to correctly find profiles</li>
<li>Issue #14706 - rework both grailsw &amp; grails-shell-cli to be testable outside of releases</li>
<li>Issue #14679 - generate reproducible groovydoc jars</li>
<li>Issue #14679 - fix profile compilation to generate reproducible jars</li>
<li>Issue #14679 - ensure groovydoc is used instead of javadoc for documentation jars</li>
<li>PR #14709 - switch to Gradle 8.14</li>
<li>PR #14678 - add support for external config locations, by incorporating the external-config plugin into Grails core</li>
<li>Refactor grails into a mono repo (grails-views, gsp, data mapping, geb, etc are all merged into core now)</li>
<li>As part of the mono repo transition, several Deprecated classes were removed from the views project; see the upgrade guide for the details.</li>
<li>Issue #14679 - refactor grails build to be parallel &amp; lazy</li>
<li>Issue #14679 - change all Grails gradle tasks to support Caching where appropriate and support lazy style configuration</li>
<li>Issue #14679 - Redesign the Grails Data TCK to support modern versions of Java</li>
<li>Issue #14679 - Support consistent property dates in generated property files when SOURCE_DATE_EPOCH is set</li>
<li>Issue #14679 - Make grails.factories generation reproducible</li>
<li>Issue #14679 - Refactor Grails AST Transformations to take advantage of Groovy's TransformWithPriority and enforce transforms always run in the order defined by the class <code>GroovyTransformOrder</code></li>
<li>Issue #14679 - Remove manifest attributes that could vary on the Grails jars (Built-By, Created-By etc)</li>
<li>Issue #14679 - Fix sourcejar creation to not contain duplicates</li>
<li>Issue #14679 - Fix javadoc jars to be generated based on groovydoc &amp; to not contain duplicates</li>
<li>Issue #14679 - Change AST transforms to be reproducible by adopting determined ordering collections</li>
<li>Issue #14679 - Configure Grails jars per Gradle's reproducibility requirements (fixed permissions, reproducible file order, etc)</li>
<li>Issue #13850 - introduce <code>grails-common</code> to share common code between Grails Data Mapping &amp; Grails-Core</li>
<li>Issue #14679 - add scripts to confirm reproducibility of Grails; currently 14 of 290 jars are reproducible</li>
<li>Issue #14679 - make TagLib lookups reproducible</li>
<li>PR #14671 - switch to webjars for test css/js assets instead of checked in files</li>
<li>The Grails Gradle plugin had a bug that caused plugin resolution issues that was fixed after the last milestone.</li>
<li>Rework the grails bom to generate valid Gradle modules, be easier to maintain, and valid pom files.  Enhance the documentation process to parse the bom &amp; generate the published versions in the grails doc.</li>
</ul>
<p>And in addition to all of this:</p>
<ul>
<li>We changed all coordinates of Grails to be org.apache.grails based. See https://github.com/apache/grails-core/blob/7.0.x/RENAME.md for how we mapped these libraries. There is also a script documented in the upgrade guide to assist in upgrading.</li>
<li>Consolidated main Grails projects into grails-core git monorepository to drastically speed up development, testing and the release process</li>
<li>Significant test fixes</li>
<li>Significant documentation updates &amp; changes</li>
<li>Addition of license headers to Grails Source</li>
<li>Addition of NOTICE to Grails Source</li>
<li>Created https://repo.grails.org/grails/restricted/ to replace https://repo.grails.org/grails/core longer term.  This virtual repo's scope is significantly reduced to help reduce the chance of using outdated libraries.</li>
</ul>
<p>Upgrade instructions are available in the <a href="https://grails.apache.org/docs/7.0.0-M4/guide/upgrading.html#upgrading60x">documentation</a>.</p>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.9</li>
<li>Groovy 4.0.27</li>
<li>Spring Framework 6.2.7</li>
<li>Spring Boot 3.5.0</li>
<li>Gradle 8.14</li>
<li>Spock 2.3-groovy-4.0</li>
<li>See all in the <a href="https://grails.apache.org/docs/7.0.0-M4/ref/Versions/Grails%20BOM.html">grails-bom</a>.</li>
</ul>
<h2>Installing Grails 7.0.0-M4</h2>
<p>Try out Grails 7.0.0-M4 today by visiting the online app creator * <a href="https://start.grails.org/">Grails Forge</a>.
Alternatively, you can quickly install Grails 7.0.0-M4 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a>
to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-M4:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-M4
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-M4</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-M4 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-M4
# The Grails Gradle Plugin version is now available in the BOM
# and can be omitted if your project adds the Grails BOM to the
# buildscript dependencies.
grailsGradlePluginVersion=7.0.0-M4
# Temporary for 7.0.0-M4 to force the latest version
groovy.version=4.0.27
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. See https://grails.apache.org/docs/7.0.0-M4/guide/upgrading.html#upgrading60x.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0-M4.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0-M4.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-M4. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or
<a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0-M4. Happy coding!</p>
<h2>Why should you try out Grails 7.0.0-M4?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/apache/projects/487">updating and fixing issues</a> over the next few
weeks.</li>
<li>Based on feedback, an Apache Grails RC release is targeted for July 2025.</li>
</ul>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 19 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-M4 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-M4.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-06-10-grails-7-m4</guid><pubDate>Tue, 10 Jun 2025 00:00:00 GMT</pubDate></item><item><title>Grails 7.0.0-M3 - Release Announcement</title><link>https://grails.apache.org/blog/2025-03-05-grails-7-m3.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited for the release of Grails Framework 7.0.0-M3. <br />
We encourage you to try this pre-release and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<p>The next milestone is planned to be released under the Apache Software Foundation as Apache Grails 7.0.0-M4.</p>
<p>NOTE: Due to a release problem, 7.0.0-M2 was skipped.</p>
<h2>Mailing Lists Changes</h2>
<p>As we transition to Apache more communications will occur on our new Apache mailing lists.</p>
<h3>Users Mailing List</h3>
<p>The users mailing list will be a General purpose list for questions and discussion about Grails.<br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?users@grails.apache.org">https://lists.apache.org/list.html?users@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:users-subscribe@grails.apache.org">users-subscribe@grails.apache.org</a></p>
<h3>Dev Mailing List</h3>
<p>The dev mailing list is focused on the framework implementation and its evolution. <br />
<strong>Web Archive:</strong> <a href="https://lists.apache.org/list.html?dev@grails.apache.org">https://lists.apache.org/list.html?dev@grails.apache.org</a> <br />
<strong>Subscribe:</strong> Send a blank email to <a href="mailto:dev-subscribe@grails.apache.org">dev-subscribe@grails.apache.org</a></p>
<p>When participating in Apache mailing lists, you should never include any personally identifiable information (PII) like
your address, phone number or email address, as all messages sent to these lists are publicly accessible and archived,
meaning anyone can view your information. Make sure your email client does not add your signature with these items.</p>
<h2>What's Changed</h2>
<p>For changes made in Grails 7 prior to 7.0.0-M3, check out the <a href="/blog/2024-12-23-grails-7-m1.html">Grails 7.0.0-M1 Release Blog Post</a></p>
<h3>With the release of Grails 7.0.0-M3, we have:</h3>
<ul>
<li>Consolidated several main/core Git repositories/Gradle projects to drastically reduce the time to publish a release.
This resulted in the version of many dependencies changing and in some cases skipping major versions to match with the
consolidated project. The old project Git repository default branch readme has been updated to point to the new location.
Existing issues and PRs have been migrated when possible.</li>
<li>Consolidated 10 active profiles into a single Git repository/Gradle Project.</li>
<li>Consolidated 6 Spring Security plugins into the Spring Security Core Git repository.</li>
<li>Updated the Web and Base Grails profiles to generate runnable Grails 7 applications.</li>
<li>Changed so that <code>hibernate-ehcache</code> is no longer provided by the <code>hibernate5</code> plugin.
<a href="https://github.com/apache/grails-core/blob/7.0.x/UPGRADE7.md">See details</a></li>
<li>Fixed documentation (asciidoc, groovydoc &amp; javadoc) generation and publishing across many projects.</li>
<li>Ensured tests run during build and CI across many projects.</li>
<li>Updated <code>ContainerGebSpec</code> in <code>geb</code> with:
<ul>
<li>Cross-platform file input support.</li>
<li>IDE hints and auto-completion of <code>Browser.*</code>, <code>Page.*</code> and <code>WebDriver.pageSource</code> methods.</li>
<li>Recycling of the recording container.</li>
<li>Delegation to the current page object.</li>
<li>Inclusion of the <code>ScreenshotReporter</code> by default.</li>
<li>Fix of log message for reports directory.</li>
</ul>
</li>
<li>Updated <code>grails-gradle-plugin</code> with:
<ul>
<li>End-to-end tests.</li>
<li>Fix of <code>configScript</code> handling.</li>
<li>Inclusion of <code>testFixtures</code> in version resolving for POM generation in <code>org.grails.grails-publish</code>.</li>
<li>Fix to include AST sources in javadoc and source jars.</li>
<li>Fix to <code>org.grails.grails-publish</code> to ensure sources and javadoc are published by default.</li>
<li>Changes and standardization of profile task names so they can be used with the Java Gradle Plugin.</li>
<li>Changes to not require Java or Groovy Gradle Plugins for profile publishing.</li>
<li>Fix of profile publishing to support the Java Gradle Plugin.</li>
<li>Consolidation of profiles into a single Gradle multi-project build.</li>
</ul>
</li>
<li>Updated <code>database-migration-plugin</code> with:
<ul>
<li>Move to <code>gorm-hibernate5</code> project.</li>
<li>Exclusion of <code>liquibase-commercial</code> to prevent it from being exported.</li>
<li>Loading of migrations from embedded jars (plugins).</li>
<li>Allowing the loading of classpath resources for sqlFile changesets.</li>
</ul>
</li>
<li>Replaced <code>tomcat-jdbc</code> with <code>HikariCP</code> in default generated applications from <code>grails-shell</code> CLI and <code>grails-forge</code> CLI.</li>
<li>Updated <code>asset-pipeline</code> to resolve missing graalvm asset compiler dependencies for bootRun, unit test and integration tests.</li>
<li>Leveraged <code>grails-bom</code> versions wherever possible to simplify updates across the projects.</li>
<li>Consolidated any versions not set by <code>grails-bom</code> in <code>gradle.properties</code> across projects.</li>
<li>Allowed disabling of <code>AutoTimestamp</code> on insertion event if values are not <code>null</code>.</li>
<li>Allowed customization of <code>AutoTimestamp</code> <code>dateCreated</code> and <code>lastUpdated</code> properties.</li>
<li>Added GSP Pagination support for Bootstrap 5.</li>
<li>Fixed configuration loading in the <code>quartz</code> plugin.</li>
<li>Fixed an error in <code>grails-bom</code> with handling inherited BOMs from <code>spring-boot-dependencies</code>.</li>
</ul>
<h2>Dependency Upgrades</h2>
<p>In this release, we've upgraded several dependency versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.8</li>
<li>Groovy 4.0.25</li>
<li>Jna 5.16.0</li>
<li>MongoDB driver: 5.3.1</li>
<li>Slf4j 2.0.16</li>
<li>Spring Boot 3.4.2</li>
<li>Spring Framework 6.2.2</li>
<li>See all in the <a href="https://central.sonatype.com/artifact/org.grails/grails-bom/7.0.0-M3">grails-bom</a>.</li>
</ul>
<p>As part of the Grails 7.0.0-M3 release we have also released milestones of the following:</p>
<ul>
<li>org.grails.plugins:async:7.0.0-M3</li>
<li>org.grails.plugins:audit-logging:6.0.0-M4</li>
<li>org.grails.plugins:cache:8.0.0-M3</li>
<li>org.grails.plugins:converters:7.0.0-M3</li>
<li>org.grails.plugins:database-migration:9.0.0-M3</li>
<li>org.grails.plugins:events:7.0.0-M3</li>
<li>org.grails.plugins:fields:6.0.0-M3</li>
<li>org.grails.plugins:geb:5.0.0-M3</li>
<li>org.grails.plugins:grails-redis:5.0.0-M3</li>
<li>org.grails.plugins:grails-web-console:7.0.0-M2</li>
<li>org.grails.plugins:gsp:7.0.0-M3</li>
<li>org.grails.plugins:hibernate5:9.0.0-M3</li>
<li>org.grails.plugins:mongodb:9.0.0-M3</li>
<li>org.grails.plugins:quartz:4.0.0-M2</li>
<li>org.grails.plugins:scaffolding:6.0.0-M3</li>
<li>org.grails.plugins:spring-security-acl:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-cas:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-core:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-ldap:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-oauth2:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest-gorm:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest-grailscache:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest-memcached:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest-redis:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-rest-testapp-profile:7.0.0-M3</li>
<li>org.grails.plugins:spring-security-ui:7.0.0-M3</li>
<li>org.grails.plugins:views-gradle:4.0.0-M3</li>
<li>org.grails.plugins:views-json:4.0.0-M3</li>
<li>org.grails.plugins:views-json-templates:9.0.0-M3</li>
<li>org.grails.plugins:views-markup:4.0.0-M3</li>
<li>org.grails.profiles:angular:10.0.2</li>
<li>org.grails.profiles:base:10.0.2</li>
<li>org.grails.profiles:plugin:10.0.2</li>
<li>org.grails.profiles:profile:10.0.2</li>
<li>org.grails.profiles:react:10.0.2</li>
<li>org.grails.profiles:rest-api:10.0.2</li>
<li>org.grails.profiles:rest-api-plugin:10.0.2</li>
<li>org.grails.profiles:vue:10.0.2</li>
<li>org.grails.profiles:web:10.0.2</li>
<li>org.grails.profiles:web-plugin:10.0.2</li>
<li>org.grails:grails-async:7.0.0-M3</li>
<li>org.grails:grails-async-gpars:7.0.0-M3</li>
<li>org.grails:grails-async-rxjava:7.0.0-M3</li>
<li>org.grails:grails-async-rxjava2:7.0.0-M3</li>
<li>org.grails:grails-bootstrap:7.0.0-M3</li>
<li>org.grails:grails-codecs:7.0.0-M3</li>
<li>org.grails:grails-console:7.0.0-M3</li>
<li>org.grails:grails-core:7.0.0-M3</li>
<li>org.grails:grails-databinding:7.0.0-M3</li>
<li>org.grails:grails-datastore-async:9.0.0-M3</li>
<li>org.grails:grails-datastore-core:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-async:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-hibernate5:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-mongodb:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-rx:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-support:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-tck:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-test:9.0.0-M3</li>
<li>org.grails:grails-datastore-gorm-validation:9.0.0-M3</li>
<li>org.grails:grails-datastore-web:9.0.0-M3</li>
<li>org.grails:grails-dependencies:7.0.0-M3</li>
<li>org.grails:grails-docs:7.0.0-M3</li>
<li>org.grails:grails-encoder:7.0.0-M3</li>
<li>org.grails:grails-events-gpars:7.0.0-M3</li>
<li>org.grails:grails-events-rxjava:7.0.0-M3</li>
<li>org.grails:grails-events-rxjava2:7.0.0-M3</li>
<li>org.grails:grails-gorm-testing-support:9.0.0-M3</li>
<li>org.grails:grails-gradle-model:7.0.0-M3</li>
<li>org.grails:grails-gradle-plugin:7.0.0-M4</li>
<li>org.grails:grails-gsp:7.0.0-M3</li>
<li>org.grails:grails-logging:7.0.0-M3</li>
<li>org.grails:grails-plugin-codecs:7.0.0-M3</li>
<li>org.grails:grails-plugin-controllers:7.0.0-M3</li>
<li>org.grails:grails-plugin-databinding:7.0.0-M3</li>
<li>org.grails:grails-plugin-datasource:7.0.0-M3</li>
<li>org.grails:grails-plugin-domain-class:7.0.0-M3</li>
<li>org.grails:grails-plugin-i18n:7.0.0-M3</li>
<li>org.grails:grails-plugin-interceptors:7.0.0-M3</li>
<li>org.grails:grails-plugin-mimetypes:7.0.0-M3</li>
<li>org.grails:grails-plugin-rest:7.0.0-M3</li>
<li>org.grails:grails-plugin-services:7.0.0-M3</li>
<li>org.grails:grails-plugin-url-mappings:7.0.0-M3</li>
<li>org.grails:grails-plugin-validation:7.0.0-M3</li>
<li>org.grails:grails-shell:7.0.0-M3</li>
<li>org.grails:grails-spring:7.0.0-M3</li>
<li>org.grails:grails-test:7.0.0-M3</li>
<li>org.grails:grails-testing-support:7.0.0-M3</li>
<li>org.grails:grails-test-suite-base:7.0.0-M3</li>
<li>org.grails:grails-test-suite-persistence:7.0.0-M3</li>
<li>org.grails:grails-test-suite-uber:7.0.0-M3</li>
<li>org.grails:grails-test-suite-web:7.0.0-M3</li>
<li>org.grails:grails-web:7.0.0-M3</li>
<li>org.grails:grails-web-boot:7.0.0-M3</li>
<li>org.grails:grails-web-common:7.0.0-M3</li>
<li>org.grails:grails-web-databinding:7.0.0-M3</li>
<li>org.grails:grails-web-gsp:7.0.0-M3</li>
<li>org.grails:grails-web-mvc:7.0.0-M3</li>
<li>org.grails:grails-web-taglib:7.0.0-M3</li>
<li>org.grails:grails-web-testing-support:7.0.0-M3</li>
<li>org.grails:grails-web-url-mappings:7.0.0-M3</li>
<li>org.grails:grails7-wrapper:6.0.0</li>
<li>org.grails:views-json-testing-support:4.0.0-M3</li>
</ul>
<h2>Installing Grails 7.0.0-M3</h2>
<p>Try out Grails 7.0.0-M3 today by visiting the online app creator * <a href="https://start.grails.org/">Grails Forge</a>.
Alternatively, you can quickly install Grails 7.0.0-M3 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a>
to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-M3:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-M3
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-M3</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-M3 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-M3
# The Grails Gradle Plugin version is now available in the BOM
# and can be omitted if your project adds the Grails BOM to the
# buildscript dependencies.
grailsGradlePluginVersion=7.0.0-M4
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with
the new version. See https://grails.apache.org/docs/7.0.0-M3/guide/upgrading.html#upgrading60x.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you
have specific versions defined in your build configuration, you may need to manually update them to align with
Grails 7.0.0-M3.</p>
<p>By following these steps, you should be able to transition your existing Grails application to Grails 7.0.0-M3.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-M3. Compare the
versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a
reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or
<a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically
detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in
manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and
improvements in Grails 7.0.0-M3. Happy coding!</p>
<h2>Why should you try out Grails 7.0.0-M3?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/grails/projects/3">updating and fixing issues</a> over the next few
weeks.</li>
<li>Apache Grails 7.0.0-M4 will be released thereafter under the Apache Software Foundation.</li>
<li>Based on feedback, an Apache Grails final milestone or RC release is targeted for April 2025.</li>
</ul>
<h2>Thank you!</h2>
<p>A huge thank you to our amazing community for supporting the Grails Framework over the past 19 years! We’re excited for
the future and grateful for the opportunity to continue innovating and pushing Grails forward together.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-M3 possible. <br />
Special thanks to:</p>
<ul>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/JonasPammer">Jonas Pammer</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-M3.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in
the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2025-03-05-grails-7-m3</guid><pubDate>Wed, 05 Mar 2025 00:00:00 GMT</pubDate></item><item><title>Introducing Grails Framework 6.2.3 Release</title><link>https://grails.apache.org/blog/2025-01-03-introducing-grails-6-2-3.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited to announce the release of Grails framework 6.2.3. This latest version delivers a key bug fix.</p>
<h2>Bug Fixes and Improvements</h2>
<p>Grails 6.2.3 addresses a critical bug fixes:</p>
<ul>
<li>Fixes an edge cases that causes a cast class exception when inherited commands are used as an action parameter.</li>
</ul>
<h2>Dependency Upgrades</h2>
<p>Keeping up with the latest dependencies is crucial for the health of any framework. In this release, we have upgraded various dependencies to their latest versions, including but not limited to the following:</p>
<ul>
<li><code>org.grails:grails-gradle-plugin</code> to version 6.2.4</li>
<li><code>org.apache.tomcat:tomcat-jdbc</code> to version 9.0.98</li>
<li><code>org.apache.tomcat.embed:tomcat-embed-core</code> to version 9.0.98</li>
</ul>
<p>These upgrades ensure that Grails 6.2.3 remains compatible with the latest libraries and tools, providing developers with a robust and reliable environment. We recommend checking out the <a href="https://github.com/apache/grails-core/releases/tag/v6.2.3">GitHub release page</a> for more information.</p>
<h2>Installing Grails 6.2.3</h2>
<p>You can get started with Grails 6.2.3 today by visiting our <a href="https://start.grails.org/">official website</a>. Alternatively, you can quickly install Grails 6.2.3 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 6.2.3:</p>
<pre><code class="language-shell">sdk install grails 6.2.3
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 6.2.3</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.propreties</code> file to specify Grails 6.2.3 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=6.2.3
grailsGradlePluginVersion=6.2.4
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with the new version.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you have specific versions defined in your build configuration, you may need to manually update them to align with Grails 6.2.3.</p>
<p>By following these steps, you can smoothly transition your existing Grails application to the exciting Grails 6.2.3.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">https://start.grails.org</a> and generate a new Grails application with Grails 6.2.3. Compare the versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or <a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and improvements in Grails 6.2.3. Happy coding!</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack community</a>, share your feedback, and contribute to making Grails framework even better in the future. Happy coding!</p>]]></description><author>James Daugherty</author><guid>2025-01-03-introducing-grails-6-2-3</guid><pubDate>Fri, 03 Jan 2025 00:00:00 GMT</pubDate></item><item><title>James Fredley Named 2025 Grails® Rock Star</title><link>https://grails.apache.org/blog/2025-01-02-grails-community-rockstar-fredley.html</link><description><![CDATA[</p>
<p>Happy New Year!</p>
<p>The Grails Foundation is recognizing and celebrating great leadership and
stewardship from <a href="https://github.com/jamesfredley">James Fredley</a>.</p>
<h2>Thank You James Fredley!</h2>
<p>The Grails Foundation and Object Computing have been supporting the Grails
community, with a special focus on Grails 6.2.x and the upcoming Grails 7
release expected in Q1 2025. This new release will streamline many aspects of
the framework, update dependencies, and introduce exciting new capabilities. The
team’s dedication has been exceptional, and the community is deeply appreciative
of their efforts.</p>
<p>As with projects at the Apache Foundation, Grails doesn’t have a formal project
or technical lead. Instead, leadership naturally emerges from those who
contribute. James Fredley is one such individual who has been instrumental in
driving the team forward on Grails 7. His technical expertise on the complex
codebase has been invaluable, but perhaps even more remarkable is his role as a
caring and supportive steward of the technology.</p>
<p>James is a sharp technologist who excels in guiding technical discussions, even
when opinions clash. His ability to lead these conversations to a productive
outcome, regardless of where the team initially stands, demonstrates not only
his technical skill but also his exceptional leadership and character. He is a
true asset to the team and the community.
James’ contributions go far beyond code; his leadership and personal dedication
to the Grails project have been key toward making Grails 7 a reality. I do not
believe that Grails 7 would be in the great position that it is in right now if
it were not for the dedication and commitment that James has invested.  It is
with great appreciation that we recognize James as a <a href="/community.html">Grails Community Rock Star</a>.
Please join us in thanking James Fredley for everything he has done to elevate
Grails to new heights. His efforts are deeply valued. James, you truly are a
Grails leader and a great person. Please keep up the fantastic work!</p>
<p>Thank you, James!</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack community</a>, share your feedback, and contribute to making Grails framework even better in the future. Happy coding!</p>]]></description><author>Jeff Scott Brown</author><guid>2025-01-02-grails-community-rockstar-fredley</guid><pubDate>Thu, 02 Jan 2025 00:00:00 GMT</pubDate></item><item><title>Grails 7.0.0-M1 - Release Announcement</title><link>https://grails.apache.org/blog/2024-12-23-grails-7-m1.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited for the release of Grails Framework 7.0.0-M1.<br />
We encourage you to try this pre-release and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>What's Changed</h2>
<ul>
<li>New minimum versions introduced:
<ol>
<li>Gradle 8</li>
<li>Groovy 4</li>
<li>Java 17</li>
<li>Sitemesh 3</li>
<li>Spring Boot 3.4 (Spring Framework 6.2)</li>
</ol>
</li>
<li>Default integration of the Micronaut Framework has been removed from Grails. Use <a href="https://micronaut-projects.github.io/micronaut-spring/latest/guide/">Micronaut for Spring</a> to add Micronaut support to your Grails application.</li>
</ul>
<h3>With the release of Grails 7.0.0-M1, we have:</h3>
<ul>
<li>Added support for:
<ol>
<li>Gradle 8.12</li>
<li>Groovy 4.0.24</li>
<li>Java 17-23, 17 and 21 are LTS</li>
<li>Sitemesh 3</li>
<li>Spring Boot 3.4.1 &amp; Spring Framework 6.2.1, including transition from <code>javax</code> to <code>jakarta</code> namespace.</li>
</ol>
</li>
<li>Added default support for containerized browser testing using <a href="https://java.testcontainers.org/">Testcontainers</a> through the <a href="https://github.com/apache/grails-core/tree/HEAD/grails-geb#readme">Geb Grails Plugin</a>, eliminating web browser version synchronization issues. A <a href="https://github.com/apache/grails-core/tree/HEAD/grails-geb#containergebspec-recommended">container runtime environment</a> is now required for Geb functional and integration tests.
<ol>
<li>This has also been backported for Grails 6.x compatiblility via <a href="https://github.com/apache/grails-geb/releases/tag/v4.1.1">Geb 4.1.1</a></li>
</ol>
</li>
<li><a href="https://java.testcontainers.org/">Testcontainers</a> features are also available on <a href="https://start.grails.org/">Grails Forge</a> and Grails Forge CLI for MySQL, PostgreSQL, SQL Server and MongoDB.</li>
<li>Support for Live Reload via Hotswap Agent: <a href="https://github.com/apache/grails-forge/issues/445">current integration details</a>.  This was made possible by the removal of the default Micronaut parent application context.</li>
<li>Reintroduced the <code>grails-shell</code>, <code>grails-wrapper</code> and <code>grails-profiles</code> that were removed in Grails 6.
<ol>
<li>Update to the latest wrapper release based on Grails version with <code>./grailsw update-wrapper</code></li>
</ol>
</li>
<li>Updated the default styling to use Bootstrap 5.3.3. Both <a href="https://github.com/apache/grails-core/tree/HEAD/grails-scaffolding#readme">Scaffolding</a> and <a href="https://github.com/apache/grails-core/tree/HEAD/grails-fields#readme">Fields</a> now support Bootstrap classes.</li>
<li>Reduced deployment sizes (currently pending, due to Graalvm dependencies required for test and bootRun by <code>asset-pipeline</code>).</li>
<li>Enhanced the <a href="https://mvnrepository.com/artifact/org.grails/grails-bom">Grails BOM</a> by adding more versions and extending the <a href="https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-dependencies">Spring Boot BOM</a> for streamlined dependency management. Grails Gradle Plugins apply the BOM by default. If using <code>buildSrc</code>, ensure it is manually applied.</li>
<li>Removed the <code>-plain</code> suffix from the JAR artifact output in Grails Plugin projects.</li>
<li>Disabled all artifact outputs except the JAR artifact for the <code>assemble</code> task in Grails Plugin projects.</li>
<li>Introduced a new tag, <code>g:formActionSubmit</code>, to support submitting forms to different actions. The <code>g:actionSubmit</code> tag is now deprecated and will be removed in a future release.</li>
<li>Introduced a new annotation, <code>@Scaffold</code>, for Controllers and Services to eliminate common boilerplate in the <a href="https://github.com/apache/grails-core/tree/HEAD/grails-scaffolding#readme">Scaffolding Plugin</a>.</li>
<li>Resolved multiple issues related to Controller namespace support.</li>
<li>Begun the process of discontinuing bean overriding in the core framework by adopting standard <a href="https://docs.spring.io/spring-boot/reference/using/auto-configuration.html">Spring Auto-configuration</a>.</li>
<li>Enhanced the <code>g:form</code> tag to include CSRF protection when Spring Security CSRF is enabled.</li>
<li>Decoupled a significant amount of dependencies in Grails, enabling easier maintenance moving forward.</li>
<li>Upgraded external dependencies to the latest available versions.</li>
<li>Removed tight coupling with Sitemesh. Sitemesh 3 is now the default version.</li>
<li>Default Support for evironment specific logging configuration via Spring Logback Extensions in <code>logback-spring.xml</code></li>
<li><a href="https://start.grails.org/">Grails Forge</a> does not generate <code>buildSrc/</code> or <code>settings.gradle</code> by default, but they are optional features.  This simplifies build and Gradle plugin configuration and consolidates version management into one location.</li>
</ul>
<h2>Dependency Upgrades</h2>
<p>Staying current with the latest dependencies is essential for the health of any framework. In this release, we've upgraded several dependencies to their latest versions, including but not limited to the following:</p>
<ul>
<li>Asset Pipeline 5.0.5</li>
<li>Geb 7.0</li>
<li>H2 2.3.232</li>
<li>Hibernate 5.6.15.Final (Jakarta version)</li>
<li>Jackson 2.18.2</li>
<li>Jakarta Servlet 6.0.0</li>
<li>JUnit 5.11.4</li>
<li>Sitemesh 3.2.2</li>
<li>Slf4j 2.0.16</li>
<li>Snakeyaml 2.3</li>
<li>Spring Boot 3.4.1</li>
<li>Spring Framework 6.2.1</li>
<li>Tomcat 10.1.34</li>
<li>see all on <a href="https://mvnrepository.com/artifact/org.grails/grails-bom/7.0.0-M1">Grails-BOM</a></li>
</ul>
<p>As part of the Grails 7.0.0-M1 release we have also released milestones of the following:</p>
<ul>
<li>org.grails.plugins:async:6.0.0-M2</li>
<li>org.grails.plugins:audit-logging:6.0.0-M4</li>
<li>org.grails.plugins:cache:8.0.0-M2</li>
<li>org.grails.plugins:converters:6.0.0-M1</li>
<li>org.grails.plugins:database-migration:6.0.0-M1</li>
<li>org.grails.plugins:events:6.0.0-M2</li>
<li>org.grails.plugins:fields:6.0.0-M1</li>
<li>org.grails.plugins:geb:5.0.0-M2</li>
<li>org.grails.plugins:grails-redis:5.0.0-M1</li>
<li>org.grails.plugins:grails-web-console:7.0.0-M2</li>
<li>org.grails.plugins:gsp:7.0.0-M1</li>
<li>org.grails.plugins:hibernate5:9.0.0-M2</li>
<li>org.grails.plugins:mongodb:9.0.0-M2</li>
<li>org.grails.plugins:quartz:4.0.0-M1</li>
<li>org.grails.plugins:scaffolding:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-core:7.0.0-M1</li>
<li>org.grails.plugins:spring-security-ldap:5.0.0-M2</li>
<li>org.grails.plugins:spring-security-rest:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-rest-gorm:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-rest-grailscache:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-rest-memcached:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-rest-redis:6.0.0-M1</li>
<li>org.grails.plugins:spring-security-rest-testapp-profile:6.0.0-M1</li>
<li>org.grails.plugins:views-gradle:4.0.0-M1</li>
<li>org.grails.plugins:views-json:4.0.0-M1</li>
<li>org.grails.plugins:views-json-templates:9.0.0-M2</li>
<li>org.grails.plugins:views-markup:4.0.0-M1</li>
<li>org.grails.profiles:angular:10.0.1</li>
<li>org.grails.profiles:base:7.0.1</li>
<li>org.grails.profiles:plugin:7.0.1</li>
<li>org.grails.profiles:profile:7.0.1</li>
<li>org.grails.profiles:react:7.0.1</li>
<li>org.grails.profiles:rest-api:7.0.1</li>
<li>org.grails.profiles:rest-api-plugin:7.0.1</li>
<li>org.grails.profiles:vue:7.0.1</li>
<li>org.grails.profiles:web:7.0.1</li>
<li>org.grails.profiles:web-plugin:7.0.1</li>
<li>org.grails:grails-async:6.0.0-M2</li>
<li>org.grails:grails-async-gpars:6.0.0-M2</li>
<li>org.grails:grails-async-rxjava:6.0.0-M2</li>
<li>org.grails:grails-async-rxjava2:6.0.0-M2</li>
<li>org.grails:grails-bootstrap:7.0.0-M1</li>
<li>org.grails:grails-codecs:7.0.0-M1</li>
<li>org.grails:grails-console:7.0.0-M1</li>
<li>org.grails:grails-core:7.0.0-M1</li>
<li>org.grails:grails-databinding:7.0.0-M1</li>
<li>org.grails:grails-datastore-async:9.0.0-M2</li>
<li>org.grails:grails-datastore-core:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-async:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-hibernate5:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-mongodb:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-rx:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-support:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-tck:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-test:9.0.0-M2</li>
<li>org.grails:grails-datastore-gorm-validation:9.0.0-M2</li>
<li>org.grails:grails-datastore-web:9.0.0-M2</li>
<li>org.grails:grails-dependencies:7.0.0-M1</li>
<li>org.grails:grails-docs:7.0.0-M1</li>
<li>org.grails:grails-encoder:7.0.0-M1</li>
<li>org.grails:grails-events-gpars:6.0.0-M2</li>
<li>org.grails:grails-events-rxjava:6.0.0-M2</li>
<li>org.grails:grails-events-rxjava2:6.0.0-M2</li>
<li>org.grails:grails-gorm-testing-support:4.0.0-M2</li>
<li>org.grails:grails-gradle-model:7.0.0-M1</li>
<li>org.grails:grails-gradle-plugin:7.0.0-M3</li>
<li>org.grails:grails-gsp:7.0.0-M1</li>
<li>org.grails:grails-logging:7.0.0-M1</li>
<li>org.grails:grails-plugin-codecs:7.0.0-M1</li>
<li>org.grails:grails-plugin-controllers:7.0.0-M1</li>
<li>org.grails:grails-plugin-databinding:7.0.0-M1</li>
<li>org.grails:grails-plugin-datasource:7.0.0-M1</li>
<li>org.grails:grails-plugin-domain-class:7.0.0-M1</li>
<li>org.grails:grails-plugin-i18n:7.0.0-M1</li>
<li>org.grails:grails-plugin-interceptors:7.0.0-M1</li>
<li>org.grails:grails-plugin-mimetypes:7.0.0-M1</li>
<li>org.grails:grails-plugin-rest:7.0.0-M1</li>
<li>org.grails:grails-plugin-services:7.0.0-M1</li>
<li>org.grails:grails-plugin-url-mappings:7.0.0-M1</li>
<li>org.grails:grails-plugin-validation:7.0.0-M1</li>
<li>org.grails:grails-shell:7.0.0-M1</li>
<li>org.grails:grails-spring:7.0.0-M1</li>
<li>org.grails:grails-test:7.0.0-M1</li>
<li>org.grails:grails-testing-support:4.0.0-M2</li>
<li>org.grails:grails-test-suite-base:7.0.0-M1</li>
<li>org.grails:grails-test-suite-persistence:7.0.0-M1</li>
<li>org.grails:grails-test-suite-uber:7.0.0-M1</li>
<li>org.grails:grails-test-suite-web:7.0.0-M1</li>
<li>org.grails:grails-web:7.0.0-M1</li>
<li>org.grails:grails-web-boot:7.0.0-M1</li>
<li>org.grails:grails-web-common:7.0.0-M1</li>
<li>org.grails:grails-web-databinding:7.0.0-M1</li>
<li>org.grails:grails-web-gsp:7.0.0-M1</li>
<li>org.grails:grails-web-mvc:7.0.0-M1</li>
<li>org.grails:grails-web-taglib:7.0.0-M1</li>
<li>org.grails:grails-web-testing-support:4.0.0-M2</li>
<li>org.grails:grails-web-url-mappings:7.0.0-M1</li>
<li>org.grails:grails7-wrapper:6.0.0</li>
<li>org.grails:views-json-testing-support:4.0.0-M1</li>
</ul>
<h2>Installing Grails 7.0.0-M1</h2>
<p>Try out Grails 7.0.0-M1 today by visiting the online app creator * <a href="https://start.grails.org/">Grails Forge</a>.
Alternatively, you can quickly install Grails 7.0.0-M1 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 7.0.0-M1:</p>
<pre><code class="language-shell">sdk install grails 7.0.0-M1
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 7.0.0-M1</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.properties</code> file to specify Grails 7.0.0-M1 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=7.0.0-M1
grailsGradlePluginVersion=7.0.0-M3
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with the new version. See https://grails.apache.org/docs/7.0.0-M1/guide/upgrading.html#upgrading60x.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you have specific versions defined in your build configuration, you may need to manually update them to align with Grails 7.0.0-M1.</p>
<p>By following these steps, you can smoothly transition your existing Grails application to the exciting Grails 7.0.0-M1.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">Grails Forge</a> and generate a new Grails application with Grails 7.0.0-M1. Compare the versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or <a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and improvements in Grails 7.0.0-M1. Happy coding!</p>
<h2>Why should you try out Grails 7.0.0-M1?</h2>
<ul>
<li>Help us test this major upgrade of the Grails Framework and provide feedback.</li>
<li>Be ready for when Grails 7 is released.</li>
</ul>
<h2>Grails 7 Release Schedule</h2>
<ul>
<li>We will continue to work on <a href="https://github.com/orgs/grails/projects/3">updating and fixing issues</a> over the next few weeks.</li>
<li>Grails 7 M2 will be released thereafter.</li>
<li>Based on feedback, a Grails GA or RC release is targeted for March 2025.</li>
</ul>
<h2>Thank you!</h2>
<p>Big thanks to our wonderful community of users for your continued support of the Grails Framework over the past 19 years!
With a hopeful outlook towards the future and a deep sense of gratitude, we eagerly anticipate the path that lies ahead, embracing the invaluable chance to develop and pioneer new advancements within this framework.</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 7.0.0-M1 possible. Special thanks to:</p>
<ul>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/amondel2">Aaron Mondelblatt</a></li>
<li><a href="https://github.com/arjangch">Arjang Chinichian</a></li>
<li><a href="https://github.com/bkoehm">Brian Koehmstedt</a></li>
<li><a href="https://github.com/gsartori">Gianluca Sartori</a></li>
<li><a href="https://github.com/tylervz">Tyler VanZanten</a></li>
<li><a href="https://github.com/vsachinv">Sachin Verma</a></li>
<li><a href="https://github.com/guillermocalvo">Guillermo Calvo</a></li>
<li><a href="https://github.com/puneetbehl">Puneet Behl</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the release of Grails 7.0.0-M1.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack Community</a>, share your feedback, and contribute to making Grails Framework even better in the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2024-12-23-grails-7-m1</guid><pubDate>Mon, 23 Dec 2024 00:00:00 GMT</pubDate></item><item><title>Introducing Grails Framework 6.2.2 Release</title><link>https://grails.apache.org/blog/2024-11-20-introducing-grails-6-2-2.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited to announce the release of Grails framework 6.2.2. This latest version delivers bug fixes and reintroduces key features based on community feedback.</p>
<h2>What's Changed</h2>
<p>In this release, we have made several changes to improve the framework's performance and maintainability. Some of the notable changes include:</p>
<ul>
<li>
<p><strong>Simplify Generated Build</strong>:</p>
<ul>
<li>Consolidates Gradle Plugin configuration to buildscript{}, plugins{} and apply plugin: in build.gradle</li>
<li>Changes Gradle buildSrc/build.gradle and Settings File to non-default, optional features</li>
<li>When the Gradle Settings File feature is selected, it only contains one line defining the root project</li>
<li>When the Gradle buildSrc feature is selected buildscript{} is not generated, they are equivalent</li>
<li>These changes allow Gradle plugins to be defined in one location and for consolidation of dependency version resolution.</li>
</ul>
</li>
<li>
<p><strong>Grails Wrapper</strong>:</p>
<ul>
<li>Make grails-wrapper a default feature</li>
<li>Ensure grails-wrapper files exist in native grails-forge-cli builds</li>
<li>Put profile information in all locations required by grails-shell and grails-wrapper</li>
</ul>
</li>
</ul>
<h2>Bug Fixes and Improvements</h2>
<p>Grails 6.2.2 also addresses several bug fixes and improvements, including:</p>
<ul>
<li>Set asset-pipeline skipNonDigest to true, which reduces jar/war files size</li>
<li>Include development, test and production dataSource configurations in generated application.yml</li>
<li>Default generated applications to Java 11, 17 is optional</li>
<li>gorm-hibernate5: Create foreign key constraint when tablePerHierarchy=false</li>
<li>Remove -plain from Grails plugin jar filenames</li>
<li>fields: Fix for invalid class not rendering on widget</li>
<li>scaffolding: remove dependency on org.grails:grails-dependencies</li>
</ul>
<p>These updates will enhance the stability and reliability of the framework.</p>
<h2>Dependency Upgrades</h2>
<p>Keeping up with the latest dependencies is crucial for the health of any framework. In this release, we have upgraded various dependencies to their latest versions, including but not limited to the following:</p>
<ul>
<li><code>org.grails:grails-gradle-plugin</code> to version 6.2.3</li>
<li><code>org.codehaus.groovy:groovy</code> to version 3.0.23</li>
<li><code>org.grails.plugins:hibernate5</code> to version 8.1.1</li>
<li><code>com.bertramlabs.asset-pipeline</code> to version 4.5.1</li>
<li><code>com.bertramlabs.asset-pipeline:asset-pipeline-grails</code> to version 4.5.1</li>
<li><code>org.grails.plugins:fields</code> to version 5.1.1</li>
<li><code>org.grails.plugins:scaffolding</code> to version 5.1.3</li>
<li><code>org.grails.plugins:gsp</code> to version 6.2.4</li>
<li><code>org.apache.tomcat:tomcat-jdbc</code> to version 9.0.97</li>
<li><code>org.apache.tomcat.embed:tomcat-embed-core</code> to version 9.0.97</li>
<li><code>org.apache.ant:ant</code> to version 1.10.15</li>
<li><code>org.aspectj:aspectjrt</code> to version 1.9.22.1</li>
<li><code>org.mongodb:mongo-driver</code> to version 4.11.5</li>
<li>And many more transitive dependencies.</li>
</ul>
<p>These upgrades ensure that Grails 6.2.2 remains compatible with the latest libraries and tools, providing developers with a robust and reliable environment. We recommend checking out the <a href="https://github.com/apache/grails-core/releases/tag/v6.2.2">GitHub release page</a> for more information.</p>
<h2>Installing Grails 6.2.2</h2>
<p>You can get started with Grails 6.2.2 today by visiting our <a href="https://start.grails.org/">official website</a>. Alternatively, you can quickly install Grails 6.2.2 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 6.2.2:</p>
<pre><code class="language-shell">sdk install grails 6.2.2
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 6.2.2</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.propreties</code> file to specify Grails 6.2.2 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=6.2.2
grailsGradlePluginVersion=6.2.3
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with the new version.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you have specific versions defined in your build configuration, you may need to manually update them to align with Grails 6.2.2.</p>
<p>By following these steps, you can smoothly transition your existing Grails application to the exciting Grails 6.2.2.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">https://start.grails.org</a> and generate a new Grails application with Grails 6.2.2. Compare the versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or <a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and improvements in Grails 6.2.2. Happy coding!</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 6.2.2 possible. Special thanks to:</p>
<ul>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/guillermocalvo">Guillermo Calvo</a></li>
<li><a href="https://github.com/jdaugherty">James Daugherty</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the success of Grails 6.2.2.</p>
<p>With all these exciting changes and improvements, Grails 6.2.2 is set to offer an even better experience for developers working on web applications. Whether you're an experienced Grails developer or just getting started, this release has something for everyone.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack community</a>, share your feedback, and contribute to making Grails framework even better in the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2024-11-20-introducing-grails-6-2-2</guid><pubDate>Wed, 20 Nov 2024 00:00:00 GMT</pubDate></item><item><title>Introducing Grails Framework 6.2.1 Release</title><link>https://grails.apache.org/blog/2024-10-03-introducing-grails-6-2-1.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited to announce the release of Grails framework 6.2.1. This latest version delivers critical bug fixes and reintroduces key features based on community feedback.</p>
<h2>What's Changed</h2>
<p>The 6.2.1 release, while being a patch release, brings back the Grails Shell, Profiles and Wrapper (as an optional feature) and addresses some bugs.</p>
<ul>
<li><strong>Grails Shell, Profiles and Wrapper</strong>:
<ul>
<li>Reintroduces the Grails Shell and Profiles in response to community feedback, addressing a key feature loss identified by users including:
<ul>
<li>enables the IntelliJ Grails Plugin to load in IntelliJ</li>
<li>execution of Grails scripts that have not been migrated to Gradle such as <strong>grails list-plugins</strong> and <strong>grails dbm-update</strong></li>
<li>execution of custom company/internal Grails scripts</li>
<li>continued use of custom company/internal profiles</li>
</ul>
</li>
<li>Grails Wrapper is now an optional feature from Grails Forge via the Grails distribution or <a href="https://start.grails.org/">https://start.grails.org/</a>
<ul>
<li>you can now run <strong>./grailsw update-wrapper</strong> to get the latest grails wrapper version based on the Grails version</li>
</ul>
</li>
</ul>
</li>
</ul>
<h2>Bug Fixes and Improvements</h2>
<p>Grails 6.2.1 also addresses several bug fixes and improvements, including:</p>
<ul>
<li>Fixes a lack of a “controller” attribute in GSP tags with a “resource” attribute</li>
<li>Fixes a bug in LinkGenerator when domain classes have a static id mapping to another property, that is not “id”</li>
<li>Fixes a problem finding the main class when running CLI commands</li>
<li>Fixes an edge cases that causes a cast class exception when the same variable name is used as arguments to multiple actions</li>
</ul>
<p>These updates will enhance the stability and reliability of the framework.</p>
<h2>Dependency Upgrades</h2>
<p>Keeping up with the latest dependencies is crucial for the health of any framework. In this release, we have upgraded various dependencies to their latest versions, including but not limited to the following:</p>
<ul>
<li><code>com.github.javaparser:javaparser-core</code> to version 3.25.10</li>
<li><code>ch.qos.logback:logback-classic</code> to version 1.2.13</li>
<li><code>org.springframework:spring-core</code> to version 5.3.39</li>
<li><code>org.grails:grails-testing-support</code> to version 3.2.2</li>
<li><code>org.apache.tomcat:tomcat-jdbc</code> to version 9.0.95</li>
<li><code>org.grails.plugins:fields</code> to version 5.1.0</li>
<li><code>org.grails.plugins:scaffolding</code> to version 5.1.2</li>
<li><code>org.grails:grails-shell</code> to version 6.2.1</li>
<li><code>org.grails:grails6-wrapper</code> to version 4.0.1</li>
<li><code>org.grails.plugins:gsp</code> to version 6.2.2</li>
<li><code>org.grails.profiles:base</code> to version 6.0.1</li>
<li><code>org.grails.profiles:web</code> to version 6.0.1</li>
<li><code>org.grails.profiles:profile</code> to version 6.0.1</li>
<li><code>org.grails.profiles:plugin</code> to version 6.0.1</li>
<li><code>org.grails.profiles:web-plugin</code> to version 6.0.1</li>
<li><code>org.grails.profiles:rest-api</code> to version 6.0.1</li>
<li><code>org.grails.profiles:rest-api-plugin</code> to version 6.0.1</li>
<li><code>org.grails.profiles:react</code> to version 6.0.1</li>
<li><code>org.grails.profiles:vue</code> to version 6.0.1</li>
<li><code>org.grails.profiles:angular</code> to version 9.0.1</li>
<li>And many more transitive dependencies.</li>
</ul>
<p>These upgrades ensure that Grails 6.2.1 remains compatible with the latest libraries and tools, providing developers with a robust and reliable environment. We recommend checking out the <a href="https://github.com/apache/grails-core/releases/tag/v6.2.1">GitHub release page</a> for more information.</p>
<h2>Installing Grails 6.2.1</h2>
<p>You can get started with Grails 6.2.1 today by visiting our <a href="https://start.grails.org/">official website</a>. Alternatively, you can quickly install Grails 6.2.1 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 6.2.1:</p>
<pre><code class="language-shell">sdk install grails 6.2.1
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 6.2.1</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.propreties</code> file to specify Grails 6.2.1 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=6.2.1
grailsGradlePluginVersion=6.2.1
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with the new version.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you have specific versions defined in your build configuration, you may need to manually update them to align with Grails 6.2.1.</p>
<p>By following these steps, you can smoothly transition your existing Grails application to the exciting Grails 6.2.1.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting, or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">https://start.grails.org</a> and generate a new Grails application with Grails 6.2.1. Compare the versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or <a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and improvements in Grails 6.2.1. Happy coding!</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 6.2.1 possible. Special thanks to:</p>
<ul>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
<li><a href="https://github.com/jamesfredley">James Fredley</a></li>
<li><a href="https://github.com/puneetbehl">Puneet Behl</a></li>
<li><a href="https://github.com/sbglasius">Søren Berg Glasius</a></li>
<li><a href="https://github.com/davydotcom">David Estes</a></li>
<li><a href="https://github.com/paulk-asert">Paul King</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the success of Grails 6.2.1.</p>
<p>With all these exciting changes and improvements, Grails 6.2.1 is set to offer an even better experience for developers working on web applications. Whether you're an experienced Grails developer or just getting started, this release has something for everyone.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack community</a>, share your feedback, and contribute to making Grails framework even better in the future. Happy coding!</p>]]></description><author>James Fredley</author><guid>2024-10-03-introducing-grails-6-2-1</guid><pubDate>Thu, 03 Oct 2024 00:00:00 GMT</pubDate></item><item><title>Grails Community Contributions</title><link>https://grails.apache.org/blog/2024-10-01-grails-community-contributions.html</link><description><![CDATA[</p>
<p><strong>Grails Community Contributions</strong></p>
<p>As a follow-up to our <a href="/blog/2024-06-07-grails-future.html">blog post</a> a few months ago, we have worked with the community to assemble a Grails Community Steering Committee and enabled <a href="https://github.com/orgs/grails/discussions">GitHub Discussions</a> in the grails GitHub org to solicit feedback on a number of topics.
The goal of this was to help design a path forward for the Grails framework. One of the first priorities was to define
the scope for a meaningful and valuable Grails 7. This effort required significant contributions from a combination of
passionate community members and organizations who care about being involved in the future of the technology. We are
pleased with the progress the Steering Committee has made so far as efforts continue to be made towards the Grails
framework 7 MVP.</p>
<p>When the committee was initially put together, we did not reach out to individuals, but instead let members of the
community volunteer their time and efforts as they felt they could help. We want to continue to create awareness and
encourage community participation. Please join us <a href="https://slack.grails.org/">here</a> in our Grails Community Slack to get involved. Additionally,
there is a 60-minute online meeting each Thursday at 10:00am US Central during which the team will be discussing
priorities for the technology and helping to manage governance of the Framework.</p>
<p>We want to thank you in advance for your continued support of the Grails framework and our amazing community.</p>]]></description><author>James Fredley</author><guid>2024-10-01-grails-community-contributions</guid><pubDate>Tue, 01 Oct 2024 00:00:00 GMT</pubDate></item><item><title>Grails 7 MVP</title><link>https://grails.apache.org/blog/2024-06-25-grails-seven-mvp.html</link><description><![CDATA[</p>
<p><strong>MVP (Minimum Viable Product) for Grails 7.</strong></p>
<p>The Grails Community Steering Committee has begun discussions on the MVP (Minimum Viable Product)
for Grails 7. To assist in these discussions, the Grails Foundation has enabled
<a href="https://github.com/orgs/grails/discussions">GitHub Discussions</a> on the grails-core project. We now
need the community’s feedback!</p>
<p>Please vote on the various posted polls and respond to the existing discussions to help with decisions
on priorities for the Grails 7 MVP.</p>
<p>Thank you for all of your input!</p>]]></description><author>Jeff Brown</author><guid>2024-06-25-grails-seven-mvp</guid><pubDate>Tue, 25 Jun 2024 00:00:00 GMT</pubDate></item><item><title>Grails Future Planning</title><link>https://grails.apache.org/blog/2024-06-07-grails-future.html</link><description><![CDATA[</p>
<p><strong>Grails Community Steering Committee is working on plans for the future of the Grails framework.</strong></p>
<p>The Grails Foundation would like to follow up on the
<a href="https://objectcomputing.com/resources/news/2024/05/10/open-letter-our-open-source-communities">Open Letter To Our
Community</a> that was recently published by Object Computing, Inc. (OCI).<br />
We have assembled a Grails Community Steering Committee with the goal of
helping define the path forward for the Grails framework. One of the first
priorities of the group is to define the scope for a meaningful and valuable
Grails 7, which can be created and supported responsibly. Achieving that will
require contributions from a combination of passionate community members and
organizations who care about being involved in the future of the technology.</p>
<p>Our experience has shown that increased transparency regarding challenges and
opportunities is crucial for the Framework's continued development. We're
committed to improving communication in this area.</p>
<p>The Grails Steering Committee’s current focus is on three key goals:</p>
<ol>
<li>Defining an MVP (Minimum Viable Product) for Grails 7.</li>
<li>Outlining Community Contribution Opportunities: We'll clearly define how individuals and organizations can contribute to the MVP's development.</li>
<li>Highlighting Contribution Methods: We recognize that contributions come in various forms. Some organizations may prefer dedicating engineering resources, while others might choose to provide financial support for a core development team.</li>
</ol>
<p>Previously, these contribution avenues have existed but lacked clear
communication. We're committed to making them more visible and accessible.</p>
<p>The work we are doing right now will enable our community to have a greater
impact on the future of the Grails framework. The feedback we get in the coming
weeks will be enlightening. We must understand what is important from the
community’s perspective, and for us to envision the possible paths to accomplish
desired outcomes. OCI is committed to stewarding the framework forward including
helping the technology and the community find a public place for the community to
rally around the technology.</p>
<p>Creating and maintaining these free and open solutions is a significant commitment
and it will take a positively energized community to help us carry things forward.
Every single message we have received and every single conversation we have been
involved in in recent weeks has been helpful, appreciated, and respectful. This
community is remarkable and your input is sincerely appreciated.</p>
<p>We will continue to communicate more information here in the coming weeks. Always
feel welcome to reach out to us at <a href="mailto:dev@grails.apache.org">dev@grails.apache.org</a> if you have any questions,
concerns, or would like to engage in ways that you are currently not.  Together
we are all defining the way forward and your help is appreciated.</p>]]></description><author>Jeff Brown</author><guid>2024-06-07-grails-future</guid><pubDate>Fri, 07 Jun 2024 00:00:00 GMT</pubDate></item><item><title>CVE-2023-46131: Data Binding Denial of Service Vulnerability</title><link>https://grails.apache.org/blog/2023-12-20-cve-data-binding-dos.html</link><description><![CDATA[</p>
<p><strong>A vulnerability in grails-core data binding can leave your application open to a denial-of-service attack.</strong></p>
<h2>Overview</h2>
<p>The Grails® framework engineering team has confirmed a security vulnerability in the grails-databinding module, discovered by Wenbo Shen, Rui Chang, crane from Zhejiang University, and two other researchers from Antgroup FG Security Lab. This vulnerability is assigned the identifier <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-46131">CVE-2023-46131</a>.</p>
<p>An attacker can send a specially crafted request to a Grails framework application that will trigger internal server errors when the application attempts data binding. After the attack, these internal server errors will continue to be generated, even after the attacker has moved on and the application has received valid requests. The attack request may even crash the Java Virtual Machine (JVM). The server must be restarted to restore proper working operation.</p>
<h2>Impacted Applications</h2>
<p>Most Grails framework applications are susceptible, from Grails version 2.x and later.</p>
<h2>Protecting Your Applications</h2>
<p>The Grails Team recommends that all Grails framework applications upgrade to a patched version of the framework. Patches are available for Grails in these versions:</p>
<ul>
<li><a href="https://github.com/apache/grails-core/releases/tag/v6.1.0">6.1.0</a></li>
<li><a href="https://github.com/apache/grails-core/releases/tag/v5.3.6">5.3.6</a></li>
<li><a href="https://github.com/apache/grails-core/releases/tag/v4.1.4">4.1.4</a></li>
<li><a href="https://github.com/apache/grails-core/releases/tag/v3.3.18">3.3.18</a></li>
</ul>
<p>(<strong>2024 Jan 29 Update:</strong> An earlier revision of this blog post recommended release versions that patched the vulnerability but unfortunately introduced an unrelated defect.
This defect has been fixed, and the recommended versions above reflect the patched, fixed releases.)</p>
<p>The best way to protect your application is to upgrade to a patched release.</p>
<p>No workaround is possible for this vulnerability except to avoid data binding altogether.</p>
<h2>Support</h2>
<p>The Grails Foundation and the Grails development team take application security very seriously. We continue to research and monitor this vulnerability and will post updates with new information as it is discovered.</p>
<p>If you have questions about this vulnerability or need assistance with upgrades or workarounds, please join the <a href="https://github.com/apache/grails-core/issues/13302">discussion on GitHub</a> or contact us at <a href="mailto:security@apache.org?subject=CVE-2023-46131">security@apache.org</a>.</p>]]></description><author>Matthew Moss</author><guid>2023-12-20-cve-data-binding-dos</guid><pubDate>Wed, 20 Dec 2023 00:00:00 GMT</pubDate></item><item><title>Introducing Grails Framework 6.1.0 Release</title><link>https://grails.apache.org/blog/2023-11-14-introducing-grails-6_1_0.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited to announce the release of Grails Framework 6.1.0! This release comes with a host of changes, bug-fixes, and improvements that will further enhance your experience with the Grails framework . Grails continues to be a powerful and efficient framework for building web applications in Groovy, and this latest version takes it to the next level. Let's dive into what's new in Grails 6.1.0.</p>
<h2>What's Changed</h2>
<p>In this release, we have made several changes to improve the framework's performance and maintainability. Some of the notable changes include:</p>
<ul>
<li>
<p><strong>Update to SnakeYaml 2.2</strong>: This update fixes the <a href="https://www.cve.org/CVERecord?id=CVE-2022-1471">CVE-2022-1471</a> reported in December of last year. This unsafe deserialization problem could easily lead to arbitrary code execution under the right circumstances. For more details on this vulnerability, you can read about it on <a href="https://snyk.io/blog/snakeyaml-unsafe-deserialization-vulnerability/">Snyk's blog</a>.</p>
</li>
<li>
<p><strong>Decoupling the Sitemesh Plugin</strong>: We have introduced significant changes to decouple the Sitemesh plugin for more flexibility. Here are the details:</p>
<ol>
<li>
<p>Created a new <code>org.grails.plugins:sitemesh2</code> and moved Sitemesh specific tag libraries that require the Sitemesh2 dependency into a separate Sitemesh2 specific plugin. This plugin can now be optionally used, providing more flexibility in choosing Sitemesh versions.</p>
</li>
<li>
<p>Introducing the <a href="https://github.com/codeconsole/grails-sitemesh3">Sitemesh3 Grails Plugin</a>, a new plugin that can be independently used with Grails 6. This plugin offers compatibility with the latest Sitemesh version, allowing developers to leverage the benefits of Sitemesh3 in their Grails applications.</p>
</li>
<li>
<p>To migrate from Sitemesh 2 to Sitemesh 3, not only completely decouples Sitemesh from GSP, but it also introduces a powerful new feature that GSP has been lacking: Decorator Chaining. With SiteMesh 3, you can apply multiple decorators to a view. For instance, something like this:</p>
<pre><code class="language-html">&lt;meta name=&quot;layout&quot; content=&quot;my-decorator,my-other-decorator&quot; /&gt;
</code></pre>
<p>This enhancement provides more flexibility in structuring views and layouts, making it easier to create complex and dynamic page layouts.</p>
</li>
<li>
<p>Going Further (JDK 17) - Jakarta compatible SiteMesh 3.2 is already available. Sitemesh 3 supports JDK 17, making it an easier transition to future Grails releases, such as Grails 7.0.</p>
</li>
<li>
<p>To learn more about updates around Grails and Sitemesh, please <a href="https://github.com/apache/grails-core/issues/13058">review the discussion</a>. This discussion provides insights into the decisions and considerations made during the decoupling process.</p>
</li>
</ol>
<p>These changes aim to provide developers with more choices and the ability to use the Sitemesh version that best suits their application requirements.</p>
</li>
<li>
<p>Updated Micronaut Groovy to version 3.4.0 for better compatibility.</p>
</li>
<li>
<p>Escaped Javadoc special characters for improved documentation.</p>
</li>
<li>
<p>Update Spring Core to 5.3.30, and Spring Boot 2.7.16.</p>
</li>
<li>
<p>Updated various dependencies and plugins to their latest versions.</p>
</li>
</ul>
<p>These changes will not only make Grails more efficient but also ensure that it remains current and compatible with the latest technologies.</p>
<h2>Bug Fixes and Improvements</h2>
<p>Grails 6.1.0 also addresses several bug fixes and improvements, including:</p>
<ul>
<li>An update to GSP version 6.1.0.</li>
<li>An update to the grails-testing-support monorepo to version 3.1.0.</li>
</ul>
<p>These updates will enhance the stability and reliability of the framework.</p>
<h2>Dependency Upgrades</h2>
<p>Keeping up with the latest dependencies is crucial for the health of any framework. In this release, we have upgraded various dependencies to their latest versions, including but not limited to the following:</p>
<ul>
<li><code>commons-io:commons-io</code> to version 2.15.0.</li>
<li><code>org.jsoup:jsoup</code> to version 1.16.2.</li>
<li><code>org.grails:grails-datastore-gorm-hibernate5</code> to 8.0.1.</li>
<li><code>Micronaut</code> to version 3.10.2.</li>
<li><code>Gradle</code> to version 7.6.3.</li>
<li><code>Apache Tomcat</code> to 9.0.81.</li>
<li><code>JUnit Jupiter</code> to 5.10.0, and <code>JUnit Platform</code> to 1.10.0.</li>
<li>And many more.</li>
</ul>
<p>These upgrades ensure that Grails 6.1.0 remains compatible with the latest libraries and tools, providing developers with a robust and reliable environment. We recommend checking out the <a href="https://github.com/apache/grails-core/releases/tag/v6.1.0">GitHub release page</a> for more information.</p>
<h2>Installing Grails 6.1.0</h2>
<p>You can get started with Grails 6.1.0 today by visiting our <a href="https://start.grails.org/">official website</a>. Alternatively, you can quickly install Grails 6.1.0 using the <a href="https://sdkman.io/">SDKMan</a>.</p>
<ol>
<li>
<p>If you don't have SDKMan installed, follow the instructions at <a href="https://sdkman.io/install/">SDKMan Installation Guide</a> to set it up.</p>
</li>
<li>
<p>Once SDKMan is installed, open your terminal and run the following command to install Grails 6.1.0:</p>
<pre><code class="language-shell">sdk install grails 6.1.0
</code></pre>
</li>
<li>
<p>You're all set! To verify the installation, run:</p>
<pre><code class="language-shell">grails --version
</code></pre>
</li>
</ol>
<h2>Upgrading Your Existing Applications to Grails 6.1.0</h2>
<p>If you already have a Grails application and want to upgrade to the latest version, follow these steps:</p>
<ol>
<li>
<p>Open the project in your favorite IDE (preferably JetBrains' IntelliJ IDEA).</p>
</li>
<li>
<p>Update your application's <code>gradle.propreties</code> file to specify Grails 6.1.0 as the desired version.</p>
<pre><code class="language-properties">grailsVersion=6.1.0
grailsGradlePluginVersion=6.1.0
</code></pre>
</li>
<li>
<p>Make any necessary adjustments to your application code, configuration, and dependencies to ensure compatibility with the new version.</p>
</li>
</ol>
<p>Normally, Grails Core dependencies are automatically updated using the Grails Bill of Materials (BOM). However, if you have specific versions defined in your build configuration, you may need to manually update them to align with Grails 6.1.0.</p>
<p>By following these steps, you can smoothly transition your existing Grails application to the exciting Grails 6.1.0.</p>
<h3>Exploring Alternative Approaches</h3>
<p>If manual dependency updates seem daunting or you want a more streamlined approach, consider the following alternatives:</p>
<h4>1. Use Grails Forge Website</h4>
<p>Visit <a href="https://start.grails.org">https://start.grails.org</a> and generate a new Grails application with Grails 6.1.0. Compare the versions in the newly generated application with your existing one to identify any discrepancies. This can serve as a reference point for your update.</p>
<h4>2. Automated Dependency Update Bots</h4>
<p>Configure automated dependency update bots like <a href="https://docs.renovatebot.com/">Renovate</a> or <a href="https://dependabot.com/">Dependabot</a> with your source control platform (e.g., GitHub). These bots can automatically detect and update outdated dependencies in your project, including Grails dependencies, saving you time and effort in manual updates.</p>
<p>With these steps and alternative approaches, you should be well on your way to enjoying the exciting features and improvements in Grails 6.1.0. Happy coding!</p>
<h2>Contributors</h2>
<p>We would like to extend our heartfelt thanks to all the contributors who made Grails 6.1.0 possible. Special thanks to:</p>
<ul>
<li><a href="https://github.com/codeconsole">Scott Murphy</a></li>
<li><a href="https://github.com/guillermocalvo">Guillermo Calvo</a></li>
<li><a href="https://github.com/puneetbehl">Puneet Behl</a></li>
<li><a href="https://github.com/weiqigao">Weiqi Gao</a></li>
<li><a href="https://github.com/mattmoss">Matthew Moss</a></li>
<li><a href="https://github.com/Emrichardsone">Emma Richardson</a></li>
<li><a href="https://github.com/matrei">Mattias Reichel</a></li>
</ul>
<p>Their dedication and hard work have significantly contributed to the success of Grails 6.1.0.</p>
<p>With all these exciting changes and improvements, Grails 6.1.0 is set to offer an even better experience for developers working on web applications. Whether you're an experienced Grails developer or just getting started, this release has something for everyone.</p>
<p>Join the <a href="https://grails.slack.com">Grails Slack community</a>, share your feedback, and contribute to making Grails framework even better in the future. Happy coding!</p>]]></description><author>Puneet Behl</author><guid>2023-11-14-introducing-grails-6_1_0</guid><pubDate>Tue, 14 Nov 2023 00:00:00 GMT</pubDate></item><item><title>Introducing the New Grails Plugin Portal - A Static Marvel!</title><link>https://grails.apache.org/blog/2023-09-11-the-new-grails-plugin-portal.html</link><description><![CDATA[</p>
<p>Hey there, Grails enthusiasts! Are you ready for some exciting news? We're thrilled to introduce the revamped Grails Plugin Portal, and let us tell you, it's a game-changer! This dynamic portal is now completely static and hosted on GitHub, offering you a seamless and efficient experience in exploring Grails plugins.</p>
<p><img src="/blog/2023-09-11-new-grails-plugin-portal.png" alt="Grails Plugin Portal!" /></p>
<h2>A Glimpse of the Future: Grails Plugin Portal Redesigned</h2>
<p>Our dedicated team has been hard at work, and we're excited to unveil the Grails Plugin Portal 2.0, now hosted at <a href="https://github.com/apache/grails-static-website">https://github.com/apache/grails-static-website</a>. What's our aim? To make your Grails plugin journey smoother and more accessible than ever before!</p>
<h2>Key Features of the New Grails Plugin Portal</h2>
<h3>Quick and Easy Search Functionality</h3>
<p>We get it, time is precious when you're deep into Grails projects. That's why our new portal boasts a lightning-fast search feature. Type in your keywords, hit enter, and voilà! Your desired plugins are right there at your fingertips.</p>
<h3>Paginated List of All Plugins</h3>
<p>With the Grails ecosystem booming, there's no shortage of plugins to explore. To help you navigate this sea of possibilities, we've introduced a paginated list of all available plugins. Explore them at your pace, knowing that detailed plugin info is just a click away.</p>
<h3>Top-Rated Plugins</h3>
<p>Wondering which plugins are the cream of the crop? Wonder no more! Our top-rated plugins section showcases gems that have been tried, tested, and adored by fellow Grails developers. It's your shortcut to finding the best tools for your projects.</p>
<h3>Latest Release Plugins</h3>
<p>Stay ahead in the world of Grails development with our &quot;Latest Release&quot; section. We keep it up to date to showcase the newest additions to the Grails plugin ecosystem. Be the first to try out fresh features and improvements as they roll in.</p>
<h3>Tag Clouds for Owners and Tags</h3>
<p>To make your plugin search even more intuitive, we've introduced tag clouds for both plugin owners and tags. Click on a tag to find all relevant plugins or explore the work of your favorite authors. These tag clouds are your secret weapon for effortless plugin discovery!</p>
<h2>Limitations of the Previous Plugin Portal</h2>
<p>Before we dive further into the awesomeness of the new portal, let's address the shortcomings of the previous version. It had some issues that weren't exactly developer-friendly:</p>
<ol>
<li>
<p><strong>Frequent Downtime</strong>: The old portal was notorious for going offline quite often, causing disruptions and frustration for developers.</p>
</li>
<li>
<p><strong>High Resource Utilization</strong>: It was a resource-hungry beast, slowing down performance due to its dynamic architecture.</p>
</li>
<li>
<p><strong>Slow Performance</strong>: Slow loading times and delays were common complaints. The dynamic setup struggled with the increasing plugin data, resulting in sluggishness.</p>
</li>
</ol>
<h2>All Plugins in One Place</h2>
<p>Did you know that all the plugins on the Grails Plugin Portal are sourced from <a href="https://github.com/apache/grails-plugins-metadata/tree/grails-plugins.json">https://github.com/apache/grails-plugins-metadata/tree/grails-plugins.json</a>? We've streamlined the process to ensure you have access to the most up-to-date plugins directly from the source.</p>
<h2>How to Include or Update Your Grails Plugin</h2>
<p>Excited to get your Grails plugin into the spotlight on our portal? Here's how you can include or update your Grails plugin:</p>
<ol>
<li>
<p><strong>Fork the Repository</strong>: Start by forking the <a href="https://github.com/apache/grails-plugins-metadata">Grails Plugin Metadata Repository</a>.</p>
</li>
<li>
<p><strong>Edit the JSON File</strong>: Navigate to the <code>grails-plugins.json</code> file in your forked repository. This file contains the plugin metadata.</p>
</li>
<li>
<p><strong>Add Your Plugin</strong>: To include your plugin, simply add its metadata to the JSON file. Make sure to follow the established format.</p>
</li>
<li>
<p><strong>Submit a Pull Request</strong>: Once you've added or updated your plugin details, submit a pull request to the original <a href="https://github.com/apache/grails-plugins-metadata">Grails Plugin Metadata Repository</a>. Our team will review it and, upon approval, your plugin will be part of the portal!</p>
</li>
</ol>
<h2>Get Involved and Contribute</h2>
<p>But here's the exciting part: the Grails Plugin Portal is not just a resource; it's a community effort! We're eager to hear your thoughts and welcome your contributions. Have a Grails plugin you'd like to share, or ideas for portal enhancements? Join us on <a href="https://github.com/apache/grails-static-website">GitHub</a>, and together, we'll make Grails development a breeze!</p>
<h2>Embrace the Future of Grails Plugin Discovery</h2>
<p>The new Grails Plugin Portal is your gateway to a brighter future in Grails development. With its static structure, lightning-fast search, and curated lists of top-rated and latest release plugins, it's your one-stop-shop for all things Grails. Come on in, explore, discover, and become an active part of the Grails community. Let's build amazing Grails applications together with this reimagined portal!</p>
<p>Ready to get started? Visit the <a href="/plugins.html">Grails Plugin Portal</a> today!</p>]]></description><author>Puneet Behl</author><guid>2023-09-11-the-new-grails-plugin-portal</guid><pubDate>Mon, 11 Sep 2023 00:00:00 GMT</pubDate></item><item><title>Introducing Grails Spring Security Core Plugin 6.0.0 - Elevated Security, Grails 6 Compatibility, Enhanced Commands, and Effortless Documentation</title><link>https://grails.apache.org/blog/2023-08-25-introducing-grails-spring-security-core-6.html</link><description><![CDATA[</p>
<p><strong>Exciting News from the Grails Foundation: Unveiling Grails Spring Security Core Plugin 6.0.0</strong></p>
<p>Greetings, fellow developers! Prepare to be amazed by the latest release – Grails Spring Security Core Plugin 6.0.0! This isn't just an upgrade in security; it's a journey towards greater heights for your applications. Packed with updates and improvements, this release doesn't just enhance security; it also streamlines your development experience. Let's explore the exciting changes this release brings.</p>
<h2>Seamless Grails 6 Compatibility with Upgraded Commands</h2>
<p>We are intentional about making the transition to Grails 6 seamless. Grails Spring Security Core Plugin 6.0.0 now boasts upgraded commands fully compatible with Grails 6. This is crucial because the old scripts you might have been using would have caused compatibility issues with Grails 6. But worry not! We've revamped these commands, ensuring a smooth transition and allowing you to continue using them seamlessly.</p>
<p>Do you remember running a script like <code>s2-quickstart</code> using the command:</p>
<pre><code class="language-bash">grails s2-quickstart com.yourapp User Role
</code></pre>
<p>This command was used to create user and role classes (and optionally a requestmap class) in your specified package.</p>
<p>Fast forward to Grails 6, things have evolved. Now, you can trigger these commands using Gradle tasks, like so:</p>
<pre><code class="language-bash">./gradlew runCommand &quot;-Pargs=s2-quickstart com.yourapp User Role&quot;
</code></pre>
<p>The <code>runCommand</code> Gradle task allows you to execute various Grails ApplicationCommands, just like the good old <code>s2-quickstart</code>. The difference? It's sleeker, perfectly aligned with Grails 6, and propels your app into modern development.</p>
<h2>Spring Security Leveled Up to 5.8.6</h2>
<p>Security is paramount, and that's why we've given the underlying Spring Security framework a power boost in Grails Spring Security Core Plugin. It's now fueled by version 5.8.6 of Spring Security. This ensures that your application benefits from the latest security enhancements and bug fixes from the Spring Security team. By staying up to date with Spring Security versions, your app is fortified against emerging threats and vulnerabilities.</p>
<h2>Navigating Docs Made Effortless</h2>
<p>We've heard your feedback – navigating documentation shouldn't be a chore. That's why we've spruced up the Internal Docs task. This magic generates documentation that empowers you to grasp the plugin's features and their effective usage. But there's more – we've added a slick select drop-down feature. This nifty addition enables you to switch effortlessly between documentation for different releases. Whether diving into the latest version or revisiting an older one, finding the info you need is now seamless.</p>
<p><img src="/blog/2023-08-25-thenewselectoption.png" alt="Documentation Select Option" /></p>
<h2>All Aboard the Grails 6 Train</h2>
<p>Web development is a swiftly moving train, and the Grails Spring Security Core Plugin is on board. We've given it a makeover for seamless integration with Grails 6. This empowers you to tap into the coolest Grails framework features while enjoying the robust security provided by the plugin.</p>
<h2>Getting Cozy with Dependency Updates</h2>
<p>Dependencies are the foundation of your app, and keeping them up-to-date is crucial. In Grails Spring Security Core Plugin 6.0.0, we've rolled out updates to key dependencies:</p>
<ul>
<li><strong>Spring Security 5.8.6:</strong> Latest Spring Security version for cutting-edge security features.</li>
<li><strong>Hibernate 5:</strong> Upgraded to version 8, embracing enhancements in Hibernate technology.</li>
<li><strong>Spring Security Core 5.3.0:</strong> Now at version 5.3.0, aligning with latest developments in the Spring Security ecosystem.</li>
<li><strong>Grails Gradle Plugin 6:</strong> Elevating your build and development experience with Grails Gradle Plugin v6.</li>
<li><strong>Webdriver Binaries 3.2:</strong> For web testing enthusiasts, Webdriver Binaries plugin updated to v3.2, enhancing testing capabilities.</li>
<li><strong>Spring Dependency Management 1.1.3:</strong> Details matter – Spring Dependency Management plugin upgraded to v1.1.3, simplifying project dependency management.</li>
</ul>
<h2>Embrace the Future</h2>
<p>Grails Spring Security Core Plugin 6.0.0 release goes beyond security enhancement; it's a stride towards improved compatibility and integration. The transition from Grails scripts to Grails ApplicationCommand underscores the plugin's commitment to delivering a unified and consistent experience in the realm of Grails 6. As you embark on secure, robust web app development, the upgraded plugin is your ally, aligning projects with the evolving landscape of modern web development. Upgrade today for a new era of security and compatibility in your Grails applications!</p>
<h2>How to Upgrade</h2>
<p>To use the</p>
<p>latest Grails Spring Security Core plugin, simply edit your <code>build.gradle</code> file and change the dependency from version 5.3.0 to version 6.0.0:</p>
<p>From:</p>
<pre><code class="language-groovy">implementation 'org.grails.plugins:spring-security-core:5.3.0'
</code></pre>
<p>To:</p>
<pre><code class="language-groovy">implementation 'org.grails.plugins:spring-security-core:6.0.0'
</code></pre>
<p>Updating your project's dependencies is all it takes. Your application is now upgraded to Grails Spring Security Core Plugin 6.0.0, ready to take advantage of enhanced security, smoother documentation navigation, and Grails 6 compatibility.</p>
<h2>Glimpse into the Future</h2>
<p>But wait, there's more! As you enjoy these enhancements in Grails Spring Security Core Plugin 6.0.0, we want to give you a sneak peek into the exciting future. Our team is actively working on upgrading the Grails Spring Security REST plugin, bringing you even more comprehensive security features and seamless integration.</p>
<p>And that's not all. Our vision extends further down the road. We're planning to support the next major release, Spring Security 6, with a focus on addressing bug fixes and introducing further improvements. This dedication to staying ahead of the curve ensures that your applications will continue to be fortified with the latest security advancements and enhancements.</p>
<p>So, as you relish the benefits of Grails Spring Security Core Plugin 6.0.0, rest assured that the journey ahead is just as thrilling. We're committed to providing you with the tools you need to build exceptional, secure, and future-proof web applications. Stay tuned for more updates as we continue this innovative journey together!</p>]]></description><author>Puneet Behl</author><guid>2023-08-25-introducing-grails-spring-security-core-6</guid><pubDate>Fri, 25 Aug 2023 00:00:00 GMT</pubDate></item><item><title>Introducing the New Grails Forge - A Lightning-Fast, Micronaut-Inspired CLI for Grails Application Generation</title><link>https://grails.apache.org/blog/2023-08-03-introducing-new-grails-forge.html</link><description><![CDATA[</p>
<p>Dear Grails Developers,</p>
<p>The Grails Foundation™ is thrilled to unveil the next level of Grails application generation - the New Grails Forge! Building upon the foundation of the previous Grails Forge, we have introduced a brand new implementation of the Grails Forge website, and the Grails Command Line Interface (CLI).</p>
<h2>Multiple Application Types for Your Needs</h2>
<p>The New Grails Forge also introduces Grails Profiles through application-types, supporting various application types to meet your specific needs. Currently, we offer support for Web, REST API, Web Plugin, and Plugin. Stay tuned as we plan to add support for additional application types, including REST API Plugin, React, and Angular.</p>
<h2>The New Grails Forge CLI: Speed, Flexibility, and Efficiency</h2>
<p>Before we delve into the Grails Forge UI, let's first highlight the power of the New Grails Forge CLI. Inspired by the efficiency and flexibility of the Micronaut framework's CLI, the New Grails Forge CLI offers a lightning-fast and easy-to-maintain approach to creating and managing Grails projects.</p>
<p>With the New Grails Forge CLI, you can create Grails applications offline or in areas with limited connectivity, making it a perfect choice for developers on the go. Powered by the Picocli library, the CLI delivers exceptional performance and robustness, ensuring a smooth and seamless command-line experience.</p>
<h2>Getting Started with the Grails Forge UI</h2>
<p>Getting started with the Grails Forge UI is as simple as 1, 2, 3:</p>
<ol>
<li>
<p>Visit the Website: Head over to the official Grails Forge UI website at <a href="https://start.grails.org">https://start.grails.org</a></p>
</li>
<li>
<p>Explore and Customize: Take a tour of the website and explore its features. Customize your project settings to match your development requirements.</p>
</li>
<li>
<p>Generate Your Project: Once you're satisfied with your choices, hit the &quot;Generate Project&quot; button. Your Grails project will be created instantly, and you can download the project files to get started immediately.</p>
</li>
</ol>
<h2>Global CLI Compatibility: The Best of Both Worlds</h2>
<p>While many commands transition smoothly to Gradle tasks, we understand that some actions require the familiarity of the globally-installed Grails CLI. Fear not, as the New Grails Forge thoughtfully addresses this concern. If you have the Grails CLI installed on your system, you can still use it within your project folder for commands involving file manipulations. This harmonious integration ensures a seamless transition for existing projects while taking advantage of the new features of the New Grails Forge.</p>
<h2>Extending Functionality: A World of Possibilities</h2>
<p>The New Grails Forge empowers you to extend the functionality of your projects effortlessly. Although some plugin-specific commands may require slight adjustments during the migration, we've got you covered with our comprehensive Grails Documentation, providing valuable insights into creating custom commands. This newfound capability allows you to tailor commands to your unique needs, automate tasks, integrate with third-party tools, and streamline repetitive processes.</p>
<h2>Lightning-Fast and Offline Ready</h2>
<p>With the new CLI, you can create Grails applications even offline or in areas with limited connectivity, thanks to its lightning-fast performance. Say goodbye to frustrating delays and embrace a seamless and efficient application generation process.</p>
<h2>Powered by Picocli and Rocker Template Engine</h2>
<p>To achieve such speed and efficiency, we harnessed the power of the Picocli library to build a robust and flexible command-line application. This integration ensures that you have a user-friendly and highly maintainable CLI at your fingertips.</p>
<p>Moreover, we adopted the Rocker template engine, which produces statically typed plain Java objects, guaranteeing precision and performance in every command you execute.</p>
<h2>Saying Farewell to the Grails CLI Wrapper</h2>
<p>With Grails 6, we're embracing a new era where the Grails CLI wrapper will no longer be included in new projects. Instead, we encourage you to leverage the Gradle build system for greater flexibility and a more cohesive development environment. Common commands, such as &quot;./grailsw run-app,&quot; can now be executed directly using the straightforward &quot;./gradlew bootRun.&quot;</p>
<h2>Enhanced Plugin Compatibility with Grails ApplicationCommand</h2>
<p>While many commands transition seamlessly to Gradle tasks, we acknowledge that certain commands, supported via plugins, may require special attention during migration. To address this, we introduced Grails ApplicationCommand tasks, enabling compatibility with plugin-specific commands. Refer to our comprehensive Grails Documentation for valuable insights on creating custom commands and making the most of this new capability.</p>
<h2>Turbocharge Your Grails Development: Swift Installation of the New Grails Forge</h2>
<p>Installing the New Grails Forge is a breeze! Follow these step-by-step instructions based on your preferred method:</p>
<h3>Option 1: Installing with SDKMan</h3>
<p>The easiest way to install the New Grails CLI is with SDKMan. Simply run the following command in your terminal:</p>
<pre><code class="language-shell">sdk install grails 6.0.0
</code></pre>
<h3>Option 2: Download &amp; Install Binary</h3>
<ol>
<li>
<p>Download the latest binary from the following link, based on your Operating System: <a href="https://github.com/apache/grails-forge/releases">New Grails CLI Binary</a></p>
</li>
<li>
<p>Extract the downloaded zip file to an appropriate directory on your system.</p>
</li>
<li>
<p>Create an environment variable named &quot;GRAILS_HOME&quot; and set its value to the installation directory, for example:</p>
<ul>
<li>On Windows: <code>set GRAILS_HOME=c:/grails</code></li>
<li>On macOS/Linux: <code>export GRAILS_HOME=/usr/local/grails</code></li>
</ul>
</li>
<li>
<p>Update the PATH environment variable to include the Grails binary directory. For example:</p>
<ul>
<li>On Windows: <code>set PATH=%PATH%;%GRAILS_HOME%\bin</code></li>
<li>On macOS/Linux: <code>export PATH=$PATH:$GRAILS_HOME/bin</code></li>
</ul>
</li>
</ol>
<h3>Option 3: Use SDKMan to Build &amp; Install From Source</h3>
<ol>
<li>Clone the repository with the following command:</li>
</ol>
<pre><code class="language-shell">git clone https://github.com/apache/grails-forge.git
</code></pre>
<ol start="2">
<li>Build the distribution using the following command:</li>
</ol>
<pre><code class="language-shell">cd grails-forge
./gradlew :grails-cli:assembleDist
</code></pre>
<ol start="3">
<li>
<p>Copy and extract the archive from <code>grails-forge/grails-cli/build/distributions/grails-cli.*.zip</code> to your user home directory.</p>
</li>
<li>
<p>Use SDKMan to install the development version using the following commands:</p>
</li>
</ol>
<pre><code class="language-shell">sdk install grails dev ~/grails-cli/
sdk use grails dev
</code></pre>
<h2>Explore the Source Code</h2>
<p>Curious about the inner workings of the New Grails Forge? Delve into the source code on GitHub: <a href="https://github.com/apache/grails-forge">Grails Forge Core Source Code</a></p>
<h2>Preview Feature: Explore Your Grails Application Source Files</h2>
<p>We are excited to introduce the Preview Feature on <a href="https://start.grails.org">https://start.grails.org</a>! This powerful addition allows you to take a sneak peek into your Grails application source files before actually generating the project. With the Preview Feature, you can explore the selected options and features to see exactly what will be generated, giving you full control and confidence in your project setup.</p>
<p>How does it work? It's simple:</p>
<ol>
<li>
<p>Customize Your Options: Start by selecting the application type and setting your project preferences, just like you would with the regular project generation process.</p>
</li>
<li>
<p>Click &quot;Preview&quot;: Instead of hitting the &quot;Generate Project&quot; button right away, click on &quot;Preview&quot; to see the magic happen.</p>
</li>
<li>
<p>Visualize Your Project: The Preview Feature will instantly generate a visualization of your Grails application source files, showcasing the directory structure and all the code files based on your chosen options.</p>
</li>
<li>
<p>Navigate and Inspect: Dive into the source files, navigate through the directories, and inspect the actual code snippets that will be included in your project.</p>
</li>
<li>
<p>Refine and Adjust: If you spot anything you'd like to modify, simply go back, adjust your options, and preview again until you're fully satisfied with your project setup.</p>
</li>
</ol>
<p>This Preview Feature is a game-changer, as it allows you to make informed decisions and tailor your Grails application precisely to your needs. Gone are the days of uncertainty - with the Preview Feature, you can confidently create and manage your Grails projects with ease.</p>
<p>So, what are you waiting for? Try out the Preview Feature on <a href="https://start.grails.org">https://start.grails.org</a> and unleash the full potential of the New Grails Forge CLI and UI.</p>
<h2>Ready to Forge Ahead</h2>
<p>With the New Grails Forge installed on your system, you're all set to embark on a new era of Grails application generation. Explore the lightning-fast performance, enhanced flexibility, and seamless compatibility with Gradle and plugins. Together, let's redefine Grails development and build remarkable applications for a rapidly evolving world.</p>
<h2>Introducing the Grails Forge UI: A User-Friendly Gateway to Project Generation</h2>
<p>Now, let's move on to the star of the show - the React-based Grails Forge UI! This cutting-edge website serves as an interactive and user-friendly alternative to project generation, eliminating the need to install the CLI locally.</p>
<h2>Seamless Replacement for the Old Grails Forge Website</h2>
<p>With the Grails Forge UI, we are embracing the future of project creation and bidding farewell to the old Grails Forge website <a href="https://start.grails.org">https://start.grails.org</a>. This exciting transition ensures a more advanced and efficient platform for generating Grails projects.</p>
<h2>A Leap Towards the Future</h2>
<p>The New Grails Forge marks a significant leap towards the future of Grails application generation. With its Micronaut-inspired design, lightning-fast performance, and versatile application-types, you can confidently embark on your development journey, knowing you have a powerful tool at your disposal.</p>
<h2>Join the New Grails Forge Revolution</h2>
<p>We invite you to embrace the New Grails Forge and be part of this revolutionary movement in Grails development. As we continue to refine and improve, your feedback and insights are invaluable. Together, let's redefine Grails application generation and shape a future of remarkable applications powered by the New Grails Forge.</p>
<p>Stay connected with us on the official Grails website and community forums for the latest updates, resources, and discussions on harnessing the full potential of this cutting-edge CLI. Let's embark on this journey together, unlocking the limitless possibilities of the New Grails Forge.</p>
<p>Happy coding!</p>
<p>The Grails Team</p>]]></description><author>Puneet Behl</author><guid>2023-08-03-introducing-new-grails-forge</guid><pubDate>Thu, 03 Aug 2023 00:00:00 GMT</pubDate></item><item><title>Introducing Grails 6 - Embracing Modern Java, Java 11, and the Latest Spring and Spring Boot Updates</title><link>https://grails.apache.org/blog/2023-07-25-introducing-grails-6.html</link><description><![CDATA[</p>
<p>The Grails Foundation™ is thrilled to unveil Grails 6, a major release that propels the Framework into an exciting new era of web development. This significant update brings a host of advancements, including embracing modern Java, upgrading to Java 11, a new Grails Forge, and incorporating the latest updates of <a href="https://spring.io/blog/2023/07/19/spring-framework-5-3-28-released">Spring 5.3.28</a> and <a href="https://spring.io/blog/2023/07/19/spring-boot-2-7-12-available-now">Spring Boot 2.7.12</a>.</p>
<h2>Embracing Modern Java and Java 11:</h2>
<p>Grails 6 sets a new standard by updating its minimum Java version to Java 11. This empowers developers with the latest language features, performance improvements, and enhanced security offered by Java 11.</p>
<h2>Why Java 11 for Now?</h2>
<p>The decision to update to Java 11 in Grails 6 was driven by several factors, including Java 11's LTS status, stability, and widespread adoption in the Java ecosystem. Java 11 offers a stable and well-supported environment for Grails applications, aligning with the needs of enterprise users who prioritize a reliable and mature Java version.</p>
<h2>The Path to Java 17:</h2>
<p>While Grails 6 does not include Java 17 support in this release, we are committed to providing an easy upgrade path for those planning to move to Java 17 in the future. The Grails team is actively planning to include Java 17 support in the next major release, ensuring developers can confidently embrace the latest Java advancements when the time comes.</p>
<h2>Latest Spring and Spring Boot Updates:</h2>
<p>Grails 6 incorporates the latest updates of Spring 5.3.28 and Spring Boot 2.7.12, bringing a wealth of new features and optimizations. These updates offer performance enhancements, Kotlin Coroutines support, WebSocket improvements, enhanced Actuator endpoints, Micrometer metrics enhancements, Jakarta Persistence integration, and additional configuration properties. By leveraging the power of the latest Spring versions, Grails 6 empowers developers with a cutting-edge development experience.</p>
<h2>Updates to Gradle 7.6:</h2>
<p>Grails 6 now provides support for the latest Gradle version, 7.6.1, offering developers a more efficient and robust build automation tool. Gradle 7.6.1 brings with it various improvements, enhanced performance, and additional features, further streamlining the development process and ensuring compatibility with the latest libraries and dependencies.</p>
<h2>Introducing the New Grails Forge:</h2>
<p><strong>Grails 6 not only embraces modern Java and the latest Spring and Spring Boot updates but also introduces the New Grails Forge UI, revolutionizing the web development experience for creating and managing Grails projects.</strong> With <a href="https://grails.github.io/grails-forge-ui/">the New Grails Forge UI</a>, developers can enjoy a modern and efficient user interface with simplified project creation, intuitive navigation, real-time feedback and validation, visual dependency management, enhanced plugin integration, project customization, built-in best practices, and responsive design. This intuitive UI streamlines the development process, making it easier for developers to set up new Grails projects and manage existing ones.</p>
<h2>Enhanced Integration of the Micronaut framework with Grails:</h2>
<p>The Grails framework has long provided integration with the Micronaut framework, fostering seamless collaboration between the two Frameworks. With Grails 6, we are proud to announce further improvements in this integration, enhancing the developer experience with each major release. Developers can now enjoy even better Micronaut integration, promoting code reuse and reducing redundancy between Grails and Micronaut components. For instance, developers can easily inject Micronaut beans into Grails services, controllers, and other components, gaining access to the Micronaut framework’s extensive ecosystem of features and functionalities.</p>
<p>Another example of the improved Micronaut integration is the ability to utilize the Framework’s declarative client, allowing Grails applications to consume RESTful APIs with minimal boilerplate code. This streamlined approach enhances development efficiency and promotes maintainable, efficient communication between microservices.</p>
<h2>Community and Documentation Support:</h2>
<p>The Grails community and documentation will play a pivotal role in assisting developers with the upgrade process. As Java 17 support becomes a reality in the next major release, the community will offer valuable insights, best practices, and support to ensure a seamless migration for Grails applications.</p>
<h2>Why Update to Grails 6?</h2>
<p>Upgrading to Grails 6 offers numerous benefits for developers and product managers alike:</p>
<ol>
<li>
<p><strong>Enhanced Developer Productivity:</strong> Grails 6 introduces developer-centric improvements, reducing boilerplate code and simplifying tasks to boost productivity.</p>
</li>
<li>
<p><strong>Future-Proofed Applications:</strong> Grails 6 supports Java 11, ensuring long-term stability and security updates for your applications.</p>
</li>
<li>
<p><strong>Performance Gains:</strong> Leveraging the latest Spring and Spring Boot updates, Grails 6 delivers improved application performance and optimized resource utilization.</p>
</li>
<li>
<p><strong>Enhanced Integration Possibilities:</strong> Grails 6 offers improved Micronaut integration, allowing seamless collaboration between Grails and Micronaut components, expanding your application's capabilities.</p>
</li>
<li>
<p><strong>Up-to-Date Tooling:</strong> With compatibility with Gradle 7.6.1, Grails 6 ensures efficient build automation and compatibility with the latest libraries and dependencies.</p>
</li>
<li>
<p><strong>Active Community Involvement:</strong> Engaging with the vibrant Grails community fosters collaborative learning and development, benefiting all Grails users.</p>
</li>
<li>
<p><strong>Seamless Migration Path:</strong> Grails 6's commitment to providing an easy upgrade path to Java 17 ensures embracing the latest Java advancements without disruption.</p>
</li>
</ol>
<p>Upgrade to Grails 6 today and seize the opportunity to elevate your applications and embark on a journey towards creating innovative and scalable web applications.</p>
<h2>Join the Grails Community: A Collective Journey</h2>
<p>At the heart of Grails lies its vibrant and passionate community of developers, whose contributions play a pivotal role in shaping the framework's evolution. Community contributions not only enhance the feature set of Grails but also address bugs, provide valuable feedback, and share best practices. The active involvement of the community fosters a collaborative environment where ideas are shared, discussed, and refined, ultimately benefiting all Grails users. With Grails 6, we encourage developers to actively engage with the community, contribute to the project, and together, we can push the boundaries of web development, making Grails an even more powerful and versatile framework.</p>
<p>In conclusion, Grails 6 represents a significant advancement in web development, providing developers with a powerful platform to build exceptional applications. Embrace Grails 6 and its advancements in Java, Spring, Spring Boot, and Micronaut integration to unlock the full potential of modern web development and embark on an exciting journey towards creating innovative and scalable applications.</p>
<p>To download and get started with Grails 6, visit the official Grails documentation: <a href="https://grails.apache.org/docs/latest/guide/gettingStarted.html#downloadingAndInstalling">https://grails.apache.org/docs/latest/guide/gettingStarted.html#downloadingAndInstalling</a>.</p>
<p><strong>Happy Coding with Grails 6!</strong></p>]]></description><author>Puneet Behl</author><guid>2023-07-25-introducing-grails-6</guid><pubDate>Tue, 25 Jul 2023 00:00:00 GMT</pubDate></item><item><title>Grails 6 RC1 - Release Announcement</title><link>https://grails.apache.org/blog/2023-05-27-grails-6-rc1.html</link><description><![CDATA[</p>
<p>The Grails Foundation is pleased to announce the release of Grails 6 RC1! We encourage you to update your applications to this release.</p>
<p>The <a href="https://github.com/apache/grails-core/releases/tag/v6.0.0-RC1">Grails 6.0.0-RC1 Release</a> provides an easy upgrade path to the developers, or project managers who are looking to upgrade to Java 17, and Spring 6.</p>
<h2>What’s New?</h2>
<ul>
<li>All major Grails libraries such as Grails Views, Grails GSP, Grails Testing Support, GORM core, GORM for Hibernate, MongoDB, and Neo4J are updated to Java 11 as baseline, Gradle 7.6.1.</li>
<li>A brand new and superfast <a href="https://github.com/apache/grails-forge">Command Line Interface</a> to generate Grails 6 applications and plugins. This new CLI provides the ability to generate applications completely offline.</li>
</ul>
<h2>Installation</h2>
<h3>Installing with SDKMan</h3>
<p>The easiest way to install the new Grails CLI is with SDKMan, run the following command:</p>
<pre><code>sdk install grails 6.0.0-RC1
</code></pre>
<h3>Download &amp; Install Binary</h3>
<ul>
<li>Download the latest binary from <a href="https://github.com/apache/grails-forge/releases/tag/v6.0.0-RC1">here</a> based on your Operating System</li>
<li>Extract to appropriate directory.</li>
<li>Create environment variable GRAILS_HOME which points to installation directory, eg: c:/grails</li>
<li>Update the PATH environment variable, append %GRAILS_HOME%\bin.</li>
</ul>
<h3>Use SDKMan To Build &amp; Install From Source</h3>
<ul>
<li>Clone the repository as follows:</li>
<li>git clone <a href="https://github.com/apache/grails-forge/tree/v6.0.0-RC1">github.com/apache/grails-forge/tree/v6.0.0-RC1</a></li>
<li>Build dist using the command <code>./gradlew :grails-cli:assembleDist</code>.</li>
<li>Copy &amp; Extract the archive from grails-forge/grails-cli/build/distributions/grails-cli.*.zip to the user home or any other directory of your preference.</li>
<li>Use <a href="https://sdkman.io/">SDKMan</a>, to install the dev version and use the path to the extracted directory. For example, the following command install the “dev” version and assumes you’ve extracted to the user’s home directory:</li>
</ul>
<pre><code>sdk install grails dev ~/grails-cli/
sdk use grails dev
</code></pre>
<h3>Why is my Grails 6 RC1 application not working?</h3>
<ul>
<li>
<p>Starting with the recent release of Grails 6, the CLI has moved to a separate project <a href="https://github.com/apache/grails-forge">github.com/apache/grails-forge</a>. The CLI shipped with Grails Core is deprecated and will be removed in the near term.</p>
</li>
<li>
<p>If you have used Grails binaries before, then you might be used to downloading it from the <a href="https://github.com/apache/grails-core/releases/v6.0.0-RC1">Grails Core release page</a>. However, this will no longer work and you should instead, download the OS specific native image from the <a href="https://github.com/apache/grails-forge/releases/v6.0.0-RC1">Grails Forge 6.0.0-RC1 Release Page</a>.</p>
</li>
</ul>
<h3>Why do some Grails commands don't work?</h3>
<p>The New CLI currently supports commands like <code>create-app</code>, <code>create-controller</code>, etc. You could also enter the Grails CLI interactive mode by entering <code>grails</code> and pressing the <code>return key</code> for auto-complete of supported commands.</p>
<p><img src="2023-05-27-img0.gif" alt="Example CLI Commands GIF" /></p>
<p>We’ve dropped the support for commands which perform the redundant tasks such as <code>grails run-app</code> and we recommend using the Gradle <code>bootRun</code> task to run your application. However, we’ll add the support for a few other commands such as <code>create-service</code>, <code>create-test</code>, etc.</p>
<h2>Grails 4 EOL - Announcement</h2>
<p>Grails 4 was released in July 2019. As of March 31, 2023, Grails 4 has reached the end of support. This means Grails version 4.x is unlikely to receive additional updates.</p>
<p>The Grails Foundation is committed to the continued evolution, development, maintenance, and support of the Grails framework. Our goal is to provide Grails users the support they need while maintaining as much focus as possible on innovation. The level and type of support available for earlier versions of the Grails framework will change as the Framework continues to evolve, and the support team remains available to help regardless of the version of the Grails framework that you are using. Please see support options <a href="/support.html">here</a>.</p>
<p>We understand that different organizations have different support needs. With our support options, we can help your team make the most of the features available in the Grails framework and add another layer of protection to the investment in your critical business applications. <a href="/support.html">Commercial Support</a> if you need help supporting your Grails applications.</p>
<h2>Grails Roadmap</h2>
<ul>
<li>The new Grails Forge website is coming soon!</li>
<li>More application types will be supported.</li>
<li>We will be adding more features such as Security.</li>
<li>The Grails Scaffolding Plugin will be updated to work with Grails 6.</li>
</ul>]]></description><author>Puneet Behl</author><guid>2023-05-27-grails-6-rc1</guid><pubDate>Sat, 27 May 2023 00:00:00 GMT</pubDate></item><item><title>Grails 6 M2 - Release Annoucement</title><link>https://grails.apache.org/blog/2023-03-29-grails-6-m2.html</link><description><![CDATA[</p>
<p>The Grails Foundation is excited for the release of Grails framework 6 M2! We encourage you to try this release and provide your feedback <a href="https://github.com/apache/grails-core/issues">here</a>.</p>
<h2>What are some changes to expect?</h2>
<ul>
<li>Leveling up the Grails CLI</li>
<li>New Java 11 Baseline</li>
</ul>
<p>With the release of Grails 6 M2, we have introduced a brand new implementation of the Grails Command Line Interface (CLI) inspired by the CLI used in the Micronaut framework. This new CLI is much more flexible, fast and easy to maintain. Using the new CLI, you can create Grails applications offline or in areas of limited connectivity, and it is lightning fast. It uses <a href="https://picocli.info/">Picocli</a> for building the command-line application, and the Rocker template engine which produces statically typed plain Java objects.</p>
<h2>Key CLI Concepts</h2>
<ul>
<li>
<p>Application Type</p>
<p>An application type can be defined as a pre-selected group of features required at minimum to build a specific type of application. For example - a Grails web application is shipped with features such as GSP, Geb, Webdriver, etc.</p>
</li>
<li>
<p>Features</p>
<p>A feature affects the outcome of a generated project such as adding dependencies to build.gradle file, some default configurations, support additional CLI commands, etc.</p>
</li>
</ul>
<p>Starting with Grails 6, there will not be a Grails CLI wrapper in new projects.  Many of the commands offered by the legacy CLI can be run directly from Gradle.  For example, <code>./grailsw run-app</code> can be achieved with <code>./gradlew bootRun</code>.  For commands that alter the files of a Grails project like <code>create-controller</code>, you will be able to use the globally-installed Grails CLI from within the project folder.</p>
<p>There are some specific commands which are supported via plugins that may not work with the New CLI, these commands are written as Groovy scripts and need to be converted to Grails ApplicationCommand which would make them available as Gradle tasks. You can find more information in the Grails Documentation about <a href="https://grails.apache.org/docs/latest/guide/commandLine.html#creatingCustomCommands">creating custom commands</a>. Alternatively, we can rewrite commands in the New Grails CLI and use rocker templates instead.</p>
<h2>Installation</h2>
<h3>Installing with SDKMan</h3>
<p>The easiest way to install new Grails CLI is with <a href="https://sdkman.io">SDKMan</a>, run the following command:</p>
<pre><code>sdk install grails 6.0.0-M2
</code></pre>
<h3>Download &amp; Install Binary</h3>
<ul>
<li>Download the latest binary from <a href="https://github.com/apache/grails-forge/releases/tag/v6.0.0-M2">here</a> based on your Operating System</li>
<li>Extract to appropriate directory</li>
<li>Create environment variable GRAILS_HOME which points to installation directory, eg: c:/grails</li>
<li>Update the PATH environment variable, append %GRAILS_HOME%\bin</li>
</ul>
<h3>Use SDKMan To Build &amp; Install From Source</h3>
<ul>
<li>Clone the repository as follows:</li>
</ul>
<pre><code>git clone https://github.com/apache/grails-forge.git
</code></pre>
<ul>
<li>Build dist using the command <code>./gradlew :grails-cli:assembleDist</code></li>
<li>Copy &amp; Extract the archive from grails-forge/grails-cli/build/distributions/grails-cli.*.zip to the user home directory</li>
<li>Use <a href="https://sdkman.io/">SDKMan</a>, to install dev version using the following command:</li>
</ul>
<pre><code>sdk install grails dev ~/grails-cli/
sdk use grails dev
</code></pre>
<h2>The Previous Grails CLI &amp; Its Limitations</h2>
<p>The previous Grails CLI used YAML based configuration files which are not very extensible when it comes to customizing it. Also, it was very difficult to use automation tools to auto-update dependencies and the process of testing the profile was very complicated.</p>
<h2>The Grails Profiles &amp; ApplicationType in the New CLI</h2>
<p>The Grails Profiles such as web, plugin, react, etc. are supported by means of application-types. Currently, we support following application-types:</p>
<ul>
<li>Web</li>
<li>REST API</li>
<li>Web Plugin</li>
<li>Plugin</li>
</ul>
<p>We will soon add support for REST API Plugin, ReactJS and AngularJS application types.</p>
<h2>The Grails Scaffolding Plugin</h2>
<p>The Grails Scaffolding plugin, which defines commands such as generate-all and generate-controller, will not work because it uses the command scripts. In Grails 3, we introduced the concept of an ApplicationCommand which has similar abilities as scripts in regards to retrieving arguments, template generation, file access, and model building. For more information, please read the Grails documentation for <a href="https://grails.apache.org/docs/latest/guide/commandLine.html#creatingCustomCommands">creating custom commands</a>.</p>
<h2>Why should you upgrade to Grails 6?</h2>
<ul>
<li>With the future release of Grails 7, we are planning a move to Java 17 as a baseline, so Grails 6 provides an easy upgrade path to users or applications who are planning to move to Java 17.</li>
<li>We will be ending the support for Grails 4 by the end of this quarter, and Grails 5 by the end of 2023. We strongly recommend updating applications to upgrade to Grails 6.</li>
<li>Additionally with this realease, we have updated a bunch of underlying dependencies. Some of those updates include: Spring 5.3.26, Spring Boot 2.7.9, Tomcat 9.0.73, and Hibernate 5.6.15.Final. Check the Grails Core <a href="https://github.com/apache/grails-core/releases/v6.0.0-M2/">GitHub release notes</a> page for more information.</li>
</ul>
<h2>Grails 6 Release Schedule</h2>
<ul>
<li>We will work on updating other important Grails projects such as GORM, GSP, Views etc to Grails 6 M2 over the next few days.</li>
<li>Grails 6 RC1 will be released in the next couple of weeks which will include updates to GORM, GSP, and Grails Views.</li>
<li>Based on feedback, Grails GA or another RC release is targeted for the end of April.</li>
</ul>
<h2>Grails Support Schedule</h2>
<ul>
<li>We will end support for Grails 4 by the end of this quarter (31st March 2023).
End of support means that this version of the Grails framework is no longer actively maintained and is unlikely to receive additional updates. You can still recieve commercial support through our additional support options <a href="/support.html">here</a>.</li>
<li>We will support Grails 5 through the end of 2023.</li>
</ul>
<p>The Grails Foundation is committed to the continued evolution, development, maintenance, and support of the Grails framework. Our goal is to provide Grails users the support they need while maintaining as much focus as possible on innovation. The level and type of support available for earlier versions of the Grails framework will change as the Framework continues to evolve, and the support team remains available to help regardless of the version of the Grails framework that you are using.</p>
<p>We understand that different organizations have different support needs. With our support options, we can help your team make the most of the features available in the Grails framework and add another layer of protection to the investment in your critical business applications. <a href="/support.html">Commercial Support</a> if you need help supporting your Grails applications.</p>
<h2>The Road Ahead..</h2>
<ul>
<li>The new Grails Forge website is coming soon!</li>
<li>More application types will be supported.</li>
<li>We will be adding more features such as Security.</li>
<li>There will be support for the Grails Scaffolding Plugin with Grails 6.</li>
<li>We are planning the move to Java 17 baseline, support Apache Groovy 4, Spring 6, and Spring Boot 3 as part of Grails 7.</li>
</ul>
<h2>Thank you!</h2>
<p>Big thanks to our wonderful community of users for your continued support of the Grails framework over the past 15 years!
With a hopeful outlook towards the future and a deep sense of gratitude, we eagerly anticipate the path that lies ahead, embracing the invaluable chance to develop and pioneer new advancements within this Framework.</p>]]></description><author>Puneet Behl</author><guid>2023-03-29-grails-6-m2</guid><pubDate>Wed, 29 Mar 2023 00:00:00 GMT</pubDate></item><item><title>Grails Foundation joining Unity</title><link>https://grails.apache.org/blog/2023-03-17-grails-foundation-joining-unity-foundation.html</link><description><![CDATA[</p>
<p>The Grails Foundation™ is pleased to announce a new partnership with the <a href="https://unityfoundation.io/">Unity Foundation</a>™.</p>
<p>The Grails Foundation is one of three Open Source Software (OSS) Foundations joining the Unity Foundation as official member organizations of the Unity team. Established in 2020 as a non-profit, community-based organization, Unity set out on a journey to leverage open source software tools to provide more inherently equitable access to the information and services that support the needs of the greater St. Louis area community, with a focus on the underserved.</p>
<p>Dr. Ebrahim Moshiri, founder of St. Louis-based technology company, <a href="https://objectcomputing.com/">Object Computing, Inc</a>. (OCI), envisioned a radically new way of serving the community by extending all of the openly available tools and systems that OCI had been building, supporting, and advancing for the last three decades. The <a href="https://unityfoundation.io/#projects">Unity Foundation</a> was organized to drive the engineering of a new kind of CommUNITY Infrastructure and data sharing ecosystem that, through collaborations and partnerships with other St. Louis based organizations, can address the digital divide in our region. In essence, Unity seeks to apply the ideals of altruism, benevolence, and social consciousness to the world of software tools and systems that organizations use to collect, organize, and share data.</p>
<p>As a commitment to reusable and interoperable technologies to facilitate greater access and capability for all users, OCI made significant investments in establishing three OSS product Foundations - the Grails Foundation™, the <a href="https://micronaut.io/foundation/">Micronaut Foundation</a>™, and the <a href="https://opendds.org/foundation/">OpenDDS Foundation</a>™. These non-profit entities are solely focused on ensuring the continuity and sustainability of our OSS products. Today, thousands of software engineers, researchers, and end users around the globe use and contribute to these trusted tools and platforms, including organizations like Microsoft, Amazon, Oracle, and Google.
Moving the Grails Foundation under Unity provides a meaningful alliance between Unity and our amazing community. We are excited for the opportunity to work closely with Unity to further develop an open source technology infrastructure and ecosystem supporting our underserved communities. Unity will continue its commitment to serve as an OSS aggregator, and will scale community participation in helping define, advance, and contribute to the ongoing success and sustainability of the Grails framework.</p>
<p>In January 2023, Object Computing and the Unity Foundation together pledged an additional $2M to the Grails Foundation for the ongoing benefit and advancement of the Grails framework. As the proud steward of the Grails Foundation, Unity continues its commitment to innovative collaboration with community partners with a deep desire to build and contribute to a new CommUNITY infrastructure - one that will be <em>engineered</em> for equity, accessibility, enrichment, and compassion for those who need it most.</p>
<p>To learn more about the Unity Foundation, <a href="https://unityfoundation.io/">click here.</a></p>
<p>To learn more about how you or your organization can support the Grails Foundation!</p>]]></description><author>Jen Wiese</author><guid>2023-03-17-grails-foundation-joining-unity-foundation</guid><pubDate>Fri, 17 Mar 2023 00:00:00 GMT</pubDate></item><item><title>Grails Artifact Repository Scheduled Maintenance</title><link>https://grails.apache.org/blog/2023-02-08-repository-maint.html</link><description><![CDATA[</p>
<p><strong>Scheduled Maintenance of repo.grails.org Feb 12, 2023 08:00 UTC - 11:00 UTC</strong></p>
<p>The Grails Artifactory Instance at <a href="https://repo.grails.org">repo.grails.org</a> will be down for scheduled maintenance on Sunday February 12th, 2023 as JFrog migrates it to newer infrastructure.</p>
<p>The outage will begin at <strong>08:00 UTC</strong> and is expected to last 3 hours. The repository should be available again at <strong>11:00 UTC</strong></p>
<p>During this time, projects that retrieve their dependencies from repo.grails.org may experience issues.</p>
<p>For more information, or to discuss issues encountered after this window, please see this <a href="https://github.com/apache/grails-core/issues/12863">GitHub issue</a>.</p>]]></description><author>Jason Schindler</author><guid>2023-02-08-repository-maint</guid><pubDate>Wed, 08 Feb 2023 00:00:00 GMT</pubDate></item><item><title>Grails Spring Security Core Plugin Improper Privilege Management Vulnerability</title><link>https://grails.apache.org/blog/2022-11-22-ss-plugin-auth-cve.html</link><description><![CDATA[</p>
<p><strong>Information regarding CVE-2022-41923</strong></p>
<h2>Overview</h2>
<p>The Grails team has confirmed a security vulnerability found in the Grails Spring Security Core plugin, initially identified by Adrien Peter and Benjamin Sepe from <a href="https://www.synacktiv.com/">Synacktiv</a>, and investigated and reported by Arek Bazylewicz of <a href="https://id5.io">ID5</a>. This vulnerability has been assigned identifier <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-41923">CVE-2022-41923</a>.</p>
<p>The vulnerability allows an attacker access to one endpoint (i.e. the targeted endpoint) using the authorization requirements of a different endpoint (i.e. the donor endpoint). In some Grails framework applications, access to the targeted endpoint will be granted based on meeting the authorization requirements of the donor endpoint, which can result in a privilege escalation attack.</p>
<p><strong>Update</strong>: Synacktiv has made available their <a href="https://www.synacktiv.com/sites/default/files/2023-03/Synacktiv-Grails-Spring-Security-CVE-2022-41923.pdf">security advisory (PDF)</a> on this vulnerability.</p>
<h2>Impacted Applications</h2>
<p>Grails Spring Security Core plugin versions:</p>
<ul>
<li>1.x</li>
<li>2.x</li>
<li>&gt;=3.0.0 &lt;3.3.2</li>
<li>&gt;=4.0.0 &lt;4.0.5</li>
<li>&gt;=5.0.0 &lt;5.1.1</li>
</ul>
<p>We strongly suggest that all Grails framework applications using the Grails Spring Security Core plugin be updated to a patched release of the plugin.</p>
<h2>Protecting Your Applications</h2>
<p>The following Grails Spring Security Core plugin versions have been patched for this vulnerability:</p>
<ul>
<li><a href="https://github.com/apache/grails-spring-security/releases/tag/v3.3.2">3.3.2</a></li>
<li><a href="https://github.com/apache/grails-spring-security/releases/tag/v4.0.5">4.0.5</a></li>
<li><a href="https://github.com/apache/grails-spring-security/releases/tag/v5.1.1">5.1.1</a></li>
</ul>
<p>The best way to protect your Grails framework application is to upgrade to a patched release of this plugin.</p>
<p>If you are unable to upgrade to a patched version of the plugin, you can work around the issue with a small code and configuration change described in <a href="https://github.com/grails/GSSC-CVE-2022-41923">this GitHub repository</a>.  We have provided workaround examples for Grails framework 2 through 5 applications. A demonstration of the vulnerability will be provided in time, after users have an opportunity to patch their applications.</p>
<h2>Looking Forward</h2>
<p>The Grails Foundation and the Grails development team take application security very seriously. We are continuing to research and monitor this vulnerability and will update this post with new information as it is discovered.</p>
<p>If you have questions about this vulnerability or need assistance on upgrades or workarounds, please see the <a href="https://github.com/apache/grails-spring-security/issues/844">discussion on GitHub</a> or contact us at <a href="mailto:security@apache.org">security@apache.org</a>.</p>]]></description><author>Matthew Moss</author><guid>2022-11-22-ss-plugin-auth-cve</guid><pubDate>Tue, 22 Nov 2022 00:00:00 GMT</pubDate></item><item><title>Grails Data Binding to Static Properties Bug</title><link>https://grails.apache.org/blog/2022-09-28-static-binding-bug.html</link><description><![CDATA[</p>
<p><strong>Information about an issue in the Grails data binding logic that can cause modification of static properties</strong></p>
<h2>Summary</h2>
<p>The Grails Team has confirmed a bug that was found in the Grails data binding logic, which incorrectly permits data binding to static properties under certain conditions. This bug was identified and reported by the Engineering Team at Transitional Data Services (<a href="https://tdsi.com">https://tdsi.com</a>).</p>
<h2>Description</h2>
<p>Data binding to static properties is not intended behavior. However, because of this bug, a static property of the target object's class may be modified if:</p>
<ul>
<li>The data binding source contains a property of the same name as the static property</li>
<li>The static property's declared type is <strong>Object</strong> (or the type is undeclared, which is the same as declaring as <strong>Object</strong>)</li>
<li>The static property is not final</li>
</ul>
<p>This can occur when manually calling <strong>bindData</strong> (or one of several variants) given the conditions above. Under particular additional conditions, controller actions that automatically bind request data to (nested) command objects may cause static properties to change.</p>
<h2>The constraints property</h2>
<p>One common property that represents an important part of the functionality in the Grails framework is the <strong>constraints</strong> property. The <strong>constraints</strong> property allows classes that implement the <strong>Validateable</strong> trait to check that the data in an instance of the class is valid. It is also a static property that could be overwritten due to this bug, potentially leading to data corruption.   Because of this possibility, we feel it is important for organizations using the Framework to be aware of this bug and its resolutions.</p>
<p>For more information about data validation functionality available in the Grails framework, please see the <a href="https://grails.apache.org/docs/5.2.4/guide/validation.html">documentation</a>.</p>
<h2>Resolution</h2>
<p>The Grails Team recommends that all Grails applications be upgraded to a patched Grails release. Grails 4.x applications can be upgraded to version 4.1.2 or higher, and Grails 5.x applications can be upgraded to 5.2.3 or higher.</p>
<p>We have released a patched version of Grails 3 for this bug.  Grails 3.x applications can be upgraded to version 3.3.16.</p>
<p>Please note that versions 1, 2, and 3 of the Grails framework have reached end of support.  We strongly recommend that applications built with these versions be upgraded to an actively maintained version of the Framework. Additionally, the Grails Foundation provides <a href="/support.html">Commercial Support options</a> for Grails framework versions 3, 4, and 5.</p>
<p>If you are unable to upgrade to a patched version of the Framework, you can make a couple of minor adjustments to work around the issue.</p>
<p>First, if your application makes explicit calls to <strong>bindData</strong>, those calls should be reviewed and adjusted to avoid binding to static properties of the target instance's class.</p>
<p>Second, you can prevent data binding to static properties by marking them as <strong>final</strong>. For example:</p>
<pre><code class="language-groovy">class RecordValueCommand implements Validateable {
    int value
    static constraints = { value min: 0 }
}
</code></pre>
<p>Because <strong>constraints</strong> is not <strong>final</strong> and has no declared type, it is susceptible to this data binding bug. The workaround is to add the <strong>final</strong> modifier.</p>
<pre><code class="language-groovy">static final constraints = { value min: 0 }
</code></pre>
<p>In situations where the <strong>final</strong> modifier cannot be added, the type of the property should be declared explicitly (not <strong>Object</strong>) and the static property will resist type-changing modifications.</p>
<pre><code class="language-groovy">static Closure constraints = { value min: 0 }
</code></pre>
<h2>Thank you!</h2>
<p>We would like to thank the Engineering Team at Transitional Data Services for identifying this bug as well as the countless contributions from the folks in  our awesome community.  Without your dedication and enthusiasm, the Grails framework would not be where it is today.  Thank you!</p>
<p>For more technical details about this bug and the patches, please see the <a href="https://github.com/apache/grails-core/issues/12718">discussion on GitHub</a>.</p>]]></description><author>Matthew Moss</author><guid>2022-09-28-static-binding-bug</guid><pubDate>Wed, 28 Sep 2022 00:00:00 GMT</pubDate></item><item><title>Grails Framework Remote Code Execution Vulnerability</title><link>https://grails.apache.org/blog/2022-07-18-rce-vulnerability.html</link><description><![CDATA[</p>
<p><strong>Grails Framework information regarding CVE-2022-35912</strong></p>
<h2>Updates</h2>
<h3>July 20th, 2022</h3>
<p>Updated impacted Grails framework versions.</p>
<h2>Overview</h2>
<p>The Grails team has confirmed a critical security vulnerability reported by meizjm3i and codeplutos of AntGroup FG Security Lab. This vulnerability has been assigned identifier <a href="https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-35912">CVE-2022-35912</a>.</p>
<p>The vulnerability allows an attacker to remotely execute code within a Grails application runtime by issuing a specially crafted web request that grants the attacker access to the class loader. This attack exploits a section of the Grails data-binding logic.  Grails data-binding is invoked in a number of ways including the creation of command objects, domain class construction, and manual data binding when using <code>bindData</code>.  For a full description, please refer to <a href="https://grails.apache.org/docs/latest/guide/theWebLayer.html#dataBinding">the data-binding documentation</a>.</p>
<h2>Impacted Applications</h2>
<ul>
<li>Grails framework versions
<ul>
<li>&gt;= 3.3.10 &amp; &lt; 3.3.15</li>
<li>&gt;= 4.0.0 &amp; &lt; 4.1.1</li>
<li>&gt;= 5.0.0 &amp; &lt; 5.1.9</li>
<li>5.2.0</li>
</ul>
</li>
<li>Running on Java 8</li>
<li>Using embedded Tomcat runtime, as well as those deployed to a Servlet Container</li>
</ul>
<p>We have confirmed this vulnerability on Grails framework versions 3.3.10 and higher (including Grails framework 4 and 5) that are running on Java 8. The vulnerability has been observed in both the embedded Tomcat runtime and applications deployed as a war to a Tomcat instance.</p>
<p>Due to the nature of this vulnerability, we strongly suggest that all Grails applications, <em>including those that are not vulnerable to this specific attack</em>, be updated to a patched Grails release. While we have not been able to reproduce this specific exploit on applications running in Java 11 or in versions of the Grails framework before 3.3.10, the nature of the vulnerability is such that variations on the attack could be discovered that earlier Grails releases, and Grails applications running on higher versions of Java, will be impacted.</p>
<h2>Protecting Your Applications</h2>
<p>The following Grails framework versions have been patched for this vulnerability:</p>
<ul>
<li>5.2.1</li>
<li>5.1.9</li>
<li>4.1.1</li>
<li>3.3.15</li>
</ul>
<p>The best way to protect your Grails applications is to upgrade to a patched release of the framework.</p>
<p>Grails 4.x applications can be upgraded to version 4.1.1 or higher, and Grails 5.0.x and 5.1.x applications can be upgraded to 5.1.9 or higher, and Grails 5.2 applications can be upgraded to 5.2.1 or higher.</p>
<h2>Protecting Grails 3 Applications</h2>
<p>For Grails 3 applications, we have released Grails framework 3.3.15, which includes a patch for this vulnerability (please note that Grails framework version 3 has reached end of support, and we strongly recommend that all Grails 3 applications be upgraded to an actively maintained version of the framework).</p>
<h2>Protecting Grails 2 Applications</h2>
<p>As mentioned above, this specific attack is enabled by code added in version 3.3.10 of the Grails framework, so Grails framework version 2 applications are not vulnerable to it.  Due to the nature of the exploit, we strongly suggest that you upgrade your Grails applications to a patched and supported version of the framework.  Grails framework version 2 has reached end of support.</p>
<h2>Next Steps</h2>
<p>The Grails Foundation and the Grails core development team take application security very seriously. We are continuing to research and monitor this vulnerability and will update this post with new information as it is discovered.</p>]]></description><author>Puneet Behl and Jason Schindler</author><guid>2022-07-18-rce-vulnerability</guid><pubDate>Mon, 18 Jul 2022 00:00:00 GMT</pubDate></item><item><title>Announcing Our Newest Tools and Infrastructure Partner: JetBrains</title><link>https://grails.apache.org/blog/2022-04-01-jetbrains-new-tools-and-infrastructure-partner.html</link><description><![CDATA[</p>
<p><strong>We're pleased to announce that JetBrains has joined the Grails Foundation as a Tools and Infrastructure Partner.</strong></p>
<p>The Grails Foundation™ is truly appreciative of the tremendous support we receive from our sponsors. In addition to financial support, generous contributions of development tools, infrastructure, and other resources are essential to the continued evolution of the Grails® framework. Our Tools and Infrastructure Partnership program recognizes the companies whose contributions enable us to maintain and expand both the open source technologies and the assets we rely on to keep our communities informed and engaged.</p>
<p>Today, we are pleased to announce that <a href="https://www.jetbrains.com/">JetBrains</a>, producer of <a href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a>, has joined the Grails Foundation as a Tools and Infrastructure Partner! In support of our organizations' shared values and goals within the open source ecosystem, JetBrains generously provides the Foundation with licenses to their incredible suite of products for our core development team!</p>
<p>As many Grails developers already know, the ultimate edition of IntelliJ IDEA includes <a href="https://www.jetbrains.com/help/idea/getting-started-with-grails3.html">first-class support for the Grails Framework</a>, as well as a host of features to increase developer productivity across a multitude of languages and frameworks. Those features help the Foundation's core development team do the necessary work to bring the open source Framework to the community.</p>
<p>We’re delighted to have JetBrains on board as a Tools and Infrastructure Partner. The JetBrains team's support for and excitement about Grails technology over the years has been tremendous. Their engagement in our community has been awesome, and we look forward to continued collaboration in the years to come. We truly appreciate the dedication and passion JetBrains has for open source projects. On behalf of the Grails Foundation, thank you! Initiatives like these that support and grow our Framework are the kinds of things we look for in a lifelong technology partner.</p>
<p>The Grails Foundation is a not-for-profit organization that supports the Grails framework. The Foundation not only builds and supports an ecosystem of documentation, functionality, and services, it promotes and evangelizes the Framework as a leading technology in the JVM space. The generous support of our Corporate Sponsors allows the Foundation to continue to ensure technical innovation and advancement of the Framework as a free and open public-use software development toolkit for our growing global community.</p>
<p>To learn more about how you or your organization can help support this Foundation, please <a href="/">check us out</a>!</p>]]></description><author>Jen Wiese</author><guid>2022-04-01-jetbrains-new-tools-and-infrastructure-partner</guid><pubDate>Fri, 01 Apr 2022 00:00:00 GMT</pubDate></item><item><title>Grails and the Recent Spring Framework RCE</title><link>https://grails.apache.org/blog/2022-03-31-grails-spring-rce.html</link><description><![CDATA[</p>
<p><strong>Grails Framework information regarding CVE-2022-22965</strong></p>
<h2>Background</h2>
<p>The Spring Framework Team <a href="https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement">recently announced</a> a remote code execution vulnerability, published as <a href="https://tanzu.vmware.com/security/cve-2022-22965">CVE-2022-22965</a>, discovered within the Spring Framework.  At this time, there is a known exploit that impacts applications that:</p>
<ul>
<li>Use JDK 9 or higher</li>
<li>Run on the Apache Tomcat Servlet container</li>
<li>Are packaged as a WAR, and</li>
<li>Include the <code>spring-webmvc</code> or <code>spring-webflux</code> dependency</li>
</ul>
<p>More up-to-date information can be found on the <a href="https://spring.io/blog/2022/03/31/spring-framework-rce-early-announcement">Spring Blog announcement</a>.</p>
<h2>Are Grails Applications Vulnerable?</h2>
<p>Because Grails applications are built on top of Spring and Spring Boot, the Grails team has taken this vulnerability very seriously. Our investigations have yielded no evidence that Grails 4.x or 5.x applications are vulnerable to this attack. The Grails framework has its own data-binding logic, which includes checks to validate that a given property a) is in a list of properties that may be bound to, and b) exists within the target metaClass. All other property candidates are ignored.</p>
<p>The known exploit is one mechanism that can be used for this vulnerability. We will continue to monitor this situation and alert the Grails community of any vulnerabilities discovered, along with mitigation steps.</p>
<h2>Next Steps</h2>
<p>Although at this time, we have no reason to believe that Grails applications are vulnerable, as a precaution, we have released <a href="https://github.com/apache/grails-core/releases/tag/v5.1.6">Grails 5.1.6</a>.  This Grails Framework release updates our Spring dependency to 5.3.18, which includes the upstream patch from the Spring Framework Team.</p>]]></description><author>Jason Schindler</author><guid>2022-03-31-grails-spring-rce</guid><pubDate>Thu, 31 Mar 2022 00:00:00 GMT</pubDate></item><item><title>2GM Town Hall Meeting: 2022 Q1</title><link>https://grails.apache.org/blog/2022-01-07-2gm-town-hall-q1.html</link><description><![CDATA[</p>
<p>A big thanks to everyone who joined us for our Q1 2GM Town Hall Meeting! For those of you who missed the live event, the recording is embedded below.</p>
<p>At this quarter’s meeting, we provided an update on the latest advancements with the Grails and Micronaut frameworks, including a look at what is coming soon. We also shared the latest news and sponsors of the Grails and Micronaut Foundations, as well as some great live discussions and Q&amp;A with our panel.</p>
<p>A special thanks to our fantastic panel of experts: James Kleeh, Puneet Behl, Sergio del Amo Caballero, and our awesome guest <a href="http://melix.github.io/blog/">Cédric Champeau</a>.</p>
<p>Till next time!</p>
<p>— Jen Wiese</p>
<p><a href="https://objectcomputing.com/download_file/5451">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/EE5flg8Hj_E" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2022-01-07-2gm-town-hall-q1</guid><pubDate>Fri, 07 Jan 2022 00:00:00 GMT</pubDate></item><item><title>Grails Foundation Announces First Tools and Infrastructure Partner</title><link>https://grails.apache.org/blog/2022-01-07-gradle-enterprise-tools-and-infrastructure-partner.html</link><description><![CDATA[</p>
<p><strong>Gradle has joined the Grails Foundation as our first Tools and Infrastructure Partner</strong></p>
<p>The Grails Foundation™ is truly appreciative of the tremendous support we receive from our sponsors. In addition to financial support, generous contributions of development tools, infrastructure, and other resources are essential to the continued evolution of the Grails® framework. Thus, we have established a new partnership program to recognize the companies whose contributions enable us to maintain and expand both the open source technologies and the assets we rely on to keep our communities informed and engaged.</p>
<p>Today, we are pleased to announce that Gradle Inc, the providers of <a href="https://gradle.org">Gradle Build Tool</a> and <a href="https://gradle.com">Gradle Enterprise</a>, has joined the Grails Foundation as our first Tools and Infrastructure Partner! In support of our organizations' shared values and goals within the open source ecosystem, Gradle provides the Foundation free instances of <a href="https://gradle.com">Gradle Enterprise</a>.</p>
<p>Gradle Enterprise has helped our team to improve build times and test-feedback cycle times, and improve troubleshooting efficiency by combining root-cause analysis data with failure analytics.</p>
<p>We’re delighted to have Gradle on board as a Tools and Infrastructure Partner. The Gradle team's support and excitement for the Grails technology over the years has been tremendous. Their engagement in our community has been awesome, and we look forward to continued collaboration in the years to come. We truly appreciate the dedication and passion Gradle has for open source projects. On behalf of the Grails Foundation, thank you! Initiatives like these that support and grow our Framework are the kinds of things we look for in a lifelong technology partner.</p>
<p>The Grails Foundation is a not-for-profit organization that supports the Grails framework. The Foundation not only builds and supports an ecosystem of documentation, functionality, and services, it promotes and evangelizes the Framework as a leading technology in the JVM space. The generous support of our Corporate Sponsors allows the Foundation to continue to ensure technical innovation and advancement of the Framework as a free and open public-use software development toolkit for our growing global community.</p>
<p>To learn more about how you or your organization can support this Foundation, please <a href="/">check us out</a>!</p>]]></description><author>Jen Wiese</author><guid>2022-01-07-gradle-enterprise-tools-and-infrastructure-partner</guid><pubDate>Fri, 07 Jan 2022 00:00:00 GMT</pubDate></item><item><title>Grails Framework 5.1 Released</title><link>https://grails.apache.org/blog/2021-12-15-grails-five-one.html</link><description><![CDATA[</p>
<p>The Grails Foundation™ is pleased to announce a new minor release: <a href="https://github.com/apache/grails-core/releases/tag/v5.1.0"><strong>Grails framework 5.1</strong></a>!</p>
<p>This release of the Grails framework includes a number of bug fixes and Gradle 7.2 compatibility changes (the Gradle task definitions with <a href="https://docs.gradle.org/7.0/userguide/upgrading_version_6.html#task_validation_problems_are_now_errors">incorrectly defined input output will now fail the build</a>), plus a bunch of dependencies updates. For more information, please check the <a href="https://github.com/apache/grails-core/releases/tag/v5.1.0"><strong>Grails 5.1 release notes</strong></a>.</p>
<h2>Updated Dependencies</h2>
<p>The dependencies that have been updated include:</p>
<h3>Spring Boot 2.6.1</h3>
<p>One important change that accompanies Spring Boot 2.6 is that circular references are prohibited. In order to maintain backwards compatibility for Grails users, Grails framework 5.1 explicitly enables circular references by default. This will no longer be the case once Grails framework 6 is released. For more information check the <a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.6-Release-Notes">Spring Boot 2.6 Release Notes</a>.</p>
<h3>Micronaut 3.2</h3>
<p>Updating to Micronaut 3.2 should not affect Grails applications. Please check <a href="https://github.com/micronaut-projects/micronaut-core/releases/tag/v3.2.2">the release notes</a> for more details.</p>
<h3>GORM for Hibernate 7.2, which updates to Hibernate 5.6</h3>
<p>This version updates to <a href="https://in.relation.to/2021/12/08/hibernate-orm-562/">Hibernate ORM 5.6.2</a>. There are several other bug fixes and dependency updates. For complete details,  please check <a href="https://github.com/grails/gorm-hibernate5/releases/tag/v7.2.0">the release notes for GORM for Hibernate 7.2</a>.</p>
<h3>GORM for MongoDB 7.2, which updates to underline Mongo driver 4.4</h3>
<p>This version updates the underlying Mongo driver to 4.4. Read <a href="https://docs.mongodb.com/drivers/java/sync/current/whats-new/#std-label-version-4.4">What's New — MongoDB Java Sync 4.4</a> to understand what has changed in the Java driver. We also recommend that you check <a href="https://github.com/grails/gorm-mongodb/releases/tag/v7.2.0">the release notes for GORM for MongoDB 7.2</a> for a list of all the changes and dependency updates.</p>
<h3>GORM for Neo4j</h3>
<p>Please check <a href="https://github.com/grails/gorm-neo4j/releases/tag/v7.2.0">the release notes</a> for complete information about the changes in this release.</p>
<h2>A Note About Semantic Versioning</h2>
<p>Grails framework 4 was the first version of the Framework that followed semantic versioning. Grails framework 5.1.0 is a minor release; thus, it should not contain breaking changes. It contains new features, the patches introduced in Grails 5.0.x releases, and minor upgrades to Grails dependencies, such as Spring Boot, Micronaut, and GORM. Please upgrade quickly to get the latest updates into your Grails 5 applications.</p>
<h2>Upgrading to Grails Framework 5.1</h2>
<p>As this is a minor release, updating to Grails framework 5.1 should be pretty straightforward. Here are step-by step instructions:</p>
<p>In your <code>gradle.properties</code> file,</p>
<ul>
<li>Update property <code>grailsVersion</code> to 5.1.0</li>
<li>Update property <code>gorm.version</code> to 7.2.0</li>
</ul>
<p>In your <code>build.gradle</code> file</p>
<ul>
<li>Update Gradle <code>hibernate5</code> plugin to 7.2.0</li>
<li>Under dependencies, update <code>hibernate-core</code> to 5.6.2.Final</li>
</ul>
<h2>The Road Ahead</h2>
<h3>Spring Security Core Plugin</h3>
<p>Currently, the Spring Security Core Grails plugin still uses Spring Security Core 5.1.13.RELEASE which is EOL. We are planning to update the plugin to use the latest version of Spring Security. See <a href="https://github.com/spring-projects/spring-security/wiki/Spring-Security-Versions#released-versions">Spring Security Versions · spring-projects/spring-security Wiki · GitHub</a> for more information.</p>
<h3>Leveling up the Grails CLI!</h3>
<p>The current implementation of Grails CLI is difficult to test and unadaptable. For example, configuring automation tools to update dependencies is impossible. Also, the CLI does not work offline, and it is very difficult to customize it. We plan to work on implementing a new, super-flexible, easy-to-customize CLI that eliminates these limitations.</p>
<h3>Consolidating Grails Plugins</h3>
<p>Currently, Grails plugins are distributed across multiple Github organizations, including <a href="https://github.com/gpc">gpc - Grails Plugin Collective · GitHub</a>, <a href="https://github.com/grails-plugins">Grails Plugins · GitHub</a>, and <a href="https://github.com/grails3-plugins">grails3-plugins · GitHub</a>. We are planning to consolidate a list of all active plugins into one place. We will soon share more information about this initiative in the Grails blog.</p>
<h2>Need help upgrading to Grails® framework 5.1?</h2>
<p>We are excited about the release of Grails framework 5.1 and look forward to hearing about your experience with it. Please feel free to reach out to us if you have any questions or need help updating your applications. Community members and members of the core development team are available to answer questions on <a href="https://slack.grails.org/">our Slack channel</a>, and hourly commercial support can be purchased <a href="https://objectcomputing.com/products/grails/consulting-support">here</a>.</p>]]></description><author>Puneet Behl</author><guid>2021-12-15-grails-five-one</guid><pubDate>Sat, 18 Dec 2021 00:00:00 GMT</pubDate></item><item><title>Grails Framework and Log4j 2 Vulnerability</title><link>https://grails.apache.org/blog/2021-12-14-log4j2-cve.html</link><description><![CDATA[</p>
<p>Vulnerability <a href="https://nvd.nist.gov/vuln/detail/CVE-2021-44228">CVE-2021-44228</a> may allow an attacker to remotely execute code. It affects <a href="https://logging.apache.org/log4j/2.x/">Log4j</a>'s <code>log4j-core</code> jar. Log4j <a href="https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.15.0/">v2.15.0</a> fixes it. Moreover, Log4j <a href="https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.16.0/">v2.16.0</a> disables JNDI functionality by default, and it removes message lookups. Log4j <a href="https://repo1.maven.org/maven2/org/apache/logging/log4j/log4j-core/2.17.0/">v2.17.0</a> addresses CVE-2021-45105. It protects against infinite recursion in lookup evaluation.</p>
<h2>Are Grails 2 applications vulnerable?</h2>
<p>CVE-2021-44228 only affects log4j versions between 2.0 and 2.14.1. Grails 2 applications used Log4j 1.x. However, you should consider migrating as soon as possible to the latest version of the Grails framework. Grails 2 is EOL (End of Life).</p>
<h2>Are Grails applications (3, 4, or 5) vulnerable?</h2>
<p>All Grails applications built on Grails framework 3.0.0 and later use <a href="http://logback.qos.ch">Logback</a>. Thus, <strong>most Grails applications are not affected</strong>.</p>
<p>However, your application might be vulnerable if it includes untrusted input in the log messages and pulls <code>log4j-core</code> as a transitive dependency through some other library or a plugin.</p>
<h2>The &quot;tomcat-embed-logging-log4j&quot; dependency</h2>
<p>You might have noticed that there is a tomcat-embed-logging-log4j dependency in the classpath. We believe it is not affected by the vulnerability because:</p>
<ol>
<li>The JAR does not contain <code>org/apache/logging/log4j/core/lookup/JndiLookup.class</code>.</li>
<li>The <a href="https://repo1.maven.org/maven2/org/apache/tomcat/embed/tomcat-embed-logging-log4j/8.5.2/tomcat-embed-logging-log4j-8.5.2.pom">POM</a> does not mention any dependencies.</li>
</ol>
<h2>How can you check to see if you are pulling <code>log4j-core</code> as a transitive dependency?</h2>
<p>If you are using Gradle, the following command will return a dependency report for 'log4j-core' dependency:</p>
<pre><code>./gradlew dependencyInsight --dependency log4j-core
</code></pre>
<p>For Grails 2 applications, use:</p>
<pre><code>./grailsw dependencyReport
</code></pre>
<h2>How do you tell your build to use a particular version of Log4j?</h2>
<p>With Gradle, if your application is pulling <code>log4j-core</code> transitively, you can declare a <code>resolutionStrategy</code>:</p>
<pre><code class="language-groovy">configurations.all {
  resolutionStrategy.eachDependency { DependencyResolveDetails details -&amp;gt;
    if (details.requested.group == 'org.apache.logging.log4j') {
      details.useVersion '2.17.0'
    }
  }
}
</code></pre>
<h2>Other Options</h2>
<p>If you cannot upgrade, please do the following, as <a href="https://logging.apache.org/log4j/2.x/">suggested by the Log4j team</a>:</p>
<blockquote>
<p>For those who cannot upgrade to 2.15.0, in releases &gt;=2.10, this behavior can be mitigated by setting either the system property <code>log4j2.formatMsgNoLookups</code> or the environment variable <code>LOG4J_FORMAT_MSG_NO_LOOKUPS</code> to <code>true</code>.
For releases &gt;=2.7 and &lt;=2.14.1, all <code>PatternLayoutpatterns</code> can be modified to specify the message converter as <code>%m{nolookups}</code> instead of just <code>%m</code>.
For releases &gt;=2.0-beta9 and &lt;=2.10.0, the mitigation is to remove the <code>JndiLookup</code> class from the classpath: <code>zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class</code>.</p>
</blockquote>
<h2>Learn More</h2>
<p>All Grails applications built on Grails framework 3.0.0 and later are Spring Boot applications. Learn more about <a href="https://spring.io/blog/2021/12/10/log4j2-vulnerability-and-spring-boot">Log4j 2 vulnerability and Spring Boot</a> in the Spring blog.</p>]]></description><author>Sergio del Amo</author><guid>2021-12-14-log4j2-cve</guid><pubDate>Tue, 14 Dec 2021 00:00:00 GMT</pubDate></item><item><title>Grails Training Now Enrolling</title><link>https://grails.apache.org/blog/2021-12-06-february-2022-training-announcement.html</link><description><![CDATA[</p>
<p>Our first training workshops for 2022 have just been added to the schedule!</p>
<p>Courses are developed and delivered by team members who work daily with these advanced technologies and can speak with authority as subject matter experts.</p>
<p><a href="https://objectcomputing.com/services/training/catalog/grails/grails-security-workshop"><strong>Introduction to Grails Security</strong></a></p>
<p>February 14 &amp; 15, 2022</p>
<p>Learn how to build robust security functionality into your Grails apps and practice configuring and using such plugins as Spring Security Core, LDAP, REST, ACL, and UI.</p>
<p><a href="https://objectcomputing.com/services/training/catalog/grails/micronaut-and-grails"><strong>Using Micronaut Features in a Grails Application</strong></a></p>
<p>February 16 &amp; 17, 2022</p>
<p>Learn how to take advantage of the Grails framework's built-in Micronaut features to enhance their productivity and application performance.</p>]]></description><author>Jen Wiese</author><guid>2021-12-06-february-2022-training-announcement</guid><pubDate>Tue, 07 Dec 2021 00:00:00 GMT</pubDate></item><item><title>Grails Database Migration 4.0.0-RC1 Released</title><link>https://grails.apache.org/blog/2021-11-23-db-migration-plugin-update.html</link><description><![CDATA[</p>
<p>The Grails Database Migration plugin is one of the most popular plugins in the Grails ecosystem. It helps manage database changes in a structural manner and prevents inconsistencies, communication issues, and other problems.</p>
<p>In today's technology landscape, where application and database schemas are continuously evolving, this plugin makes it easy for the development team to keep track of database changes, quickly rollback, and modify the schema.</p>
<p>The plugin internally uses the Liquibase library to manage the database. When using the plugin, database migrations are represented in the form of text, either using Groovy DSL or native Liquibase XML, in one or more changelog files. There are several popular approaches to maintaining and organizing  the changelog files. We suggest you check <a href="https://grails-plugins.github.io/grails-database-migration/4.0.0-RC1/index.html">Grails Database Migration plugin documentation</a> for details.</p>
<p>In this release, we have updated to Liquibase 4.6, Grails framework 5, and Apache Groovy 3. Refer to the release notes for 4.0.0-RC1 for more details.</p>
<h2>Upgrading from Liquibase 3.10 to 4.6</h2>
<p>The update from Liquibase 3.10 to 4.6 has been a major effort, and it's allowed us to offer users  a bunch of new features, significant improvements, and bug fixes. Following are some highlights:</p>
<ol>
<li>
<p>The extension classes are now loaded with the java.util.ServiceLoader system instead of the legacy custom class-finding logic. This might not impact the main Liquibase functionality, but it will affect anyone using extension classes.</p>
</li>
<li>
<p>Logging is now based on java.util.Logging, which is unlikely to directly impact applications.</p>
</li>
<li>
<p>Support has been added to enable users to connect to Liquibase Hub (<a href="https://hub.liquibase.com">hub.liquibase.com</a>). This allows you to organize, monitor, and visualize Liquibase database change activity in real time.</p>
</li>
<li>
<p>Support has been added for additional databases, such as CockroachDB and Maria DB.</p>
</li>
<li>
<p>We've made significant changes to some important configuration and command APIs and added a new CLI library.</p>
</li>
<li>
<p>Newly added support for Liquibase Quality Checks allow you to run checks against changelogs and SQL scripts.</p>
</li>
</ol>
<p>For more information, we recommend checking out <a href="https://docs.liquibase.com/tools-integrations/extensions/extension-upgrade-guides/home.html">Liquibase Extension Upgrade Guide</a> and the <a href="https://github.com/liquibase/liquibase/releases/">release notes</a> for each major version starting with 4.x (4.1, 4.2, and so on up to 4.6).</p>
<h2>Still Not Updated to Grails Framework 5?</h2>
<p>We are excited about the recent release of Grails framework 5 and continually updating documentation and popular libraries. Now is a good time to update to Grails framework 5 and switch to Liquibase 4.</p>
<p>We would love to hear about your experience with the update to Grails Database Migration 4.0.0-RC1, and if you need any help with your upgrade, we're here to <a href="/support.html">support</a> you.</p>]]></description><author>Puneet Behl</author><guid>2021-11-23-db-migration-plugin-update</guid><pubDate>Tue, 23 Nov 2021 00:00:00 GMT</pubDate></item><item><title>Grails® 5 - Groovy Podcast Episode 84</title><link>https://grails.apache.org/blog/2021-11-11.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/podcast.html"><span class="hashtag">#podcast</span></a></p>
<p><a href="https://twitter.com/kenkousen">Ken Kousen</a> (Java Champion, NFJS speaker, serial book author) invited <a href="https://twitter.com/puneetbhl">Puneet Behl</a> (Grails Framework Development Lead) and <a href="https://twitter.com/sdelamo">Sergio del Amo</a> (2GM Developer Advocate) to join him for the latest episode of the Groovy Podcast.</p>
<p>This episode covers Grails framework 5, migrating from Grails framework 2 to Grails framework 5, Grails infrastructure, Micronaut framework integration with Grails framework, and more.</p>
<p>Listen to it in your favorite <a href="https://nofluffjuststuff.com/podcast/2/groovy_podcast_84_s05e04_with_sergio_del_amo_and_paul_king">Podcast Player</a></p>
<p><a href="https://github.com/groovy-podcast/groovypodcast/blob/master/ep-84.asciidoc">Show Notes</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/b3EVczHSPy0" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2021-11-11</guid><pubDate>Thu, 11 Nov 2021 00:00:00 GMT</pubDate></item><item><title>Grails framework 5 GA Released</title><link>https://grails.apache.org/blog/2021-10-11-grails-5-ga.html</link><description><![CDATA[</p>
<p>The Grails Foundation™ is excited to announce the GA release of Grails framework 5!</p>
<h2>Overview</h2>
<p>This release includes <a href="https://groovy-lang.org/releasenotes/groovy-3.0.html">Apache Groovy 3</a>, <a href="https://micronaut.io/2021/08/18/micronaut-framework-3-released/">Micronaut framework 3</a>, <a href="https://docs.gradle.org/7.0/release-notes.html">Gradle 7</a>, <a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes">Spring Boot 2.5</a>, <a href="https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-5.x#upgrading-to-version-53">Spring framework 5.3</a>, and <a href="https://spockframework.org/spock/docs/2.0/release_notes.html">Spock 2.0</a>.</p>
<h3>Apache Groovy 3</h3>
<p>Apache Groovy 3 is a major highlight of this release. It comes with a brand new Parrot parser and a bunch of new features and capabilities.</p>
<p>The Parrot parser supports additional syntax and language features, such as lambda expressions, default methods with interfaces, and a lot more. In addition, several new extension methods are added to existing Java classes. See the release notes for Groovy 3.0 for details.</p>
<p>Grails framework 5 is built with Groovy 3.0.7, which requires JDK 8 as the minimum version of JRE. We have tested most Grails projects up to JDK 14.</p>
<h3>Spring Upgrade</h3>
<p>Grails framework 5 updates to Spring 5.3.10 and Spring Boot 2.5.5. We strongly recommend checking the following Spring technologies release notes for more information.</p>
<ul>
<li><a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes">Spring Boot 2.5</a></li>
<li><a href="https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-5.x#upgrading-to-version-53">Upgrading to Spring Framework 5.3</a></li>
</ul>
<h2>Important Changes</h2>
<h3>Deprecating ‘dot’-Based Navigation</h3>
<p>The ‘dot’-based navigation to Grails config is deprecated and will be removed in future.</p>
<p>We request that you update your plugins to use configuration beans <code>@ConfigurationProperties</code> or <code>@Value</code>, or access configuration settings using <code>grailsApplication.config.getProperty(‘a.b.c’, String)</code> instead of <code>grailsApplication.config.a.b.c</code>.</p>
<h3>Default Autowire By Type in Data Services</h3>
<p>In previous versions, the beans inside the Grails DataService were autowire by name, but this is changed to autowire by type in Grails framework 5. Use the Spring <code>@Qualifier</code> annotation to autowire by name. For details, see the Spring documentation for <a href="https://docs.spring.io/spring-framework/docs/5.3.10/reference/html/core.html#beans-autowired-annotation-qualifiers">Fine-tuning Annotation Based Autowiring with Qualifiers</a>.</p>
<h3>Grails Gradle Plugin</h3>
<p>The <a href="https://github.com/apache/grails-gradle-plugin">Grails Gradle Plugin</a> is moved out of grails-core and may follow separate versioning, so you should decouple the <code>grailsVersion</code> Gradle property from <code>grailsGradlePluginVersion</code> in existing applications.</p>
<h3>Grails Gradle Publish Plugin Removed</h3>
<p>The Grails Gradle Publish plugin used the Bintray API to publish artifacts. However, after the JFrog shutdown of Bintray, this stopped working. We have removed this plugin from the new Grails Plugin applications.</p>
<h2>Get Started with Grails Framework 5</h2>
<h3>Download</h3>
<p>The easiest way to <a href="/download.html">get started</a> is to use SDKMAN! (The Software Development Kit Manager) to download Grails framework 5.0.0. Alternatively, you can download the Grails binary directly from <a href="/download.html">Download Page</a>.</p>
<h3>Upgrade</h3>
<p>For applications on Grails framework 4, it should be an easy upgrade, as there are not many API changes in Grails
framework 5. Also, most Grails framework 4 plugins should work just fine, unless they are using specific Spring, Spring Boot, or Groovy APIs that have been changed or removed.</p>
<p>For members of the <a href="/plugins.html">Grails plugin</a> community, now is the time to upgrade your plugins and verify they continue to work.</p>
<h2>The Road Ahead</h2>
<p>In the upcoming months, we will be working on improvements in the Grails CLI, <a href="https://guides.grails.org/index.html">Grails Guides</a>, and the <a href="/documentation.html">Grails documentation</a> around Micronaut integration.</p>
<h2>Thank You</h2>
<p>Community involvement is vital for the success of Grails framework. We appreciate the Grails community for the support and feedback throughout this journey. We are excited about this latest release. Please, upgrade your applications to Grails framework 5. We would love to hear about your experience, and if you need any help with your upgrade, we are here to <a href="/support.html">support</a> you.</p>]]></description><author>Puneet Behl</author><guid>2021-10-11-grails-5-ga</guid><pubDate>Mon, 11 Oct 2021 00:00:00 GMT</pubDate></item><item><title>New Developer Advocate Announced</title><link>https://grails.apache.org/blog/2021-10-08-developer-advocate-announced.html</link><description><![CDATA[</p>
<p>The <a href="https://micronaut.io/foundation/">Micronaut</a> and Grails Foundations™ are excited to announce that Sergio del Amo Caballero has taken on a new role and new responsibilities as the 2GM Developer Advocate!</p>
<p>The Foundations support the technical innovation and advancement of the Grails<sup>®</sup> and <a href="https://micronaut.io/">Micronaut</a><sup>®</sup> frameworks for our growing global community, and the creation of this new position is one more way we are investing in the continued success of our open source products. As Developer Advocate, Sergio will represent developer interests while engaging with our communities to evangelize the Frameworks.</p>
<p>In seeking the right person to fill the Developer Advocate position, we looked for an individual with passion for the technology who also has a strong connection with both the development team and the community at large.</p>
<blockquote>
<p>&quot;Sergio has been a major contributor to Grails and Micronaut for years. He is well known and respected in the community and is passionate about sharing information with others. I'm so excited about Sergio taking on this role and can't wait to see all of the ways that our OSS communities grow and evolve over the coming months and years.&quot;</p>
</blockquote>
<p style="text-align:right;">—Jason Schindler, 2GM Team Manager</p>
<p>Sergio discovered the Grails framework ten years ago and has been a core member of the 2GM (Groovy, Grails, and Micronaut) team at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) since 2017, during which time he has been instrumental in efforts to enhance and refine the Frameworks. He has also established a strong rapport with community members through his leadership of <a href="https://micronaut.io/guides/">Guides</a> publication, regular speaking engagements at events around the world, his personal blog, the <a href="https://groovycalamari.com/">Groovy Calamari</a> newsletter, and his enthusiasm for leading educational webinars and training courses on behalf of OCI. Sergio steps into his new position with many ideas to help expand the Frameworks' web presence and accessibility to a larger audience.</p>
<p>&quot;There are still many things that we can do to improve developer experience with the Frameworks, from people just discovering them to teams using them in their production applications. I think this is what the Frameworks need, and I have ideas about how we can support the community. This new role will allow me to do that. I'm excited about helping users unleash their productivity. The community will fulfill the rest of the deal by building amazing applications,&quot; said Sergio.</p>
<blockquote>
<p>“Sergio's strength as a technologist is matched by his genuine passion for the community. He really and truly embraces our core principle, All Of Us Is Better Than Any Of Us. His taking on this role is a tremendous win for the technology and for the community.”</p>
</blockquote>
<p style="text-align:right;">—Jeff Scott Brown, Object Computing Partner, Grails and Micronaut Foundation Co-Founder</p>
<p>Please join us in congratulating Sergio, and stay tuned for the exciting projects he's already started developing for the community!</p>]]></description><author>Jen Wiese</author><guid>2021-10-08-developer-advocate-announced</guid><pubDate>Fri, 08 Oct 2021 00:00:00 GMT</pubDate></item><item><title>2GM Q3 Town Hall Meeting: 2021 Q3</title><link>https://grails.apache.org/blog/2021-09-24-q3-town-hall-meeting.html</link><description><![CDATA[</p>
<p>A big thanks to everyone who joined us for our Q3 2GM Town Hall Meeting! For those of you who missed the live event, the recording is embedded below.</p>
<p>At this quarter's meeting, we provided an update on the latest advancements with the Grails and Micronaut frameworks, including a look at what is coming soon. We also shared the latest news and sponsors of the Grails and Micronaut Foundations, as well as some great live discussions and Q&amp;A with our panel.</p>
<p>A special thanks to our fantastic panel of experts: Jeff Scott Brown, James Kleeh, Puneet Behl, Sergio del Amo Caballero, and our awesome guest Tim Berglund.</p>
<p>Till next time!</p>
<p>— Jen Wiese</p>
<p><a href="https://objectcomputing.com/download_file/5342">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/bG89gtyVPP8" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2021-09-24-q3-town-hall-meeting</guid><pubDate>Fri, 24 Sep 2021 00:00:00 GMT</pubDate></item><item><title>Webinar: An Insider's Guide to Groovy 4</title><link>https://grails.apache.org/blog/2021-09-17-groovy-4-webinar.html</link><description><![CDATA[</p>
<p>Apache Groovy 4 is nearing release, and it's been improved in a number of areas for greater simplicity and efficiency.</p>
<p>Join Object Computing Groovy Practice Lead, <a href="https://objectcomputing.com/products/2gm-team#king">Paul King</a>, as he shares an overview of the exciting new features you'll find in Groovy 4, including JDK17 support, switch expressions, annotations on type parameters, enhanced ranges, and support for sealed classes, records, and language-integrated queries. He'll also introduce you to Groovy 4's additional bundle type checkers, macro methods, and design-by-contract support so you can specify preconditions, postconditions, and invariants.</p>
<p>This complimentary 60-minute webinar prepares Groovy users of all proficiency levels to take advantage of the new features Groovy 4 offers.</p>
<p><a href="https://objectcomputing.com/download_file/5328">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/H027QTB_5MM" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2021-09-17-groovy-4-webinar</guid><pubDate>Fri, 17 Sep 2021 00:00:00 GMT</pubDate></item><item><title>2GM Q3 Town Hall Meeting Coming Soon</title><link>https://grails.apache.org/blog/2021-09-15-q3-town-hall-meeting-scheduled.html</link><description><![CDATA[</p>
<p>Our 2021 third-quarter Town Hall Meeting is just around the corner!</p>
<p>2GM Town Hall Meetings give the Groovy, Grails, and Micronaut team a chance to engage with you and empower you to contribute to the frameworks you love. Each Town Hall Meeting is led by a panel of 2GM users, developers, and advocates, and everyone is welcome and encouraged to participate.</p>
<p>We look forward to seeing you on September 24th, where we'll be sharing an update on our Productivity Tips 'n' Tricks guide, chatting about the latest technology releases, and more!</p>
<p><a href="https://us02web.zoom.us/webinar/register/7816317393035/WN_KbJAjtyMR8m56mzMroahEw">Reserve your seat</a></p>]]></description><author>Jen Wiese</author><guid>2021-09-15-q3-town-hall-meeting-scheduled</guid><pubDate>Wed, 15 Sep 2021 00:00:00 GMT</pubDate></item><item><title>Grails Deep Dive Training Class Scheduled</title><link>https://grails.apache.org/blog/2021-09-02-grails-deep-dive.html</link><description><![CDATA[</p>
<p>If you've been wishing you could learn to maximize your productivity with the Grails framework directly from a member of the core Grails development team, this is your chance! A public offering of our popular Grails Deep Dive course starts next week.</p>
<p>This 4-day, 12-hour in-depth training workshop provides developers the knowledge and skills they need to quickly master the Grails framework. Become proficient with the technology in just a few days through live, instructor-led, hands-on training.</p>
<p><a href="https://objectcomputing.com/services/training/catalog/grails/grails-deep-dive">Learn more and enroll</a></p>]]></description><author>Jen Wiese</author><guid>2021-09-02-grails-deep-dive</guid><pubDate>Thu, 02 Sep 2021 00:00:00 GMT</pubDate></item><item><title>Groovy 4 Webinar Coming Soon</title><link>https://grails.apache.org/blog/2021-08-25-groovy-4-webinar.html</link><description><![CDATA[</p>
<p>Object Computing Groovy Project Lead, <a href="https://objectcomputing.com/products/2gm-team">Paul King</a>, presents a complimentary 60-minute webinar on September 16th in which he introduces the features and improvements you can expect in Apache Groovy 4.</p>
<p><a href="https://us02web.zoom.us/webinar/register/2816299174731/WN_pGeF4yuSRHaiBNajcDkUcA">Register here</a> to join the webinar live or to receive an email notification when the recording is available on YouTube.</p>]]></description><author>Jen Wiese</author><guid>2021-08-25-groovy-4-webinar</guid><pubDate>Wed, 25 Aug 2021 00:00:00 GMT</pubDate></item><item><title>Grails 5.0.0 RC1 Released</title><link>https://grails.apache.org/blog/2021-08-12-grails-5-rc1-release.html</link><description><![CDATA[</p>
<p>The Grails® Foundation is pleased to announce the first release candidate of <a href="https://github.com/apache/grails-core/releases/tag/v5.0.0.RC1">Grails framework 5.0.0</a>! With this release, we are one step closer to the Grails framework's next GA release!</p>
<h2>Overview</h2>
<p>Grails framework 5 represents a significant upgrade, with the Framework now rebased on top of an updated minimum set of dependencies including:</p>
<ul>
<li>Spring 5.3.9</li>
<li>Spring Boot 2.5.3</li>
<li>Apache Groovy 3</li>
<li>Hibernate 5.5</li>
<li>Gradle 6.9</li>
</ul>
<p>A major highlight of Grails framework 5 is support for Apache Groovy 3, which comes with the brand new Parrot parser and a bunch of new features and capabilities. The Parrot parser supports additional syntax and language features, such as lambda expressions, default methods with interfaces, and a lot more. See <a href="https://groovy-lang.org/releasenotes/groovy-3.0.html#releasenotes">the release notes for Groovy 3.0</a> for details.</p>
<p>Grails framework 5 also upgrades to Spring 5.3.9 and Spring Boot 2.5.3, which have a minimum Gradle requirement of 6.8 or later and a default Apache Groovy version of 3. We strongly recommend that users check out the following Spring technologies release notes for more information:</p>
<ul>
<li><a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.5-Release-Notes">Spring Boot 2.5</a></li>
<li><a href="https://github.com/spring-projects/spring-framework/wiki/Upgrading-to-Spring-Framework-5.x#upgrading-to-version-53">Spring Framework 5.3</a></li>
</ul>
<p>This release also provides support for Java 15.</p>
<p>Many Grails plugins should work with Grails framework 5. For those in the Grails plugin community, now is the time to upgrade your plugins and verify they continue to work with Grails framework 5.</p>
<h2>Important Changes</h2>
<ul>
<li>Dot-based(a.b.c) access to config is deprecated and will be removed in future.</li>
<li>The grails-publish-plugin has been removed.</li>
<li>The grails-gradle-plugin has been moved out of grails-core and may follow a separate versioning from grailsCore, so you should decouple the grailsVersion Gradle property from grailsGradlePluginVersion in existing applications.</li>
<li><code>grails.util.Metadata</code> includes breaking changes as part of improvements.</li>
</ul>
<h2>Download</h2>
<p>The easiest way to get started is to use <a href="https://sdkman.io/">SDKMAN! (The Software Development Kit Manager)</a> to download Grails 5.0.0.RC1.
Alternatively, you could download the Grails Binary directly from the <a href="https://github.com/apache/grails-core/releases/download/v5.0.0.RC1/grails-5.0.0.RC1.zip">Github Release</a> page.</p>
<h2>Conclusion</h2>
<p>Thanks to all those who contributed to this release. Please <a href="https://twitter.com/grailsframework">follow us on Twitter @grailsframework</a> for the most up-to-date information on the framework.</p>]]></description><author>Puneet Behl</author><guid>2021-08-12-grails-5-rc1-release</guid><pubDate>Wed, 11 Aug 2021 00:00:00 GMT</pubDate></item><item><title>Calling All 2GM Users: Share Your Productivity Tips</title><link>https://grails.apache.org/blog/2021-07-20-call-for-productivity-tips.html</link><description><![CDATA[</p>
<h2>We're all about sharing it back.</h2>
<p>The Object Computing Groovy, Grails, and Micronaut team is collecting tips to compile into a resource that the global developer community can benefit from. By sharing your tips, you can help your peers build better solutions, making all of us stronger.</p>
<h2>What’s your go-to productivity tool or technique?</h2>
<p>No idea is too small! The little tips are often the things that add up to make the biggest difference. Bonus points if the trick isn't documented anywhere – you may be the first person to figure something out!</p>
<p>Highlights from your submissions will be shared with the 2GM community. This is a great chance to help your fellow developers improve their skills ... and who knows? Maybe you'll also win some cool swag!</p>
<h2>Ready to participate?</h2>
<p><a href="https://objectcomputing.typeform.com/to/j0BdcprA">Head over to this link</a> and give us a peek inside your bag of tricks by sharing executable code, representative code snippets, or prose describing any practical tips you rely on to write better code faster.</p>
<p>Multiple submissions are welcome; we just ask that you have all your ideas submitted by August 31st.</p>
<p>We can’t wait to see all of the cool tips and tricks you've come up with!</p>]]></description><author>Jen Wiese</author><guid>2021-07-20-call-for-productivity-tips</guid><pubDate>Tue, 20 Jul 2021 00:00:00 GMT</pubDate></item><item><title>Updated Grails Wrapper for Grails 3 and 4 projects</title><link>https://grails.apache.org/blog/2021-06-10-grails-wrapper-update.html</link><description><![CDATA[</p>
<p>Recently, the Grails Framework Artifactory instance was updated. As a result, the Grails wrapper now fails under certain conditions because the URL it uses to retrieve information is no longer supported.</p>
<p>We are preparing a patch release of Grails framework 4 and Grails framework 3 to make new applications work with the change, but for existing Grails framework 3 and Grails framework 4 applications, the <code>grailsw</code> command will fail if the necessary assets haven't already been cached on the machine.</p>
<p>The error received is:</p>
<pre><code>You must be connected to the internet the first time you use the Grails wrapper
org.xml.sax.SAXParseException; lineNumber: 6; columnNumber: 3; The element type &quot;hr&quot; must be terminated by the matching end-tag &quot;&lt;/hr&gt;&quot;.

</code></pre>
<h2>Updating Existing Projects</h2>
<p>To fix this, replace the <code>grails-wrapper.jar</code> file in the base of your existing project with one of the updated wrappers below:</p>
<ul>
<li><a href="/files/wrapper-issue7/grails3/grails-wrapper.jar">Updated grails-wrapper.jar for Grails 3 Projects</a> <a href="/files/wrapper-issue7/grails3/grails-wrapper.jar.md5">(MD5)</a></li>
<li><a href="/files/wrapper-issue7/grails4/grails-wrapper.jar">Updated grails-wrapper.jar for Grails 4 Projects</a> <a href="/files/wrapper-issue7/grails4/grails-wrapper.jar.md5">(MD5)</a></li>
</ul>
<p>Running the <code>grailsw</code> command from within the project should now work as expected.</p>
<h2>Changing Repository URL</h2>
<p>In addition to fixing the URL, we have also added the ability to change the base URL that the wrapper uses.</p>
<p>There are two possible mechanisms for doing this:</p>
<ul>
<li>Setting an environment variable named <code>GRAILS_CORE_ARTIFACTORY_BASE_URL</code></li>
<li>Setting the <code>grails.core.artifactory.baseUrl</code> system property</li>
</ul>
<p>The default value is <code>https://repo.grails.org/grails/core</code>, and we do not expect that to change.</p>
<h2>Wrapping Up</h2>
<p>We apologize for any inconvenience you may have experienced by this recent change. We will post a more detailed post-mortem on these events in the next few days. Please continue to report <a href="https://github.com/apache/grails-core/issues">any issues</a> you encounter.</p>]]></description><author>Jason Schindler</author><guid>2021-06-10-grails-wrapper-update</guid><pubDate>Thu, 10 Jun 2021 00:00:00 GMT</pubDate></item><item><title>2GM Town Hall Meeting: 2021 Q2</title><link>https://grails.apache.org/blog/2021-05-21-2gm-town-hall-q2.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/townhall.html"><span class="hashtag">#townhall</span></a></p>
<p>A big thanks to everyone who joined us for our Q2 2GM Town Hall Meeting! For those of you who missed the live event, the recording is embedded below.</p>
<p>At this quarter's meeting, we shared updates regarding the Grails and Micronaut roadmaps, discussed changes to the Micronaut Guides, talked about how to become a sponsor of the Grails and Micronaut Foundations, and encouraged qualified community members to apply to join the 2GM engineering team! You can find all of Object Computing's open positions <a href="https://jobs.lever.co/oci">here</a>.</p>
<p>Also, special thanks to our fantastic panel of experts: Jeff Scott Brown, David Estes, Iván López, and Graeme Rocher.</p>
<p>Till next time!</p>
<p>— Jen Wiese</p>
<p><a href="https://objectcomputing.com/download_file/5201">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/_kmMsoVt32M" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2021-05-21-2gm-town-hall-q2</guid><pubDate>Fri, 21 May 2021 00:00:00 GMT</pubDate></item><item><title>How to Publish a Grails Plugin to the Maven Central Repository</title><link>https://grails.apache.org/blog/2021-04-07-publish-grails-plugin-to-maven-central.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/bintray.html"><span class="hashtag">#bintray</span></a> <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
<p>Beginning May 1, 2021, you will <a href="/blog/2021-02-12-alerts-regarding-bintray-sunset.html">no longer be able to publish your Grails plugins/artifacts to JFrog Bintray</a>. We have already copied most of the Grails plugins from JFrog Bintray to the <a href="https://repo.grails.org">Grails Artifactory</a>, which allows us to resolve those artifacts. Going forward, we recommend that you start publishing artifacts to Maven Central.</p>
<p>In this post, we outline how to publish Grails plugins to Maven Central. For detailed information, we also suggest checking <a href="https://central.sonatype.org/publish/publish-guide/">Sonatype OSSRH Guide</a>.</p>
<p>The Sonatype’s OSSRH service is the primary place to publish plugins to the Central repository. In order to use OSSRH, you need to take care of a few prerequisites and follow some basic steps.</p>
<h2>Prerequisites</h2>
<ol>
<li>
<h3>Choose your coordinates</h3>
<p>When publishing Grails plugins to Bintray, it was possible to publish under the same groupId (org.grails.plugins).</p>
<p>To publish to Sonatype, the groupID needs to be changed.</p>
<ol>
<li>If your plugins are hosted on GitHub, you could use &quot;io.github.yourusername&quot;, &quot;io.github.yourorganization&quot;, etc. For example: &quot;io.github.puneetbehl&quot;, where &quot;puneetbehl&quot; is my GitHub username.</li>
<li>If you own or manage a domain then you could use groupId starting with the reverse domain name.</li>
</ol>
<p>Please note that there is a Sonatype validation process to verify that you own the GitHub username or control the domain. See <a href="https://central.sonatype.org/publish/#individual-projects-open-source-software-repository-hosting-ossrh">Individual Projects - Open Source Software Repository Hosting (OSSRH)</a> for more information.</p>
</li>
<li>
<h3>Sign up and provide project details</h3>
<p>Once you identify a groupId, claim your namespace on the central repository.</p>
<ol>
<li>Sign up on <a href="https://issues.sonatype.org/secure/Signup!default.jspa">Sonatype JIRA</a>.</li>
<li>Provide project details by creating a new project ticket.
<ol>
<li>Create a new Issue in the &quot;Community Support - Open Source Project Repository Hosting&quot; project.</li>
<li>The issue type should be &quot;New Project&quot;.</li>
<li>On the Project Details page, enter basic project details. See the screenshot below for an example:
<img src="2021-04-07-img01.png" alt="" />
<strong>NOTE:</strong> Once the ticket is resolved, you should be good to deploy your artifacts.</li>
</ol>
</li>
</ol>
</li>
<li>
<h3>Make sure your project meets the minimum requirements</h3>
<p>When publishing to the central repository, your project must meet a basic set of metadata and content requirements. Even though metadata will be generated with Gradle plugins, it is useful to understand it.</p>
<ol>
<li>
<h4>Javadoc and Sources</h4>
<p>Verify that your plugin supplies javadoc and sources. For example, if your plugin name is myplugin then it should also package &quot;myplugin-1.0.0-sources.jar&quot; and &quot;myplugin-1.0.0-javadoc.jar&quot;.</p>
</li>
<li>
<h4>Sign Files with GnuPG/PGP</h4>
<p>All files must be signed with GnuPG/PGP, and an &quot;.asc&quot; file containing the signature must be included for each file. For example, when you deploy, the following files must be included:</p>
<ul>
<li>myplugin-1.0.0.pom</li>
<li>myplugin-1.0.0.jar</li>
<li>myplugin-1.0.0-sources.jar</li>
<li>myplugin-1.0.0-javadoc.jar</li>
<li>myplugin-1.0.0.pom.asc</li>
<li>myplugin-1.0.0.jar.asc</li>
<li>myplugin-1.0.0-sources.jar.asc</li>
<li>myplugin-1.0.0-javadoc.jar.asc</li>
</ul>
</li>
<li>
<h4>Metadata</h4>
<p>Ensure that the POM file contains the following metadata:</p>
<ul>
<li>Project coordinates - groupId, artifactId, version</li>
<li>Project name, description, and URL</li>
<li>Declare license</li>
<li>Developer information</li>
<li>SCM information</li>
</ul>
<p>You can refer to the <a href="https://central.sonatype.org/publish/requirements/">Sonatype Requirements</a> page for more information.</p>
</li>
<li>
<h4>Install GnuPG, and Distribute Your Public Key</h4>
<p>One of the requirements for publishing to the central repository is to sign your artifacts using GnuPG. To install it, please read the instructions <a href="https://central.sonatype.org/publish/requirements/gpg/">here</a>.</p>
<p>After generating the GnuPG key, distribute your public key to the key server so others can use it to verify your files. See <a href="https://central.sonatype.org/publish/requirements/gpg/#distributing-your-public-key">Distributing Your Public Key Section</a>.</p>
<p>You may receive an error from Sonatype stating that the signature could not be verified.  The error message will list the key servers that it is checking. You may need to distribute your key to another server (for example: http://keyserver.ubuntu.com:11371) in order for Sonatype to validate the artifacts.</p>
</li>
</ol>
</li>
</ol>
<h2>Publishing</h2>
<p>In order to deploy your plugin artifacts to OSSRH, you must meet the requirements for metadata in the POM and sign the artifacts. But first, let’s remove the previous Grails plugin, which was used to upload artifacts to JFrog Bintray.</p>
<p>The previous Grails plugin is configured with &quot;grails-plugin-publish&quot;, which uses a Gradle Bintray plugin to upload artifacts.</p>
<p>Delete the following lines from your project build.gradle file to remove the plugin:</p>
<pre><code class="language-groovy">apply plugin:&quot;org.grails.grails-plugin-publish&quot;

grailsPublish {
   user = 'user'
   key = 'key'
   githubSlug = 'foo/bar'
   license {
       name = 'Apache-2.0'
   }
   title = &quot;My Plugin&quot;
   desc = &quot;Full plugin description&quot;
   developers = [johndoe:&quot;John Doe&quot;]
}
</code></pre>
<ol>
<li>
<h3>Generating Metadata</h3>
<p>Use the Gradle <a href="https://docs.gradle.org/current/userguide/publishing_maven.html">maven-publish</a> plugin to generate the necessary metadata, and deploy artifacts to the repository.</p>
<ol>
<li>
<p>Apply the Maven Publish plugin</p>
<pre><code class="language-groovy">apply plugin: 'maven-publish'
</code></pre>
</li>
<li>
<p>Customize Metadata - The following sample shows how to customize the metadata for a Grails plugin:</p>
<pre><code class="language-groovy">group 'io.github.puneetbehl'
Version '1.0.0'

publishing {
   publications {
       maven(MavenPublication) {
           groupId = project.group
           artifactId = 'my-plugin'
           version = project.version

           from components.java
           artifact sourcesJar
           artifact javadocJar

           pom {
               name = 'My Grails Plugin'
               description = 'A concise description of my library'
               url = 'https://github.com/puneetbehl/myplugin'
               licenses {
                   license {
                       name = 'The Apache License, Version 2.0'
                       url = 'https://www.apache.org/licenses/LICENSE-2.0.txt'
                   }
               }
               developers {
                   developer {
                       id = 'puneetbehl'
                       name = 'Puneet Behl'
                       email = 'behlp@unityfoundation.io'
                   }
               }
               scm {
                   connection = 'scm:git:git://github.com/puneetbehl/myplugin.git'
                   developerConnection = 'scm:git:ssh://github.com:puneetbehl/myplugin.git'
                   url = 'https://github.com/puneetbehl/myplugin/tree/main'
               }
           }
       }
   }
}
</code></pre>
</li>
</ol>
</li>
<li>
<h3>Signing Artifacts</h3>
<p>Use the Gradle <a href="https://docs.gradle.org/5.0/userguide/signing_plugin.html">Signing</a> plugin to sign the artifacts, including metadata and pom.</p>
<ol>
<li>
<p>Apply the Signing Plugin</p>
<pre><code class="language-groovy">apply plugin: 'signing'
</code></pre>
</li>
<li>
<p>Provide GnuPG key Information in your build.gradle file.</p>
<pre><code class="language-groovy">ext.&quot;signing.keyId&quot; = project.hasProperty(&quot;signing.keyId&quot;) ? project.getProperty('signing.keyId') : System.getenv('SIGNING_KEY_ID')
ext.&quot;signing.password&quot; = project.hasProperty(&quot;signing.password&quot;) ? project.getProperty('signing.password') : System.getenv('SIGNING_PASSPHRASE')
ext.&quot;signing.secretKeyRingFile&quot; = project.hasProperty(&quot;signing.secretKeyRingFile&quot;) ? project.getProperty('signing.secretKeyRingFile') : (System.getenv('SIGNING_PASSPHRASE')?:&quot;${System.properties['user.home']}${File.separator}.gnupg${File.separator}secring.gpg&quot;)
</code></pre>
</li>
<li>
<p>Get Signatory Credentials</p>
<ol>
<li>Get the public key ID (The last 8 symbols using <code>gpg -K</code> command).</li>
<li>Export the keys with command <code>gpg --keyring secring.gpg --export-secret-keys &gt; ~/.gnupg/secring.gpg</code>.</li>
<li>Know the Passphrase used to protect private keys.</li>
</ol>
</li>
<li>
<p>Export the following environment variables</p>
<ol>
<li><code>SIGNING_KEY_ID</code> - The public key ID.</li>
<li><code>SIGNING_PASSPHRASE</code> - The passphrase used while generating GnuPG key.</li>
<li><code>SECRING_FILE</code> - The path to secring.gpg file.</li>
</ol>
</li>
<li>
<p>Sign the artifacts and also prevent signing snapshots by adding required check as follows:</p>
<pre><code class="language-groovy">ext.isReleaseVersion = !version.endsWith(&quot;SNAPSHOT&quot;)

afterEvaluate {
   signing {
       required { isReleaseVersion &amp;&amp; gradle.taskGraph.hasTask(&quot;publish&quot;) }
       sign publishing.publications.maven
   }
}

tasks.withType(Sign) {
   onlyIf { isReleaseVersion }
}
</code></pre>
</li>
</ol>
</li>
<li>
<h3>Configuring A Multi-Project Build</h3>
<p>In case of multi-project builds, you need to configure plugins to generate metadata and signing for each of the sub-projects. The easiest way to achieve this is:</p>
<pre><code class="language-groovy">subprojects { project -&gt;
    // your code here
}

</code></pre>
</li>
<li>
<h3>Publish Your Artifacts to OSSRH, followed by release to Maven Central</h3>
<p>The <a href="https://plugins.gradle.org/plugin/io.github.gradle-nexus.publish-plugin">Gradle Nexus Publish Plugin</a> is used to publish your artifacts to Sonatype and then to Maven Central in a fully automated way. Check the plugin <a href="https://github.com/gradle-nexus/publish-plugin">README</a> for more information.</p>
<ol>
<li>
<p>Applying the plugin</p>
<pre><code class="language-groovy">buildscript {
   repositories {
       maven { url &quot;https://repo.grails.org/grails/core&quot; }
       maven { url &quot;https://plugins.gradle.org/m2/&quot; }
   }
   dependencies {
       classpath &quot;org.grails:grails-gradle-plugin:$grailsVersion&quot;
       classpath &quot;com.bertramlabs.plugins:asset-pipeline-gradle:3.0.10&quot;
       classpath &quot;io.github.gradle-nexus:publish-plugin:1.0.0&quot;
   }
}


apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: &quot;io.github.gradle-nexus.publish-plugin&quot;
</code></pre>
</li>
<li>
<p>To publish to Maven Central via Sonatype OSSRH, add the Sonatype repository as follows:</p>
<pre><code class="language-groovy">nexusPublishing {
   repositories {
       sonatype {
           def ossUser = System.getenv(&quot;SONATYPE_USERNAME&quot;) ?: project.hasProperty(&quot;sonatypeOssUsername&quot;) ? project.sonatypeOssUsername : ''
           def ossPass = System.getenv(&quot;SONATYPE_PASSWORD&quot;) ?: project.hasProperty(&quot;sonatypeOssPassword&quot;) ? project.sonatypeOssPassword : ''
           def ossStagingProfileId = System.getenv(&quot;SONATYPE_STAGING_PROFILE_ID&quot;) ?: project.hasProperty(&quot;sonatypeOssStagingProfileId&quot;) ? project.sonatypeOssStagingProfileId : ''
           nexusUrl = uri(&quot;https://s01.oss.sonatype.org/service/local/&quot;)
           snapshotRepositoryUrl = uri(&quot;https://s01.oss.sonatype.org/content/repositories/snapshots/&quot;)
           username = ossUser
           password = ossPass
           stagingProfileId = ossStagingProfileId
       }
   }
}
</code></pre>
<p>Please note that in case of a multi project build, you must add the configuration from steps 1 and 2 under the root project.</p>
</li>
<li>
<p>Retrieve the Sonatype Staging Profile ID</p>
<ol>
<li>Log in to <a href="https://s01.oss.sonatype.org/">https://s01.oss.sonatype.org/</a> using your Sonatype credentials.</li>
<li>Select &quot;Staging Profiles&quot; under the &quot;Build Promotions&quot; section in the left navigation panel.</li>
<li>Select the Staging Profile with name as the groupId value.</li>
<li>Copy the last part in your browser URL which is the Staging Profile ID. For example, when the browser URL is https://s01.oss.sonatype.org/#stagingProfiles;ce7c8eca12345 then profile id is &quot;ce7c8eca12345&quot; (the portion after semicolon).</li>
</ol>
</li>
<li>
<p>Export the following environment variables:</p>
<ol>
<li>SONATYPE_USERNAME - Your sonatype username</li>
<li>SONATYPE_PASSWORD - Your sonatype password</li>
<li>SONATYPE_STAGING_PROFILE_ID - The Staging Profile ID copied in the previous step</li>
</ol>
</li>
<li>
<p>Publish artifacts to the new staging repository and verify them manually.</p>
<pre><code class="language-groovy">./gradlew publishToSonatype closeSonatypeStagingRepository
</code></pre>
</li>
<li>
<p>After verifying, manually drop the staging repository.</p>
<ol>
<li>Log in to <a href="https://s01.oss.sonatype.org/">https://s01.oss.sonatype.org/</a></li>
<li>Click on &quot;Staging Repositories&quot; which is under the Build Promotion section in the left navigation.</li>
<li>Click the checkbox against the repository and select drop.</li>
</ol>
</li>
<li>
<p>Publish artifacts to the new staging repository and verify them manually.</p>
<pre><code class="language-groovy">./gradlew publishToSonatype closeAndReleaseSonatypeStagingRepository
</code></pre>
</li>
</ol>
</li>
</ol>
<h2>Automate Publishing Using GitHub Action</h2>
<p>To automatically release using GitHub Workflow, add the following <a href="https://raw.githubusercontent.com/puneetbehl/myplugin/main/.github/workflows/release.yml">.github/workflows/release.yml</a> workflow configuration file to your project.</p>
<p>When using this file, you must configure the following GitHub Secrets:</p>
<ol>
<li>SONATYPE_USERNAME</li>
<li>SONATYPE_PASSWORD</li>
<li>SONATYPE_STAGING_PROFILE_ID</li>
<li>SIGNING_KEY</li>
<li>SIGNING_PASSPHRASE</li>
<li>SECRING_FILE - This is a BASE64 encoded value. Run the command <code>gpg --keyring ~/.gnupg/pubring.kbx --export-secret-keys &gt; ~/.gnupg/secring.gpg &amp;&amp; base64 ~/.gnupg/secring.gpg | pbcopy</code> to copy BASE64 encoded value to the clipboard.</li>
</ol>
<p>To trigger a release, create a new release from the GitHub releases page. Here is a sample <a href="https://github.com/puneetbehl/myplugin">Grails Plugin</a> that's configured to publish to Maven Central.</p>
<h2>Update Information on Grails Plugin Portal</h2>
<p>The <a href="/plugins.html">Grails Plugin Portal</a> uses the <a href="https://raw.githubusercontent.com/grails/grails-plugins-metadata/main/grails-plugins.json">grails-plugins.json</a> metadata file to display plugin information.</p>
<p>The metadata is hosted at <a href="https://github.com/apache/grails-plugins-metadata/blob/main/grails-plugins.json">https://github.com/apache/grails-plugins-metadata/blob/main/grails-plugins.json</a>. When you publish a new plugin or release an existing plugin, you must send a pull request to this file to update the information on the portal.</p>
<ol>
<li>
<p>When you release a new plugin, add the following information at the end of the JSON file:</p>
<pre><code class="language-groovy">{
    &quot;bintrayPackage&quot;: {
        &quot;name&quot;: &quot;My Plugin&quot;,
        &quot;repo&quot;: &quot;plugins&quot;,
        &quot;owner&quot;: &quot;puneetbehl&quot;,
        &quot;desc&quot;: &quot;A concise description&quot;,
        &quot;labels&quot;: [
                &quot;grails3&quot;,
                &quot;spring-boot&quot;,
                &quot;test-label&quot;
        ],
        &quot;licenses&quot;: [
                &quot;Apache-2.0&quot;
        ],
        &quot;issueTrackerUrl&quot;: &quot;https://github.com/puneetbehl/myplugin/issues&quot;,
        &quot;latestVersion&quot;: &quot;1.1&quot;,
        &quot;updated&quot;: &quot;2021-03-25T04:00:40.855Z&quot;,
        &quot;systemIds&quot;: [
                &quot;io.github.puneetbehl:myplugin&quot;
        ],
        &quot;vcsUrl&quot;: &quot;https://github.com/puneetbehl/myplugin&quot;
    }
    &quot;documentationUrl&quot;: &quot;https://puneetbehl.github.io/myplugin/&quot;,
    &quot;mavenMetadataUrl&quot;: &quot;https://repo1.maven.org/maven2/com/github/puneetbehl/myplugin/maven-metadata.xml&quot;,
} 
</code></pre>
</li>
<li>
<p>If you publish a new version to Maven Central, locate the entry in the JSON file and updatelatestVersion and mavenMetadataUrl. This will reflect the latest version in the plugin portal. In the future, we will use the mavenMetadataUrl field to automatically update the latest version.</p>
</li>
</ol>]]></description><author>Puneet Behl</author><guid>2021-04-07-publish-grails-plugin-to-maven-central</guid><pubDate>Wed, 07 Apr 2021 00:00:00 GMT</pubDate></item><item><title>Meet the Grails® Framework's New Mascot, Sir Gideon of Grails!</title><link>https://grails.apache.org/blog/2021-03-22-meet-the-new-mascot.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/mascot.html"><span class="hashtag">#mascot</span></a></p>
<p>In February 2021, we introduced the Grails framework's brand new mascot and reached out to our community to give the knight a name. The winner had a chance to win a one-of-a-kind Grails swag bag (and bragging rights, of course).</p>
<p>We were absolutely delighted to see the creativity, enthusiasm, and support the Grails community contributed to our quest. We received an amazing number of responses with some super imaginative suggestions.</p>
<p>So, the community has voted, and the Grails mascot has been named!</p>
<p>And the knight's new name is …</p>
<p>[Drumroll please …]</p>
<p>Gideon!</p>
<p><img src="2021-03-22-gideon-hello-world.png" alt="Meet Sir Gideon of Grails" /></p>
<p>The name Gideon was overwhelmingly the top pick. Since multiple people suggested the name, we drew several winners from those entries to receive a swag bag. Please join me in congratulating winners: Joshua Freivald, Joe Little, and Benjamin Suffin! And if you were one of the many people who suggested we name the knight Gideon who didn't win a swag bag, please feel free to enjoy the bragging rights. Every time you see Sir Gideon out there, you'll know you were part of his &quot;Hello World&quot; development.</p>
<p>Huge thanks to everyone who took part in the Name the Knight contest. Even if your name wasn't chosen, your  participation reminded us just how much we love and appreciate the Grails community.</p>]]></description><author>Jen Wiese</author><guid>2021-03-22-meet-the-new-mascot</guid><pubDate>Mon, 22 Mar 2021 00:00:00 GMT</pubDate></item><item><title>Important Information Regarding Grails and Bintray</title><link>https://grails.apache.org/blog/2021-02-12-alerts-regarding-bintray-sunset.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/bintray.html"><span class="hashtag">#bintray</span></a> <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
<p>As many of you know, last week JFrog <a href="https://jfrog.com/blog/into-the-sunset-bintray-jcenter-gocenter-and-chartcenter/">announced</a> that they are sunsetting JCenter and Bintray. On March 31st, JCenter will no longer accept new package submissions, but it will continue to serve artifacts until February 1st of 2022. On May 1, 2021, Bintray will be shut down. After May 1st, artifacts hosted by Bintray and the Bintray API will not be available.</p>
<p>This has a large impact on the Grails community, as we have been using Bintray for quite some time to host a number of our artifacts, as well as the community plugins under the <code>org.grails.plugins</code> group ID. Additionally, the <a href="/plugins.html">Grails Plugins Portal</a> utilizes the Bintray API to retrieve needed metadata to list and search plugins.</p>
<p>We have a plan, but it is going to require some lifting.</p>
<h2>Moving Existing Artifacts Out of Bintray</h2>
<p>Our primary concern is making sure existing artifacts can still be resolved after Bintray is shut down on May 1st.  In order to achieve this, we will be moving existing artifacts including community plugins from Bintray to the Grails <a href="https://repo.grails.org/">Artifactory instance</a>. JFrog is not shutting down Artifactory and will continue to support our instance. This should allow existing artifacts to be served from Artifactory once Bintray is shut down, and current Grails applications should continue to have access to the artifacts and plugins that they need that are in our control.</p>
<h2>Updating Grails Plugins Portal</h2>
<p>As mentioned earlier, the Grails Plugins Portal is currently backed by the Bintray API. On May 1st, that API will be shut down with the rest of Bintray, so we need an alternative. We will create a public repository on GitHub that will host the metadata needed by the Grails Plugins Portal and can be managed by the community. Our intent is that this repository will periodically scan for updated release information and modify the metadata that the Grails Plugins Portal requires. This is a work in progress. We will announce more details about this process in the near future.</p>
<h2>Publishing Community Plugins</h2>
<p>Unfortunately, the loss of Bintray will require some extra effort from community plugin authors when you publish your next release.</p>
<p>First, you will no longer be able to publish to Bintray, and you will no longer be able to use the <code>org.grails.plugins</code> group. Community access to the <code>org.grails.plugins</code> group was a benefit of using Bintray that we cannot easily recreate. We could grant community plugin authors access to the Grails Artifactory instance, but doing so would create substantial user management overhead. It would also more tightly couple Grails to our JFrog Artifactory instance.</p>
<p>We feel a better solution is to maintain the plugin list publicly in a GitHub repository, and for plugin authors to publish their artifacts to another repository. Fortunately, community plugin authors have some options on where to publish their artifacts. We strongly suggest that folks publish to Maven Central. There is some extra overhead in publishing there, but we feel it is the safest bet for future availability of our artifacts.</p>
<p>The “grails-plugin-publish” Gradle plugin will no longer be able to publish Grails community plugins, as it supports publishing to Bintray with the <a href="https://github.com/bintray/gradle-bintray-plugin">gradle-bintray-plugin</a>. To publish to Maven Central, we recommend that plugin authors switch to the <a href="https://docs.gradle.org/current/userguide/publishing_maven.html">Gradle Maven Publish</a> plugin instead. We will be exercising this process ourselves in the coming days and will provide more details and guidance in the very near future.</p>
<h2>Grails 5 Delay</h2>
<p>Over the next few weeks, we will be focusing our efforts on this migration, and that is likely to cause a delay in the Grails 5 release. We want to wrap this up as quickly as possible so that we can get back to work on Grails 5!</p>
<h2>Moving Forward</h2>
<p>Thank you to all of you for your continued participation in the Grails community. We know that some of the changes resulting from this will be frustrating, and we ask for your patience as we work through this migration.</p>]]></description><author>Jason Schindler</author><guid>2021-02-12-alerts-regarding-bintray-sunset</guid><pubDate>Fri, 12 Feb 2021 00:00:00 GMT</pubDate></item><item><title>Webinar: 2GM TOWN HALL MEETING: 2021 Q1</title><link>https://grails.apache.org/blog/2021-02-05-2gm-town-hall-q1.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/townhall.html"><span class="hashtag">#townhall</span></a></p>
<p>A big thanks to everyone who joined us for our first 2GM Town Hall of 2021!  We had a great time and learned about several exciting goings on within the Groovy, Grails, and Micronaut communities. For those of you who missed the live event, the recording is embedded below.</p>
<p>I would like to take this opportunity to thank our awesome panel of experts:</p>
<p>James Kleeh, Micronaut Development Lead
Puneet Behl, Grails Development Lead
Paul King, Groovy Development Lead
Plus, our guest panelist, Graeme Rocher, Architect at Oracle</p>
<p>Stay tuned for details about our next 2GM Town Hall meeting.</p>
<p><a href="https://objectcomputing.com/download_file/5088">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/j7sf8G63OrI" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2021-02-05-2gm-town-hall-q1</guid><pubDate>Fri, 05 Feb 2021 00:00:00 GMT</pubDate></item><item><title>Grails Framework Exciting Updates</title><link>https://grails.apache.org/blog/2021-01-22-grails-exciting-updates.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/grails.html"><span class="hashtag">#grails</span></a></p>
<p>We wish everyone a healthy and happy new year 2021 and thank all our users and contributors for your love and support of the Grails framework. We are excited to announce some of the upcoming changes around Grails releases, which will benefit the community and help with maintainability.</p>
<h2>Adoption of Semantic Versioning</h2>
<p>Starting with version 4.0.0, the Grails framework is following semantic versioning 2.0.0 to make the release process more predictable and simple. To understand what that means, please see <a href="https://semver.org/">the specification documentation</a></p>
<h2>Announcing Grails 5!</h2>
<p>To avoid violating semantic versioning, what had been planned to be Grails 4.1 will now be released as Grails 5. Once Grails 5 is released, we recommend users update their applications to benefit from the latest features and improvements. We believe that updating from Grails 4 to 5 should be a smooth experience as we have not made any major breaking changes in Grails 5 itself.</p>
<p>A major highlight of this release is the update to Apache Groovy 3, which includes support for Java 15 and significant other improvements around static compilation. We have also upgraded to the latest stable releases of some third-party libraries, including:</p>
<ul>
<li>
<p>Apache Groovy 3, which offers several <a href="https://groovy-lang.org/releasenotes/groovy-3.0.html">enhancements</a> to the language, including GDK improvements, a new parrot parser – far more flexible than the previous versions – and a collection of other new features and capabilities.</p>
</li>
<li>
<p>SpringBoot 2.4: This release adds a significant number of new features and improvements, such as improvements to the config file processing, a new startup actuator endpoint to help identify beans that are taking longer than expected to start, and an update to Spring Framework 5.3. For more information, check out <a href="https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-2.4-Release-Notes">SpringBoot 2.4 release notes</a>.</p>
</li>
<li>
<p>Gradle 6, which brings faster incremental Java and Groovy compilation, better version ordering, many bug fixes, and more. Refer to <a href="https://docs.gradle.org/6.5/release-notes.html">Gradle Release Notes</a> for more information.</p>
</li>
</ul>
<h2>New Release Cadence</h2>
<p>Going forward, the Grails framework will adhere to the following release cadence:</p>
<ul>
<li>A patch release every 3 weeks, which will include only bug fixes and will not introduce new features or breaking changes</li>
<li>A minor release every 6 weeks, which will introduce new features/functionality in a backward compatible manner</li>
<li>A major release once every year, which may introduce breaking changes</li>
</ul>
<p>This disciplined approach to releases will make the upgrade path for future minor and major releases easier.</p>
<h2>Grails Framework EOL Schedule</h2>
<p>In 2021, we will be scheduling “End Of Life” for Grails 2 and 3 as follows:</p>
<ul>
<li>Grails 2 will be EOL after June 30th, 2021.</li>
<li>Grails 3 will be EOL after September 30th, 2021.</li>
</ul>
<p>Going forward, with each major release, the previous major release will go into maintenance and support mode.</p>
<h2>The Road Ahead</h2>
<p>We are excited to continue to advance the Grails framework in the year 2021 with the support of the new Grails Foundation and great community. We will be focusing on improving the performance of the Grails application and user experience. In addition, we are planning a number of enhancements including:</p>
<ul>
<li>Making GSP more modular and independent of the Grails framework</li>
<li>Transaction support in GORM for MongoDB</li>
<li>Native support for web-sockets</li>
<li>Continuously improving Grails documentation (especially around plugins, Micronaut configuration, HTTP Client, and other features)</li>
<li>Better integration with Micronaut, such as declarative HTTP Client</li>
<li>Better support for Kafka, including creating Kafka listeners through a plugin and more</li>
</ul>]]></description><author>Puneet Behl</author><guid>2021-01-22-grails-exciting-updates</guid><pubDate>Fri, 22 Jan 2021 00:00:00 GMT</pubDate></item><item><title>Grails® Foundation Announced</title><link>https://grails.apache.org/blog/2020-10-26-grails-foundation-announcement.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/foundation.html"><span class="hashtag">#foundation</span></a></p>
<p>We're pleased to announce the formation of the new Grails<sup>®</sup> Foundation, a not-for-profit company established to support and continue to advance the open source Grails® Framework.</p>
<p>The Grails Foundation oversees software roadmap and development, best practices and processes, repository control, documentation and support, and fundraising related to the open source framework.</p>
<p><a href="https://objectcomputing.com/news/2020/10/26/new-grails-foundation-announced">Continue reading on Object Computing, Inc. (OCI) website</a></p>]]></description><author>Jen Wiese</author><guid>2020-10-26-grails-foundation-announcement</guid><pubDate>Mon, 26 Oct 2020 00:00:00 GMT</pubDate></item><item><title>2GM Town Hall Meeting: 2020 Q4</title><link>https://grails.apache.org/blog/2020-10-16-2gm-town-hall-2020-q4.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/townhall.html"><span class="hashtag">#townhall</span></a></p>
<p>A big thanks to everyone who joined us for our inaugural 2GM Town Hall webinar. We had a great time and learned about several exciting goings on within the Groovy, Grails<sup>®</sup> framework, and Micronaut communities. For those of you who missed the live event, the recording is embedded below.</p>
<p>I would like to take this opportunity to thank our fantastic panel of experts:</p>
<ul>
<li>James Kleeh, Micronaut Development Lead</li>
<li>Puneet Behl, Grails Development Lead</li>
<li>Jeff Scott Brown, Micronaut and Grails Practice Lead and Object Computing Partner</li>
<li>Plus, our guest panelist, David Estes</li>
</ul>
<p>David is the co-founder and VP of Engineering at Morpheus Data and also the creator of the Grails Asset-Pipeline, which is broadly used by many developers in the Grails community.
David has contributed to so many plugins over the years, he has lost count! Which is one of the many reasons we were thrilled to present him with the 2020 Grails Community Rock Star Award! Congratulations, David!</p>
<p>Stay tuned for details about our next 2GM Town Hall meeting, where Object Computing Groovy Development Lead, Paul King, will share the latest on Groovy 4.0, and we'll welcome a surprise special guest.</p>
<p>— Jen Wiese</p>
<p>2GM Product Evangelist</p>
<p><a href="https://objectcomputing.com/files/3716/0331/1496/2GM_Town_Hall_Deck.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/yfY2SBtagYs" frameborder="0"></iframe>]]></description><author>Jen Wiese</author><guid>2020-10-16-2gm-town-hall-2020-q4</guid><pubDate>Fri, 16 Oct 2020 00:00:00 GMT</pubDate></item><item><title>2GM Quarterly Town Hall Meetings</title><link>https://grails.apache.org/blog/2020-10-01-2gm-town-hall.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/townhall.html"><span class="hashtag">#townhall</span></a></p>
<p>At Object Computing, home to the Grails<sup>®</sup> framework and Micronaut, our core values energize and guide us in all that we do. Those values are:</p>
<ul>
<li>All of us is better than any one of us.</li>
<li>Innovate courageously.</li>
<li>Share it back.</li>
</ul>
<p>As part of our commitment to empowering technologists – both within our organization and without – to find inspiration in these values, we invest our resources in open source projects. Through those projects, we have the opportunity to engage with the global open source community, including the Groovy, Grails framework, and Micronaut communities – communities that are supportive, enthusiastic, creative, and full of thought leaders.</p>
<p>2GM Town Hall Meetings provide the Groovy, Grails framework, and Micronaut communities a place to gather once per quarter to review the most up-to-date news and resources available, celebrate accomplishments, ask questions, and participate more fully in the 2GM ecosystems.</p>
<p>Each Town Hall Meeting is led by a panel of 2GM users, developers, and advocates. Everyone in the 2GM communities is welcome and encouraged to participate.</p>
<p>We look forward to hearing from you, learning from you, engaging with you, and empowering you to contribute to the community and the frameworks you love.</p>]]></description><author>Jen Wiese</author><guid>2020-10-01-2gm-town-hall</guid><pubDate>Thu, 01 Oct 2020 00:00:00 GMT</pubDate></item><item><title>Grails® State of the Union</title><link>https://grails.apache.org/blog/2020-09-10-grails-state-of-union.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/micronaut.html"><span class="hashtag">#micronaut</span></a> <a href="https://grails.apache.org/blog/tag/groovy3.html"><span class="hashtag">#groovy3</span></a></p>
<p>As we approach the fourth quarter of 2020, I wanted to take a few minutes to update everyone in the community on the updates and enhancements coming to the Grails<sup>®</sup> framework.</p>
<p>In the last few months, the <a href="https://objectcomputing.com/products/2gm-team">2GM (Groovy, Grails framework, and Micronaut) team</a> has put a lot of work into the upcoming Grails 4.1 release. We’re excited to share that this release will include support for Apache Groovy 3! Groovy 3 offers a number of <a href="https://groovy-lang.org/releasenotes/groovy-3.0.html">enhancements</a> to the language including method references and a new, more flexible parser. Additionally, Grails 4.1 will support <a href="https://micronaut.io">Micronaut 2.0</a>, Gradle 6.5, and Spring 2.3. We’ve also added improvements to the Grails profiles to support the exclusion of transitive dependencies.</p>
<p>Apart from this, we've had some minor releases featuring bug fixes and improvements, which include (but are not limited to) the following:</p>
<ul>
<li>Loading configurations from plugins</li>
<li>Significant improvements to the performance of compileGroovyPages and compileJsonView Gradle tasks</li>
<li>GORM for MongoDB to support MongoDB Sync driver 4.0.3</li>
<li>GORM for Neo4j to use the latest Neo4j driver version 4.0.1</li>
<li>Update to the latest Elasticsearch in the Grails Elasticsearch plugin</li>
<li>Injecting GORM Data Services</li>
</ul>
<h2>Developer Productivity FTW!</h2>
<p>The Grails framework remains an excellent choice for rapidly building web applications. The framework utilizes the power of the Groovy language and offers lots of Groovy DSLs. If you prefer the dynamic nature of Groovy, the Grails framework is an excellent option for you.</p>
<p>Other benefits include the following:</p>
<ul>
<li>The Grails framework gives you the power to use any Spring library; from Grails 3 forward, the framework is built on top of Spring Boot</li>
<li>In Grails 4, Micronaut is the parent application, which allows you to use many Micronaut features, including the Micronaut HTTP client, Kafka client, and others in your Grails apps. Due to Micronaut’s avoidance of reflection, you also benefit from a reduced memory footprint and faster start times!</li>
<li>The Grails framework provides a variety of compelling and powerful features, such as GSP, JSON Views, and more.</li>
<li>The Grails framework allows you to quickly and easily build an application because it takes advantage of the convention over configuration concept, wherein you:
<ul>
<li>Do not need to use a lot of annotations, such as Controller, Service, etc.</li>
<li>Do not need to specify every URL mapping</li>
<li>Benefit from automatic code generation</li>
<li>Can build REST APIs for domains</li>
</ul>
</li>
</ul>
<p>While the parent context in Grails 4 is Micronaut, it is worth noting that not all Micronaut features are supported in the Grails framework at this time.  These include:</p>
<ul>
<li>Anything that has to do with the server, such as tracing, Micronaut controllers, etc.</li>
<li>GraalVM native image support</li>
<li>Micronaut serverless, AWS Lambda, Functions, GRPC, etc.</li>
</ul>
<p>As the Grails framework continues to evolve, so does the way that we are using Grails apps here at Object Computing. As I mentioned above, Grails 4 applications can now use many of Micronaut’s features, including the <a href="https://docs.micronaut.io/latest/guide/index.html#httpClient">HTTP Client</a>. If your application is using the GORM REST Client, we suggest migrating over to the Micronaut HTTP Client.</p>
<p>Also, because Grails 4 now uses Micronaut as the parent context, you can develop integrations for your applications using a <a href="https://docs.micronaut.io/latest/guide/index.html#configurations">Micronaut Configuration</a> where you may have written a Grails plugin in the past. Doing so will enable your Grails application to make use of the new functionality and opens up the opportunity to use the configuration with other non-Grails applications that have been built on Micronaut!</p>
<h2>Coming Soon</h2>
<p>In addition to the improvements above, we are planning on a number of additional enhancements including:</p>
<ul>
<li>Native support for web-sockets</li>
<li>Transaction support in GORM for MongoDB</li>
<li>Better support for Kafka, such as improvements in the CLI for creating Kafka listeners through the plugin</li>
<li>Ability to use GSP in Micronaut and Spring Boot applications by making GSP more modular and independent to the Grails framework</li>
<li>More Micronaut features, including reduced memory footprints and other benefits</li>
<li>Support for the latest Groovy and JDK.</li>
</ul>
<h2>Thank You</h2>
<p>The continuing evolution and improvements to the Grails framework wouldn’t be possible without the work and support provided by the vibrant <a href="/community.html">Grails community</a>. If you are new to the Grails framework or are considering it for your next project, please stop by our <a href="https://slack.grails.org">Slack community</a> and say &quot;hello.&quot; We can’t wait to hear about the great applications you're building with Groovy and the Grails framework!</p>]]></description><author>Puneet Behl</author><guid>2020-09-10-grails-state-of-union</guid><pubDate>Thu, 10 Sep 2020 00:00:00 GMT</pubDate></item><item><title>Webinar: Grails® 4 Upgrade</title><link>https://grails.apache.org/blog/2019-12-20.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<p>Join 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio del Amo</a>, for an in-depth demonstration of how to upgrade a Grails 3 application to Grails 4. Sergio also shows you how to benefit from the Micronaut integration available in the new iteration of the framework.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Grails 4 migration checklist</li>
<li>SpringBoot changes</li>
<li>Gradle changes</li>
<li>GORM changes</li>
<li>Plugin changes</li>
<li>Grails development hot reload</li>
<li>Micronaut + the Grails framework</li>
<li>Migration from Rest client builder to Micronaut HTTP client</li>
</ul>
<p><a href="https://objectcomputing.com/files/5715/7841/1261/Slide_Deck_Grails_4_Upgrade_Webinar.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/i-zSKRsI2FA" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2019-12-20</guid><pubDate>Fri, 20 Dec 2019 00:00:00 GMT</pubDate></item><item><title>Webinar: Groovy 3 and Beyond – An Insider's Guide</title><link>https://grails.apache.org/blog/2019-08-27.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/groovy.html"><span class="hashtag">#groovy</span></a></p>
<h2>Overview</h2>
<p>Apache Groovy 3 is approaching feature-complete status and is targeted for release over the coming months.</p>
<p>In this complimentary webinar, <a href="https://objectcomputing.com/products/2gm-team#king">Object Computing Groovy Project Lead, Paul King</a>, provides inside information on the release schedule and introduces the improvements and new features you can expect, including a new parser, improved JDK 9-14 support, and tooling enhancements.</p>
<p>Find out what the team has planned in the latest iteration of the language, and get a sneak peek at what's in the pipeline for Groovy 4!</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar.</p>
<ul>
<li>Groovy roadmap for version 3</li>
<li>An overview of the new parser
<ul>
<li>Lambda syntax and method/constructor references</li>
<li>Improved looping and Java compatibility (try with resources)</li>
<li>New operators (safe indexing, Elvis assignment, negated variants)</li>
<li>The <code>var</code> reserved type</li>
<li>Default methods in interfaces</li>
</ul>
</li>
<li>Improved JDK 9+ support
<ul>
<li>Split packaging and illegal access remediation</li>
</ul>
</li>
<li>Tooling improvements</li>
<li>A peek at what's planned for Groovy 4 and beyond</li>
</ul>
<p>Although everyone is welcome, this webinar is most useful to developers who use Java or Groovy (including any of the many projects in the Groovy ecosystem), as well as anyone with an interest in JVM languages. Previous exposure to Groovy is a plus, but no detailed knowledge is assumed.</p>
<p><a href="https://objectcomputing.com/files/6415/6694/2515/slide_deck_Groovy_3_and_Beyond_webinar.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/FPA_3dXzH7A" frameborder="0"></iframe>]]></description><author>Paul King</author><guid>2019-08-27</guid><pubDate>Tue, 27 Aug 2019 00:00:00 GMT</pubDate></item><item><title>Grails® 4 GA Released</title><link>https://grails.apache.org/blog/2019-07-11.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>After several release candidates and great feedback from the community, the <a href="https://objectcomputing.com/products/2gm-team" title="Grails Team">Grails<sup>®</sup> team</a> at Object Computing, Inc. (OCI) is pleased to announce the GA availability of <a href="https://github.com/apache/grails-core/releases/tag/v4.0.0">Grails 4</a>.</p>
<p>Grails 4 represents a significant upgrade, with the framework now rebased on top of an updated minimum set of dependencies including:</p>
<ul>
<li>Spring 5.1</li>
<li>Spring Boot 2.1</li>
<li>Java 8</li>
<li>Hibernate 5.4</li>
<li>Groovy 2.5</li>
<li>Gradle 5</li>
</ul>
<p>In addition, <a href="https://micronaut.io/" title="Micronaut">Micronaut</a> is now included as part of the Grails framework as the parent ApplicationContext, allowing any Micronaut feature, whether it be the declarative HTTP client or the Kafka client, to be used within a Grails 4 application. In fact the <a href="https://docs.micronaut.io/latest/guide/index.html#httpClient">Micronaut HTTP client</a> is now considered the supported HTTP client for use within Grails applications.</p>
<p>Startup time and memory consumption have also been optimized and improved significantly over previous releases, thanks to changes in both Spring Boot 2.1 and also the migration of some of the Grails framework's internal infrastructure wiring to Micronaut.</p>
<p>Many Grails plugins have been verified as working with Grails 4. For those within the Grails plugin community, now is the time to upgrade your plugins and verify they continue to work with Grails 4. As this is a new major version, <a href="https://grails.apache.org/docs/4.0.x/guide/upgrading.html">API changes have been made</a>, as well as changes within Spring Boot, Groovy, and Hibernate that may require changes to work with Grails 4. Please read the <a href="https://grails.apache.org/docs/4.0.x/guide/upgrading.html">upgrade documentation</a> for more information.</p>
<p>Thanks to all those who contributed to the release, and if you haven't already, do sign up for <a href="https://objectcomputing.com/products/micronaut/community/something-big-is-coming">next week's webinar</a> where we have more exciting announcements related to the Grails framework and Micronaut planned.</p>]]></description><author>Graeme Rocher</author><guid>2019-07-11</guid><pubDate>Thu, 11 Jul 2019 00:00:00 GMT</pubDate></item><item><title>Webinar: Using Apache Groovy for Data Science</title><link>https://grails.apache.org/blog/2019-06-18.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/groovy.html"><span class="hashtag">#groovy</span></a></p>
<p>Apache Groovy is a multi-faceted, multi-paradigm programming language for the JVM that offers a wealth of features that make it ideal for transforming big data into usable solutions.</p>
<ul>
<li>It has a dynamic nature like Python, which means that it is very powerful, easy to learn, and productive.</li>
<li>It has a static nature like Java and Kotlin, which makes it fast when needed.</li>
<li>And it has first-class functional support, meaning that it offers features and allows solutions similar to Scala.</li>
</ul>
<p>In this complimentary webinar, <a href="https://objectcomputing.com/products/2gm-team#king">Object Computing Groovy Practice Lead, Paul King</a>, reviews the key benefits of using Groovy to develop data science solutions, including integration with various JDK libraries commonly used in data science solutions.</p>
<p><a href="https://objectcomputing.com/files/5715/6095/8662/Slide_Deck_Groovy_for_Data_Science_Webinar.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/rixvYN-DCPk" frameborder="0"></iframe>]]></description><author>Paul King</author><guid>2019-06-18</guid><pubDate>Tue, 18 Jun 2019 00:00:00 GMT</pubDate></item><item><title>Possible Grails® MITM Vulnerability</title><link>https://grails.apache.org/blog/2019-05-30.html</link><description><![CDATA[</p>
<h2>Introduction</h2>
<p>In the Grails<sup>®</sup> framework, we have been using Travis to automatically release new versions.</p>
<p>Some time ago, a user <a href="https://github.com/apache/grails-core/issues/11250" title="Issue 11250">opened an issue</a> detailing a possible MITM (Man in the Middle) attack because we were using a non-secured repository as part of the build process.</p>
<h2>Our Analysis</h2>
<p>The HTTP repository mentioned before was only used to resolve SDKMan notification service and not for any project dependencies. All project dependencies were resolved with HTTPS.</p>
<p>We have conducted an audit of the latest versions of the Grails <code>3.1.x</code>, <code>3.2.x</code>, <code>3.3.x</code>, and <code>4.x</code> lines, and we have verified that their contents have not been manipulated.</p>
<p>We undertook the same process as the Groovy team and diffed all jars and executable content. There were 6 differences in the generated byte code, which we isolated to an issue in the Groovy compiler, which was simply changing the <em>order</em> of the byte code output – not the byte code itself.</p>
<p>In addition, we have released Grails <code>3.3.10</code>, which includes the applied patch, as well as a version of Groovy that also has the patch applied.</p>
<h2>Assuring This Won't Happen Again</h2>
<p>We have added a check that will make the build fail if any repository is not secure. You can get more information on this solution <a href="https://github.com/apache/grails-core/blob/master/build.gradle#L597" title="Learn more about this solution">here</a>.</p>
<h2>Steps for Users</h2>
<p>No action is necessary. The issue was specifically related to the build of the framework itself and not applications built with it. If there were an issue, it would have been introduced in the build of the Grails framework (not your Grails apps), and we have verified that Grails code itself was not compromised. Thus, users do not need to verify their own apps because they weren’t resolving dependencies over HTTP. However, in case of doubt, you can upgrade to Grails <code>3.3.10</code>, which includes the applied patch.</p>]]></description><author>Iván López</author><guid>2019-05-30</guid><pubDate>Thu, 30 May 2019 00:00:00 GMT</pubDate></item><item><title>Webinar: Single-Page Apps Simplified with the Grails® framework and Vue.js</title><link>https://grails.apache.org/blog/2019-05-24.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<p>Vue.js is a modern, pragmatic JavaScript library designed for building user interfaces. Vue borrows good ideas from React and Angular, then adds a slew of features to enhance developer experience and productivity. Interest in Vue is through the roof, and for good reason.</p>
<p>The Grails<sup>®</sup> framework includes a Vue profile for building applications with a Vue front-end. In addition, the Grails framework offers several features that make it an ideal back-end framework for single-page apps (SPAs), including JSON views and JWT authentication with the Spring Security REST plugin.</p>
<p>In this webinar, 2GM (Groovy, Grails framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#klein-z">Zachary Klein</a>, introduces the Vue.js library and walks you through a Grails project using Vue, REST, and JWT security. He completes the demonstration by demonstrating the steps necessary to build an executable JAR file with the Grails framework and Vue.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Introduction to Vue.js</li>
<li>Overview of the Vue profile for the Grails framework</li>
<li>Overview of Spring Security REST with JWT</li>
<li>Demonstration of how to implement JWT security with the Grails framework and Vue</li>
<li>Demonstration of a sample project using the Grails framework and Vue</li>
<li>Demonstration of an executable JAR build with Gradle</li>
</ul>
<p>This is a great opportunity for Grails developers to add a new skill to their coding toolboxes! General web and JVM developers are also encouraged to discover what the Grails framework has to offer modern web development practices.</p>
<p><a href="https://objectcomputing.com/files/4215/5872/4980/Slide_Deck_SPAs_with_Grails_and_Vue_Webinar.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/eSNYhZeTmWg" frameborder="0"></iframe>]]></description><author>Zachary Klein</author><guid>2019-05-24</guid><pubDate>Fri, 24 May 2019 00:00:00 GMT</pubDate></item><item><title>Webinar: Introducing Grails® 4: Upgrades and New Features</title><link>https://grails.apache.org/blog/2019-03-27.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<p>This webinar provides an introduction to the latest iteration of the Grails<sup>®</sup> framework.</p>
<h2>Overview</h2>
<p>The first milestone of Grails 4 was released in February 2019, and further milestones and release candidates are forthcoming, pending community feedback.</p>
<p>This webinar, hosted by 2GM (Groovy, Grails framework, and Micronaut) team member <a href="https://objectcomputing.com/products/2gm-team#kleeh">James Kleeh</a>, provides Grails users a summary of the new features they can expect in Grails 4 (including Micronaut integration!) and a good idea of what to expect regarding the upgrade process.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Differences between Grails 3 and Grails 4</li>
<li>Key upgrades and new features</li>
<li>Why Spring Loaded is out, and how this impacts your Grails applications</li>
<li>What Micronaut integration means for you</li>
<li>What to expect from the upgrade effort going forward</li>
</ul>
<p><a href="https://objectcomputing.com/files/9715/5371/5835/Slide_Deck_Introducing_Grails_4_Webinar.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/EVA_pIrjVdo" frameborder="0"></iframe>]]></description><author>James Kleeh</author><guid>2019-03-27</guid><pubDate>Wed, 27 Mar 2019 00:00:00 GMT</pubDate></item><item><title>Grails® 4 Milestone 1 Released</title><link>https://grails.apache.org/blog/2019-02-19.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>The <a href="https://objectcomputing.com/products/2gm-team" title="Grails Team">Grails<sup>®</sup> team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the availability of the <a href="https://github.com/apache/grails-core/releases/tag/v4.0.0.M1">first milestone of Grails 4</a>.</p>
<p>Grails 4 represents a significant upgrade with the framework now rebased on top of an updated minimum set of dependencies including:</p>
<ul>
<li>Spring 5.1</li>
<li>Spring Boot 2.1</li>
<li>Java 8</li>
<li>Hibernate 5.4</li>
<li>Groovy 2.5</li>
</ul>
<p>In addition, <a href="https://micronaut.io/" title="Micronaut">Micronaut</a> is now included as part of the Grails framework as the parent ApplicationContext, allowing any Micronaut feature, whether it be the declarative HTTP client or the Kafka client, to be used within a Grails 4 application.</p>
<p>Startup time and memory consumption have also been optimized and improved significantly over previous releases, thanks to changes in both Spring Boot 2.1 and also the migration of some of the Grails framework's internal infrastructure wiring to Micronaut.</p>
<p>Many Grails plugins have been verified as working with Grails 4, and for those within the Grails plugin community, now is the time to upgrade your plugins and verify the plugins continue to work with Grails 4. As this is a new major version, <a href="https://grails.apache.org/docs/4.0.x/guide/upgrading.html">API changes have been made</a>, as well as changes within Spring Boot, Groovy, and Hibernate that may require changes to work with Grails 4. Please read the <a href="https://grails.apache.org/docs/4.0.x/guide/upgrading.html">upgrade documentation</a> for more information.</p>
<p>Thanks to all those who contributed to the release, and we look forward to your feedback and to seeing you at Devnexus 2019.</p>]]></description><author>Graeme Rocher</author><guid>2019-02-19</guid><pubDate>Tue, 19 Feb 2019 00:00:00 GMT</pubDate></item><item><title>Quickcast #12: Building Grails® Applications with Gradle</title><link>https://grails.apache.org/blog/2019-01-30.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this Grails<sup>®</sup> Quickcast, 2GM (Groovy, Grails framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio del Amo</a>, explores Grails integration with the Gradle build tool.</p>
<p>In this 25-minute tutorial, Sergio:</p>
<ul>
<li>Explains the Gradle wrapper-related files</li>
<li>Explains how it's possible to delegate IDE build/run actions from IntelliJ IDEA to Gradle</li>
<li>Introduces common Gradle tasks for Grails developers, such as bootRun, test, integrationTest, and check or assemble</li>
<li>Demonstrates how to work with system properties and get a more verbose output from your Gradle test executions</li>
</ul>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/-h3YfHbGkvA" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2019-01-30</guid><pubDate>Wed, 30 Jan 2019 00:00:00 GMT</pubDate></item><item><title>SDKMAN! with Travis</title><link>https://grails.apache.org/blog/2019-01-07.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/deployment.html"><span class="hashtag">#deployment</span></a></p>
<p>The <a href="https://objectcomputing.com/products/2gm-team">2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) uses <a href="https://travis-ci.org/">Travis CI</a> and <a href="https://sdkman.io/">SDKMAN!</a> daily.</p>
<p>Using SDKMAN! in Travis is possible and opens a lot of possibilities.</p>
<p>The following <code>.travis.yml</code> file will install SDKMAN! and create a Grails app using the latest version available.</p>
<pre><code class="language-bash">install: true
jdk:
  - oraclejdk8
script:
  - curl -s get.sdkman.io | bash
  - source &quot;$HOME/.sdkman/bin/sdkman-init.sh&quot;
  - echo sdkman_auto_answer=true &gt; ~/.sdkman/etc/config
  - source &quot;/home/travis/.sdkman/bin/sdkman-init.sh&quot;
  - sdk install grails
</code></pre>]]></description><author>Sergio del Amo Caballero</author><guid>2019-01-07</guid><pubDate>Mon, 07 Jan 2019 00:00:00 GMT</pubDate></item><item><title>Webinar: Introduction to Grails® Multi-Tenancy</title><link>https://grails.apache.org/blog/2018-10-12.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<h2>Overview</h2>
<p>In this webinar, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio del Amo Caballero</a>, demonstrates the multi-tenancy capabilities built into the Grails framework and GORM.</p>
<p>Multi-tenancy, as it relates to software development, is when a single instance of an application is used to service multiple clients (tenants) in such a way that each tenant's data is isolated from the other. Among other things, multi-tenancy enables you to build software as a service (SaaS) applications.</p>
<p>Grails developers interested in learning how to integrate multi-tenancy in their applications will get an introduction to the Grails framework's multi-tenancy capabilities and an in-depth demonstration of how to implement this powerful functionality.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Supported multi-tenancy modes (database, schema, discriminator)</li>
<li>The Grails framework's built-in tenant resolver</li>
<li>How to build your own tenant resolver</li>
<li>How to build a custom tenant resolver by logged-in user</li>
<li>How to configure datasources dynamically while using database multi-tenancy</li>
</ul>
<p>This webinar is an excellent learning opportunity for Grails developers who wish to gain an understanding of Grails multi-tenancy capabilities and the possibilities therein.</p>
<p><a href="https://objectcomputing.com/files/4915/6624/8967/slide_deck_Micronaut_Multitenancy.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/ypVirnPo4y4" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2018-10-12</guid><pubDate>Fri, 12 Oct 2018 00:00:00 GMT</pubDate></item><item><title>Grails® Domain Read-Only Attribute</title><link>https://grails.apache.org/blog/2018-10-02.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
<p>Recently I encountered a situation with a client Grails<sup>®</sup> application that required a read-only domain attribute. The application had a backend table where one column (call it <code>A</code>) was populated strictly by a batch database process. The table needed to be mapped to a Grails domain class. Certain columns (call them <code>B through D</code>) were to be updated from the UI. Attribute <code>A</code> should not be writable, but needed to be accessed for read-only operations.</p>
<h2>The Problem</h2>
<p>The catch here is when an update occurs on a mapped domain class, GORM with Hibernate issues an update on all columns, regardless of which columns have a value change. So even if attribute <code>B</code> is changed, an update will be issued on all columns <code>A through D</code>. If the database is configured with a specific column as read-only, you will get an error along the lines of: &quot;failure to insert into a read-only column&quot;.</p>
<p>We propose two solutions:</p>
<ul>
<li>Derived Properties</li>
<li>Hibernate's Dynamic update.</li>
</ul>
<h2>Example</h2>
<p>Let's contrive a simple example with a domain class to understand the issue. Perhaps there is a <code>Team</code> with a <code>name</code>, <code>coach</code>, and <code>nationalRank</code>. <code>name</code> and <code>coach</code> are read-write attributes while <code>nationalRank</code> is the attribute which is read-only. It is updated strictly by a database batch process.</p>
<pre><code class="language-groovy">package grails.readonly.attribute

class Team {

    String name
    String coach
    Integer nationalRank

    static mapping = {
    }
}
</code></pre>
<p>Given a row already exists, we then issue an update with the statement:</p>
<pre><code class="language-groovy">team.name= &quot;Raiders&quot;
team.save(flush: true)
</code></pre>
<p>Hibernate will generate the log shown below. As you can see <code>nationalRank</code> is included in the statement, which will end up in an error due to the database constraint of read-only.</p>
<pre><code class="language-groovy">Hibernate: update team set version=?, national_rank=?, coach=?, name=? where id=? and version=?
</code></pre>
<h2>Derived Properties</h2>
<p>To prevent hibernate from including an attribute in the update statement, we can use the <code>formula</code> mapping for <code>nationalRank</code>. This means that GORM will allow us to access the property as though it were a normal column, but will ignore it for update operations (because formulas are, by definition, not updateable). In this case, the formula simply returns the value of the column, but the net effect gives us the desired behavior.</p>
<pre><code class="language-groovy">package grails.readonly.attribute

class Team {

    String name
    String coach
    Integer nationalRank

    static mapping = {
        nationalRank nullable: false, formula: 'NATIONAL_RANK'
    }
}
</code></pre>
<p>Now upon updates, the following hibernate log is generated (note the omission of <code>nationalRank</code>):</p>
<pre><code class="language-groovy">Hibernate: update team set version=?, coach=?, name=? where id=? and version=?
</code></pre>
<p>A derived property is one that takes its value from a SQL expression. E.g., <code>tax formula: 'PRICE * TAX_RATE'</code>. The formula expressed in the ORM DSL references to NATIONAL_RANK instead nationalRank. We are echoing a value which must be set elsewhere and cannot be inserted through GORM. So returning the column value directly achieves a read-only effect. <a href="https://gorm.grails.org/6.1.x/hibernate/manual/#derivedProperties">DerivedProperties</a></p>
<h2>DynamicUpdate</h2>
<p>An alternate way of achieving the same result is to use hibernate's <code>dynamicUpdate</code> mapping. <code>dynamicUpdate</code> tells Hibernate whether to include unmodified properties in the SQL UPDATE statement. This excludes any attribute from the update statement which is not dirty.</p>
<pre><code class="language-groovy">package grails.readonly.attribute

class Team {

    String name
    String coach
    Integer nationalRank

    static mapping = {
        dynamicUpdate true
    }
}
</code></pre>]]></description><author>Nirav Assar</author><guid>2018-10-02</guid><pubDate>Tue, 02 Oct 2018 00:00:00 GMT</pubDate></item><item><title>Security Vulnerability in Asset-Pipeline and Jetty</title><link>https://grails.apache.org/blog/2018-09-23.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
<h2>Introduction</h2>
<p><a href="https://github.com/bertramdev/asset-pipeline">Asset-pipeline</a> has been the default plugin for handling static assets in a Grails<sup>®</sup> web application since Grails 2.4.0. A security vulnerability that involves asset-pipeline and Jetty has been identified.</p>
<h2>Affected Versions</h2>
<p>The vulnerability affects all asset-pipeline users that deploy Grails applications in Jetty, and it allows directory traversal and download any file knowing its specific directory.</p>
<h2>Reproducing The Issue</h2>
<ul>
<li>Create a new grails application: <code>grails create-app foo</code></li>
<li>In <code>build.gradle</code> change the <code>spring-boot-starter-tomcat</code> to <code>spring-boot-starter-jetty</code></li>
<li>Build a war file: <code>grails war</code></li>
<li>Deploy to Jetty</li>
<li>Send the following request to download Application.class <code>wget localhost:8080/foo-0.1/assets/..%5c%5cfoo%5cApplication.class -O Application.class</code></li>
<li>It is also possible to download any any arbitrary file if the path is known. For example to download <code>application.yml</code>execute <code>curl -v localhost:8080/foo-0.1/assets/..%5capplication.yml</code>.</li>
</ul>
<h2>Fixing The Issue</h2>
<p>The vulnerability has been addressed in recent versions of the asset-pipeline plugin:</p>
<ul>
<li>2.14.1.1 for Grails 2.x</li>
<li>2.15.1 for Grails 3 and Java 7</li>
<li>3.0.6 for Grails 3 and Java 8</li>
</ul>]]></description><author>Iván López</author><guid>2018-09-23</guid><pubDate>Sun, 23 Sep 2018 00:00:00 GMT</pubDate></item><item><title>Quickcast #11: Grails® Profiling with YourKit</title><link>https://grails.apache.org/blog/2018-08-22-2.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.apache.org/blog/tag/yourkit.html"><span class="hashtag">#yourkit</span></a></p>
<p>In this Quickcast, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#assar">Nirav Assar</a>, demonstrates how to use YourKit to profile a Grails application and spot CPU problems and heap and garbage collection issues.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/NJ_T5g4bBeY" frameborder="0"></iframe>]]></description><author>Nirav Assar</author><guid>2018-08-22-2</guid><pubDate>Wed, 22 Aug 2018 00:00:00 GMT</pubDate></item><item><title>Quickcast #10: Debugging Grails® Apps</title><link>https://grails.apache.org/blog/2018-08-22-1.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this 13-minute Quickcast, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#lopez">Iván López</a>, demonstrates a variety of ways to debug Grails core code and the Grails CLI (command line interface). Developers may use these tips to fix issues or contribute enhancements to the core Grails framework.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/y69Cr_hYUCA" frameborder="0"></iframe>]]></description><author>Iván López</author><guid>2018-08-22-1</guid><pubDate>Wed, 22 Aug 2018 00:00:00 GMT</pubDate></item><item><title>Mock vs Stub vs Spy</title><link>https://grails.apache.org/blog/2018-06-22.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/spock.html"><span class="hashtag">#spock</span></a></p>
<h2>Introduction</h2>
<p><a href="https://spockframework.org/">Spock</a> provides three powerful yet distinct, tools that make working with collaborators easier:</p>
<ul>
<li><a href="https://spockframework.org/spock/docs/1.1/all_in_one.html#_creating_mock_objects">Mocks</a></li>
<li><a href="https://spockframework.org/spock/docs/1.1/all_in_one.html#Stubs">Stubs</a></li>
<li><a href="https://spockframework.org/spock/docs/1.1/all_in_one.html#Spies">Spies</a></li>
</ul>
<p>Quite often, the code that is under test is required to interact with outside units of code known as <a href="https://spockframework.org/spock/docs/1.1/all_in_one.html#_terminology">collaborators</a>. Unit tests are most often designed to focus on testing one class in isolation through the use of Mocks, Stubs or Spies. Tests are more robust and less prone to breakage should the collaborator code evolve.</p>
<p>These isolated tests are less brittle and less prone to breakage should the collaborators' internals be modified.</p>
<h2>TLDR</h2>
<h3>Mocks</h3>
<p>Use Mocks to:</p>
<ul>
<li>verify the contract between the code under test and a collaborator</li>
<li>verify the the collaborator's method is called the correct number of times</li>
<li>verify the collaborator's method is called with the correct parameters</li>
</ul>
<h3>Stubs</h3>
<p>Use Stubs to:</p>
<ul>
<li>provide a predetermined response from a collaborator</li>
<li>take a predetermined action from a collaborator, like throwing an exception</li>
</ul>
<h3>Spies</h3>
<p>Beware of Spies. As the Spock documentation states:</p>
<blockquote>
<p>Think twice before using this feature. It might be better to change the design of the code under specification.</p>
</blockquote>
<p>That being said, there are situations when we must work with legacy code. This legacy code may be difficult or impossible to test with Mocks or Stubs. In this case, Spies may be our only viable option.</p>
<p>It's better to have legacy code that is tested with a Spy then it is to have legacy code that is not tested at all.</p>
<p>Use Spies to:</p>
<ul>
<li>test legacy code collaborators that are too difficult or impossible to test with a Mock or Spy</li>
<li>verify the collaborator's method is called the correct number of times</li>
<li>verify the collaborator's method is called with the correct parameters</li>
<li>provide a predetermined response from a collaborator</li>
<li>take a predetermined action from a collaborator, like throwing an exception</li>
</ul>
<h2>Mocks</h2>
<p>The power of Mocks really shines when the goal of a unit test is to validate the contract between the code under test and a collaborator.</p>
<p>Let's take a look at the following example where we have a controller, <code>FooController</code>, which utilizes <code>FooService</code> as a collaborator and then test the functionality with a Mock.</p>
<p>FooController.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooController {
    FooService fooService

    def doSomething() {
        render fooService.doSomething(&quot;Sally&quot;)
    }
}
</code></pre>
<p>FooService.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooService {

    String doSomething(String name) {
        &quot;Hi ${name}, FooService did something&quot;
    }
}
</code></pre>
<p>In this scenario, we want to write a test that will validate:</p>
<ul>
<li>the contract between <code>FooController</code> and <code>FooService</code></li>
<li><code>FooService.doSomething(name)</code> is called the correct number of times</li>
<li><code>FooService.doSomething(name)</code> is passed the correct parameter</li>
</ul>
<p>Here's the test:</p>
<p>MockSpec.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class MockSpec extends Specification implements ControllerUnitTest&lt;FooController&gt; {

    void &quot;Mock FooService&quot;() {
        given: &quot;the collaborating service is mocked&quot;
        def fooService = Mock(FooService)

        and: &quot;the mocked service is set on the controller&quot;
        controller.fooService = fooService

        when: &quot;the controller action is called&quot;
        controller.doSomething()

        then: &quot;the Mock can be used to validate cardinality and parameters&quot;
        1 * fooService.doSomething(&quot;Sally&quot;)

        and: &quot;the mocked service returns the default 'zero value' of 'null'&quot;
        response.text == null.toString()
    }
}
</code></pre>
<p>The above test mocks <code>FooService</code> by doing the following:</p>
<pre><code class="language-groovy">def fooService = Mock(FooService)
</code></pre>
<p>The test also verifies that <code>FooService.doSomething(name)</code> is called just once and the parameter passed to it is equal to a String value of &quot;Sally&quot;.</p>
<pre><code class="language-groovy">1 * fooService.doSomething(&quot;Sally&quot;)
</code></pre>
<p>The above snippets of code accomplish four important tasks:</p>
<ul>
<li>Creates a Mock for <code>FooService</code></li>
<li>Ensures the <code>FooService.doSomething(String name)</code> method is called only once and the parameter <code>name</code> is equal to the String &quot;Sally&quot;</li>
<li>Isolates the code under test by mocking the implementation of the collaborator</li>
</ul>
<h2>Stubs</h2>
<p>Does the code under test use a collaborator? Is the goal to ensure the code under test behaves properly when interacting with a collaborator? Does the collaborator act as input to the code under test?</p>
<p>If the behavior of the code under test will change based upon the behavior of the collaborator, then what you need to use is a Stub.</p>
<p>Let's take a look at the following example where we have a controller, <code>FooController</code>, which utilizes <code>FooService</code> as a collaborator and then test the functionality with a Stub.</p>
<p>FooController.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooController {
    FooService fooService

    def doSomething() {
        render fooService.doSomething(&quot;Sally&quot;)
    }
}
</code></pre>
<p>FooService.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooService {

    String doSomething(String name) {
        &quot;Hi ${name}, FooService did something&quot;
    }
}
</code></pre>
<p>Here's the test:</p>
<p>StubSpec.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class StubSpec extends Specification implements ControllerUnitTest&lt;FooController&gt; {

    void &quot;Stub FooService&quot;() {
        given: &quot;the collaborating service is stubbed&quot;
        def fooService = Stub(FooService) {
            doSomething(_) &gt;&gt; &quot;Stub did something&quot;
        }

        and: &quot;the stubbed service is set on the controller&quot;
        controller.fooService = fooService

        when: &quot;the controller action is called&quot;
        controller.doSomething()

        then: &quot;the stubbed service returns the stubbed text&quot;
        // 1 * fooService.doSomething() cardinality not supported by Stub
        response.text == &quot;Stub did something&quot;
    }
}
</code></pre>
<p>The above test stubs <code>FooService</code> by doing the following:</p>
<pre><code class="language-groovy">def fooService = Stub(FooService) {
    doSomething(_) &gt;&gt; &quot;Stub did something&quot;
}
</code></pre>
<p>The above code accomplishes four important tasks:</p>
<ul>
<li>Creates a Stub for <code>FooService</code></li>
<li>Ensures the <code>FooService.doSomething(String name)</code> method will return the String &quot;Stub did something&quot; independently of the <code>name</code> parameter value. Hence the use of <code>_</code>.</li>
<li>Isolates the code under test by mocking the implementation of the collaborator</li>
</ul>
<h2>Spies</h2>
<p>Please don't read this section.</p>
<p>Look away.</p>
<p>Please skip ahead to the next section.</p>
<p>Still reading this? Well, okay, let's talk about Spies.</p>
<p>Do not use Spies. As the Spock documentation states:</p>
<blockquote>
<p>Think twice before using this feature. It might be better to change the design of the code under specification.</p>
</blockquote>
<p>That being said, there are situations when we must work with legacy code. The legacy code may be difficult to test with Mocks or Stubs. In this case, Spies may the only viable option.</p>
<p>Spies are different than Mocks or Stubs because they do not act as a test duplicate in the same sense.</p>
<p>When a class is Mocked or Stubbed, a test double is created and the original code that exists within the Mocked or Stubbed object is not executed.</p>
<p>Spies, on the other hand, will execute the original code from which the Spy was created, but a Spy will also allow you to modify what the Spy returns and verify cardinality much like Mocks and Stubs.</p>
<p>Let's take a look at the following example where we have a controller, <code>FooController</code>, which utilizes <code>FooService</code> as a collaborator and then test the functionality with a Spy.</p>
<p>FooController.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooController {
    FooService fooService

    def doSomething() {
        render fooService.doSomething(&quot;Sally&quot;)
    }
}
</code></pre>
<p>FooService.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import groovy.transform.CompileStatic

@CompileStatic
class FooService {

    String doSomething(String name) {
        &quot;Hi ${name}, FooService did something&quot;
    }
}
</code></pre>
<p>Here's the test:</p>
<p>SpySpec.groovy</p>
<pre><code class="language-groovy">package com.mycompany.myapp

import grails.testing.web.controllers.ControllerUnitTest
import spock.lang.Specification

class SpySpec extends Specification implements ControllerUnitTest&lt;FooController&gt; {

    void &quot;Spy FooService&quot;() { 
        given: &quot;the collaborating service is a Spy&quot;
        def fooService = Spy(FooService)

        and: &quot;the Spy service is set on the controller&quot;
        controller.fooService = fooService

        when: &quot;the controller action is called&quot;
        controller.doSomething()

        then: &quot;the Spy can be used to validate cardinality&quot;
        1 * fooService.doSomething(&quot;Sally&quot;) &gt;&gt; &quot;A Spy can modify implementation&quot;

        and: 'A spy can modify implementation'
        response.text == &quot;A Spy can modify implementation&quot;
    }
}
</code></pre>
<p>The above test creates a Spy on <code>FooService</code> by doing the following:</p>
<pre><code class="language-groovy">def fooService = Spy(FooService)
{% endhighlight %} 

The following code demonstrates how the Spy allows us to verify `FooService.doSomething(name)` is called just once and the parameter passed to it is equal to a String value of &quot;Sally&quot;:
Moreover, it changes the method implementation to return a different String.

{% highlight groovy %}
1 * fooService.doSomething(&quot;Sally&quot;) &gt;&gt; &quot;A Spy can modify implementation&quot;
</code></pre>
<p>The following code demonstrates how the Spy allows us to verify <code>FooService.doSomething(name)</code> is called just once and the parameter passed to it is equal to a String value of &quot;Sally&quot;: Moreover, it changes the method implementation to return a different String.</p>
<pre><code class="language-groovy">1 * fooService.doSomething(&quot;Sally&quot;) &gt;&gt; &quot;A Spy can modify implementation&quot;
</code></pre>
<p>The above code accomplishes four important tasks:</p>
<ul>
<li>Creates a Spy for <code>FooService</code></li>
<li>Verifies interaction with the collaborator.</li>
<li>Verifies how the application behaves when a collaborator responds in a certain way.</li>
</ul>
<h2>FAQ</h2>
<p><strong>Q:</strong> Should I use a Mock, a Stub, or a Spy?</p>
<p><strong>A:</strong> This is a question faced by many a developer. The following FAQ may help if you are ever unsure as to which mocking option to use.</p>
<p><strong>Q:</strong> Is the goal of the test to verify the contract between the code under test and a collaborator?<br />
<strong>A:</strong> If you answered yes, use Mock</p>
<p><strong>Q:</strong> Is the goal of the test to ensure the code under test behaves properly when interacting with a collaborator?<br />
<strong>A:</strong> If you answered yes, use Stub</p>
<p><strong>Q:</strong> Does the collaborator act as input to the code that is under test?<br />
<strong>A:</strong> If you answered yes, use Stub</p>
<p><strong>Q:</strong> Are you working with legacy code that is extremely difficult to test and you've exhausted all other options?<br />
<strong>A:</strong> Try using a Spy</p>
<h2>Sample Code</h2>
<p>The sample code referenced in this post may be found at <a href="https://github.com/ddelponte/mock-stub-spy">https://github.com/ddelponte/mock-stub-spy</a></p>
<h2>Useful Links</h2>
<ul>
<li><a href="https://spockframework.org/spock/docs/1.1/all_in_one.html#_interaction_based_testing">https://spockframework.org/spock/docs/1.1/all_in_one.html#_interaction_based_testing</a></li>
<li><a href="https://martinfowler.com/bliki/UnitTest.html">https://martinfowler.com/bliki/UnitTest.html</a></li>
<li><a href="https://martinfowler.com/articles/mocksArentStubs.html">https://martinfowler.com/articles/mocksArentStubs.html</a></li>
</ul>]]></description><author>Dean Del Ponte</author><guid>2018-06-22</guid><pubDate>Fri, 22 Jun 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: I've Seen Grails® Code You Wouldn't Believe</title><link>https://grails.apache.org/blog/2018-06-15.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<h2>Overview</h2>
<p>&quot;I’ve seen Grails<sup>®</sup> code you wouldn’t believe …</p>
<p>… or how to properly write maintainable Grails applications&quot;</p>
<p>Over the years, Iván López has built a lot of different Grails applications, and he's learned from his mistakes. As an experienced Grails developer, Iván now possesses a vast amount of knowledge about how to avoid problems and pitfalls in future projects.</p>
<p>For over a year, Iván has been sharing his hard-won expertise with others, so they can benefit from his experience and write more maintainable code that's easy to read and modify.</p>
<p>In this 1-hour webinar, Iván walks you through code examples and demonstrates how to adapt them to best practices. You'll also see code examples that you should never, ever write, along with alternative solutions that will significantly improve your applications.</p>
<p>Iván says, &quot;I promise no developers were harmed in the making of this talk.&quot;</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Best practices for writing maintainable and testable Grails applications</li>
<li>How to detect bad code and tips for turning it into good code</li>
<li>Strategies for avoiding common pitfalls when writing Grails applications</li>
</ul>
<p>This webinar is an excellent learning opportunity for Grails developers who have had problems adding new features or maintaining their Grails applications and would like to improve their speed, efficiency, and debugging skills.</p>
<h2>Q&amp;A Follow-Up</h2>
<p>We had a lot of great questions at the end of this webinar. Here are Iván's responses to the questions we didn't have time to answer.</p>
<p><strong>Q:</strong> Can you just define as many UrlMapping files as you wish in your webapp's grails-app/conf, as long as they have different names but end with UrlMapping.groovy?</p>
<p><strong>A:</strong> Yes. Take a look at <a href="https://github.com/grails-core-issues-forks/multiple-url-mappings/commit/e65f85513d1bd8af89c9b36a6825e20948d17902">this commit</a> in a sample project I've created for an example.</p>
<p><strong>Q:</strong> Any best practices regarding withSession / withNewSession?</p>
<p><strong>A:</strong> My best advice is to try not to use them. In most cases, you can create regular services and annotate them with @Transactional. In the other few places in which you need them, I almost always use withNewSession because there is no session available. In any case I try to avoid this as much as I can.</p>
<p><strong>Q:</strong> Is it recommended to write business logic always in service layer?</p>
<p><strong>A:</strong> Yes it is. Think about this. Imagine that you're creating a regular Grails application that renders GSPs pages, and also you want to create some RESTful or SOAP endpoints. If you write all your business logic in services, the only thing you need to do is call those services from the different endpoints: &quot;regular&quot; controllers, RESTful controllers, and SOAP endpoints.</p>
<p>In these 3 controllers you're dealing with a different transport/communication layer and returning the same thing, but in a different format: HTTP to render HTML, HTTP to return JSON, and HTTP to return SOAP. Once you validate the parameters in these layers (and you can also share the validation logic using command objects), the only thing you need to do is call the same service with the parameters needed.</p>
<p>What I always do when developing new features in a Grails application is start with the services. I don't think about controllers, just services. This way, I can think in terms of my business logic: &quot;I need to receive these parameters, and I need to return this other thing.&quot;</p>
<p>Then I use TDD to develop the service, so I make sure that everything works.</p>
<p>After that, I go to the controllers layer, write command objects (with tests), and then write the controllers that call the services I finished in the previous step. As I already developed (and tested) my business logic when I created the services, I know that everything will work, and I just need to pass the appropriate parameters to the services.</p>
<p>Finally, when everything is done, I start up the application to make sure that everything works as expected (and it should because I have tests for everything).</p>
<p><strong>Q:</strong> I’ve noticed a lot of auto-generated code when I’m single stepping through code (e.g., transactional wrappers). Any advice on best practice for avoiding this kind of overhead?</p>
<p><strong>A:</strong> Most of that code is because of the Spring Framework. Since Grails 3, we rely a lot on AST transformations and traits to generate code during compilation to avoid that overhead.</p>
<p>For example, the Grails @Transactional annotation is applied at compile time vs. Spring @Transactional that relies on runtime proxies. The &quot;problem&quot; is that both Spring and Hibernate use runtime proxies and runtime reflection, so you can't get rid of all those wrappers.</p>
<p>If you want to avoid runtime proxies, I would suggest you take a look at <a href="https://micronaut.io/">Micronaut</a>. :)</p>
<p><a href="https://objectcomputing.com/files/7815/2933/9902/180615_Grails_Code_Webinar_slidedeck.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/lZX_lL7cxHE" frameborder="0"></iframe>]]></description><author>Iván López</author><guid>2018-06-15</guid><pubDate>Fri, 15 Jun 2018 00:00:00 GMT</pubDate></item><item><title>Grails® Mock Logging</title><link>https://grails.apache.org/blog/2018-05-24.html</link><description><![CDATA[</p>
<p>In Grails<sup>®</sup> 3 applications, logging is handled by the <a href="https://grails.apache.org/docs/latest/guide/conf.html#logging">Logback logging framework</a>. Grails artifacts are configured with logging out of the box. The developer simply invokes <code>log.info(&quot;log whatever&quot;)</code> and it works. But how do we create unit tests that assert that logs occur with the appropriate level?</p>
<p>This blog will highlight some mock logging techniques and when to use them.</p>
<h2>Default Grails Logging in Unit Tests</h2>
<p>First let's get the obvious out of the way for clarity. If you are not concerned about testing how logs operate in your application, there is no reason to worry about mocking loggers in Grails apps.</p>
<p>Since the logger is already present in Grails controllers, services, and domain objects there is no need to mock the logger when running unit tests. When a unit test is run with <a href="https://testing.grails.org/latest/guide/index.html">Grails Testing Support</a>, the logger will execute just as in does in production mode. In this scenario, we can say the logger as already &quot;mocked&quot; for the purpose of focusing on the <a href="https://wiki.c2.com/?ClassUnderTest">Class Under Test</a>. This is distinct from the scenario of actually verifying logging occurs, which we will dive into next.</p>
<h2>Verify Logging with Tests</h2>
<p>What if we want to assert that a certain log occurs with a particular log level? For example, let's say we want to test that that the method below prints friendly advice based on the <code>age</code> parameter.</p>
<pre><code class="language-groovy">package mock.logging

class AgeService {

    void offerAgeAdvice(int age) {

        if (age &lt; 0) {
            log.error (&quot;You cannot be $age years old!&quot;)
        } else if (age in 0..&lt;30) {
            log.info (&quot;You are a young and vibrant :) Age $age&quot;)
            log.info (&quot;Live life to the fullest&quot;)
        } else if (30 &lt;= age) {
            log.warn (&quot;It's all downhill from here, sorry. Age $age&quot;)
        }

    }
}
</code></pre>
<p>In this scenario we need to mock the logger and capture the message passed in. Then we can assert that the message is correct and also assert the appropriate log level was used in each scenario. Conceptually, this is pretty easy. But in practice not so much.</p>
<h2>Why Not Use Spock?</h2>
<p>One would think that we should simply mock out the logger with <code>def mockLogger = Mock(Logger)</code>, then set the service in the unit test with <code>service.log = mockLogger</code>. We could proceed to check the arguments passed in and also the number of times <code>service.log</code> is called with spock programming. However, in Grails apps we run into a few basic problems while trying to mock with native spock or even <a href="https://groovy-lang.org/testing.html#_mockfor_and_stubfor">Groovy MockFor</a>.</p>
<p>Logback is the default framework and the <a href="https://logback.qos.ch/apidocs/ch/qos/logback/classic/Logger.html">Logger</a> is <code>final</code>. We cannot mock a final class. Furthermore, the injected <code>log</code>property in Grails artifacts is a read-only property and cannot be set. These two fundamental problems prohibit spock mocks from being effective in most mock logging situations in Grails apps.</p>
<h2>Use Mockito to Verify Log Events</h2>
<p>The <a href="https://site.mockito.org/">Mockito</a> Library can be used to verify logs take place. With Mockito, we can create a mock <code>Appender</code> class, attach it to the logger, and then use an <code>ArgumentCaptor</code> to capture the invocations sent to the logger.</p>
<p>build.gradle</p>
<pre><code class="language-groovy">dependencies { 
    ...
    testCompile &quot;org.mockito:mockito-core:2.+&quot;
}
</code></pre>
<p>Spock test with Mockito</p>
<pre><code class="language-groovy">    void &quot;verify logging with mockito appender&quot;() {
        when: &quot;we attach a mocked appender to the logger&quot;
        Appender mockedAppender = Mockito.mock(Appender)
        Logger logger = LoggerFactory.getLogger(&quot;mock.logging.AgeService&quot;)
        logger.addAppender(mockedAppender)

        service.offerAgeAdvice(22)

        ArgumentCaptor&lt;Appender&gt; argumentCaptor = ArgumentCaptor.forClass(Appender)
        Mockito.verify(mockedAppender,
                       Mockito.times(2)).doAppend(argumentCaptor.capture())
        logger.detachAppender(mockedAppender)

        then: &quot;we capture the arguments and verify log statements occurred&quot;
        argumentCaptor.getAllValues().size() == 2
        List&lt;LoggingEvent&gt; loggingEvents = argumentCaptor.getAllValues()
        loggingEvents[0].getMessage() == &quot;You are a young and vibrant :) Age 22&quot;
        loggingEvents[0].getLevel() == Level.INFO
        loggingEvents[1].getMessage() == &quot;Live life to the fullest&quot;
        loggingEvents[1].getLevel() == Level.INFO
    }
</code></pre>
<h2>Use Slf4j Test to Verify Log Events</h2>
<p><a href="https://projects.lidalia.org.uk/slf4j-test/">Slf4j Test</a> is a test implementation of Slf4j that stores log messages in memory and provides messages for retrieving them. This works nicely to substitute for the real implementation in the test environment of Grails apps.</p>
<p>In <code>build.gradle</code>, we first need to depend on the jar, and then exclude the real implementation from the test environment. It is quite simple to check the logging events.</p>
<p>build.gradle</p>
<pre><code class="language-groovy">dependencies { 
    ...
    testCompile 'uk.org.lidalia:slf4j-test:1.1.0'
}

configurations {
    testCompile.exclude group: 'ch.qos.logback', module: 'logback-classic'
}
</code></pre>
<p>Spock test with Slf4j Test</p>
<pre><code class="language-groovy">    void &quot;verify logging with slf4j-test&quot;() {
        when:
        TestLogger logger = TestLoggerFactory.getTestLogger(&quot;logging.AgeService&quot;)

        service.offerAgeAdvice(-1)

        ImmutableList&lt;LoggingEvent&gt; loggingEvents = logger.getLoggingEvents()

        then:
        loggingEvents.size() == 1
        loggingEvents[0].message == &quot;You cannot be -1 years old!&quot;
        loggingEvents[0].level == uk.org.lidalia.slf4jext.Level.ERROR
    }
</code></pre>
<h2>Use Spock Mocks With a Declared Logger</h2>
<p>Spock mocks can be used on one particular case: with your own declared logger variable. If defined as non-final, you can use spock mocks to verify log calls. This approach is straightforward, but has the drawback that each class will have repeated code and does not rely on Grails conventions.</p>
<p>For example, use a <code>LoggerFactory</code> to define a logger in a class.</p>
<pre><code class="language-groovy">package mock.logging

import org.slf4j.Logger
import org.slf4j.LoggerFactory

/**
 * Non grails groovy class with a declared Slf4j logging object
 */
class DeclaredSlf4jService {

    private static Logger log = LoggerFactory.getLogger(DeclaredSlf4jService)

    void logSomething() {
        println &quot;*********** log in the class ******&quot; + log.dump()
        log.info(&quot;Live life to the fullest&quot;)
    }
</code></pre>
<p>Then a spock Specification with <code>Mock()</code> follows the normal spock conventions to verify invocations and parameters.</p>
<pre><code class="language-groovy">package mock.logging

import org.slf4j.Logger
import spock.lang.Specification

class DeclaredSlf4jServiceSpec extends Specification {

    DeclaredSlf4jService declaredSlf4jService = new DeclaredSlf4jService()
    def mockLogger = Mock(Logger)

    def setup() {
        declaredSlf4jService.log = mockLogger
    }

    def cleanup() {
    }

    void &quot;test mock with spock on declared logger&quot;() {
        when:
        declaredSlf4jService.logSomething()

        then:
        1 * mockLogger.info(&quot;Live life to the fullest&quot;)
    }
}
</code></pre>
<h2>Sample Code</h2>
<p>Sample code of Grails mocking logging can be found here. I hope these examples can help you decide on the best approach for your project.</p>
<ul>
<li><a href="https://github.com/niravassar/mock-logging-slf4j-test">https://github.com/niravassar/mock-logging-slf4j-test</a></li>
<li><a href="https://github.com/niravassar/mock-logging">https://github.com/niravassar/mock-logging</a></li>
</ul>]]></description><author>Nirav Assar</author><guid>2018-05-24</guid><pubDate>Thu, 24 May 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: Groovy 2.5+ Roadmap with Paul King</title><link>https://grails.apache.org/blog/2018-05-18.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/groovy.html"><span class="hashtag">#groovy</span></a></p>
<p>In this webinar, <a href="https://objectcomputing.com/products/2gm-team#king">Paul King</a> introduces you to the latest features in Groovy 2.5 and offers a peek at what's planned for Groovy 3.0, including new AST transforms, new macro features, the new Parrot parser, and myriad other miscellaneous features.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar.</p>
<ul>
<li>AST Macros – write AST transformations and code generation or matching code in a Groovy friendly syntax</li>
<li>AST Transformations – new transforms and improvements including revamped versions of @Canonical and @Immutable</li>
<li>New DGM capabilities and library improvements – tap command, miscellaneous improvements</li>
<li>Improved tool support, including groovysh and Groovy console</li>
<li>Improvements throughout the libraries – JSON improvements, CliBuilder with annotations</li>
<li>The Parrot Parser – Java syntax alignment, new features, advanced capabilities</li>
<li>JDK9: support, limitations and on-going work</li>
</ul>
<p><a href="https://objectcomputing.com/files/7715/2708/5312/180518-Groovy-Update-slide-deck.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/ECZVbiFZPwE" frameborder="0"></iframe>]]></description><author>Paul King</author><guid>2018-05-18</guid><pubDate>Fri, 18 May 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: Database Migration with Grails® 3</title><link>https://grails.apache.org/blog/2018-04-06.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<h2>Overview</h2>
<p>Database migrations are an important facet of web development. Preserving existing data while seamlessly adding new functionality and tables is critical when making incremental database changes to production applications.</p>
<p>Without a tool to manage database migrations, developers end up cobbling together solutions using manual SQL, error-prone communication processes, and costly risk management strategies.</p>
<p>In this webinar, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#assar">Nirav Assar</a>, demonstrates how to apply the Grails Database Migration plugin in development and production.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Fundamental database management concepts</li>
<li>Overview of database migration tools</li>
<li>Demonstration of the Grails Database Migration plugin</li>
<li>Live coding examples representing real-world use cases</li>
<li>Advanced scenarios and best practices</li>
</ul>
<p><a href="https://objectcomputing.com/files/2715/2338/5917/180409-Database_Migration_Grails_3_Webinar_Deck.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/rNdfozn7NCs" frameborder="0"></iframe>]]></description><author>Nirav Assar</author><guid>2018-04-06</guid><pubDate>Fri, 06 Apr 2018 00:00:00 GMT</pubDate></item><item><title>Introducing the Grails® 3 GORM Logical Delete Plugin</title><link>https://grails.apache.org/blog/2018-04-05.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a> <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
<p>Recently our development team came upon the need to develop a Grails<sup>®</sup> 3 plugin that implements logical delete for entities.</p>
<p>A &quot;logical&quot; delete (sometimes referred to as a &quot;soft&quot; delete) is a delete that doesn’t actually delete the relevant data but instead marks the data as deleted. Marking the data as deleted has the benefit of excluding the data from queries by default, while still maintaining the ability to retrieve the data when/if necessary. Essentially the plugin offers a mechanism to &quot;hide&quot; domain objects from retrieval. This is useful for retaining data without having it clutter the current set of active data.</p>
<p>Logical Delete functionality is available in a few Grails 2 plugins. However these implementations rely on filters, ASTs, and runtime metaClass enhancements. We decided to create another implementation of the logical delete using some of latest Grails 3 features such as Traits and Listeners.</p>
<p>This blog will highlight how to use the plugin and also give some insight into the techniques used under the covers.</p>
<hr />
<h2>Summary</h2>
<p><a href="https://grails-plugins.github.io/gorm-logical-delete/">GORM Logical Delete Plugin</a></p>
<p>Logical delete of an entity has a few relevant use cases in enterprise applications. Companies may want to &quot;delete&quot; data from their everyday usage, but still keep it for later retrieval. Auditing requirements for financial institutions may require the data to be sustained for up to seven years.</p>
<p>From a technical perspective, if a domain model has several complex associations that make a chain of domain objects, hard deletion may cause slow cascading affects or be blocked by referential integrity. In these situations, a logical delete alleviates these concerns.</p>
<h2>Installation</h2>
<p>To add the GORM Logical Delete plugin to an application, add the following dependency to the dependencies block of your <code>build.gradle</code>:</p>
<pre><code class="language-groovy">compile &quot;org.grails.plugins:gorm-logical-delete:2.0.0.M2&quot;
</code></pre>
<h2>Enable Domain Entity with Logical Delete</h2>
<p>Any domain entity can be implemented with the <code>LogicalDelete</code> trait. The trait adds a boolean persistent property named <code>deleted</code> to the domain class. The property is used to &quot;hide&quot; entities from queries if it is set to <code>true</code>. Note the mapping columns can customize the property to a database column name.</p>
<pre><code class="language-groovy">import gorm.logical.delete.LogicalDelete

class Person implements LogicalDelete&lt;Person&gt; {
    String userName

    static mapping = {
        // the deleted property may be configured
        // like any other persistent property...
        deleted column:&quot;delFlag&quot;
    }
}
</code></pre>
<p>In order to delete a domain object enabled with logical delete, simply use the same GORM interface as usual.</p>
<pre><code class="language-groovy">Person p = new Person(userName: &quot;Nirav&quot;).save()
p.delete()
</code></pre>
<p>If you would like to physically delete the record from persistence, use the attribute <code>hard: true</code>:</p>
<pre><code class="language-groovy">p.delete(hard: true)
</code></pre>
<p>Undelete functionality is quite handy if you want to reverse the property to false.</p>
<pre><code class="language-groovy">Person.withDeleted {
    Person p = Person.get(id)
    p?.unDelete()
}
</code></pre>
<h2>Querying Objects</h2>
<p>When an object is enabled with logical delete, queries associated with the domain object will hide those marked with <code>deleted = true</code>.</p>
<p>Dynamic Finders, Criteria Query, Detached Criteria Query, and the <code>GormEntity</code> methods like <code>get</code>, <code>load</code>, <code>proxy</code>, and <code>read</code> are all supported.</p>
<p>See the <a href="https://grails-plugins.github.io/gorm-logical-delete/snapshot/index.html#_queries">Query documentation</a> for a list of examples.</p>
<blockquote>
<p>Note Hibernate Criteria and HQL queries are NOT supported by this plugin as they are ORM implementation specific.</p>
</blockquote>
<h2>Behind The Scenes</h2>
<p>It's beneficial to understand how the plugin is implemented under the covers. We have tried to use the most efficient techniques with Groovy and the Grails framework, which reduces some of the noise and clutter found in previous plugin implementations.</p>
<p>In concept, what is occurring is that any domain object can be given a logical delete capability with the attribute <code>deleted</code>. When the entity is logically deleted, it is set to <code>true</code>. It is not physically deleted from persistence. During query time, a query event is intercepted by a listener and the query is altered to only include <code>deleted = false</code> items from the result set. This gives the illusion that the items are not present, but in reality they are just hidden by the query.</p>
<h2>LogicalDelete</h2>
<p>The <a href="https://grails-plugins.github.io/gorm-logical-delete/snapshot/api/gorm/logical/delete/LogicalDelete.html"><code>LogicalDelete</code></a> trait makes available a <code>deleted</code> attribute. As stated earlier, an entity can implement this.</p>
<p>The <code>LogicalDelete</code> trait has overridden static methods which take into account the <code>deleted</code> property in an altered query. This allows the client to use the <code>GormEntity</code> methods to essentially hide those items.</p>
<h2>PreQueryListener</h2>
<p>The <a href="https://grails-plugins.github.io/gorm-logical-delete/snapshot/api/gorm/logical/delete/PreQueryListener.html"><code>PreQueryListener</code></a> implements <code>ApplicationListener</code> and when the event fires, it will add a <code>deleted</code> equals <code>false</code> to the query.</p>
<p>The <code>ThreadLocal</code> variable <code>IGNORE_DELETED_FILTER</code> should also be noted. When set to <code>true</code>, then all entities that exist in the database are included in the query. In other words, it bypasses the logical delete flag all together. In <code>LogicalDelete</code>, note how this <code>ThreadLocal</code> variable is used in the <code>withDeleted</code> method. The method is passed in a closure (which is a query) and the variable is set to <code>true</code>, which bypasses the delete flag.</p>
<p><a href="https://grails-plugins.github.io/gorm-logical-delete/snapshot/api/org/gorm/logical/delete/ast/WithDeletedTransformation.html"><code>WithDeletedTransformation</code></a> essentially achieves the same goal, but is intended as an implementation for an annotation.</p>
<p>The spock tests contained in the plugin are a good resource to reference examples and usages of the plugin API.</p>
<p>Take a look and we hope the plugin is useful for your needs.</p>]]></description><author>Nirav Assar</author><guid>2018-04-05</guid><pubDate>Thu, 05 Apr 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: Build a Better API with GORM &amp; GraphQL</title><link>https://grails.apache.org/blog/2018-03-09.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a> <a href="https://grails.apache.org/blog/tag/graphql.html"><span class="hashtag">#graphql</span></a></p>
<h2>Overview</h2>
<p>GraphQL is an exceptional technology that allows APIs to be more efficient and expressive. GORM is the object relational mapper used by Grails<sup>®</sup> apps that enables developers to interact with both relational and document databases through the declaration of simple Groovy classes.</p>
<p>In this 55-minute webinar, 2GM (Groovy, Grails framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#kleeh">James Kleeh</a>, discusses in depth a new GORM extension and Grails plugin that combine these two great technologies and increase developer productivity.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar.</p>
<ul>
<li>GORM Introduction</li>
<li>GraphQL Introduction</li>
<li>Comparison of GraphQL vs REST</li>
<li>GORM-GraphQL Features</li>
<li>GORM-GraphQL Customizations</li>
<li>GORM-GraphQL Testing</li>
</ul>
<p>This webinar is an excellent learning opportunity for developers who wish to improve the efficiency and expressiveness of their APIs.</p>
<p><a href="https://objectcomputing.com/files/2115/2088/9809/180309-GORM-GraphQL-Webinar-Deck.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/KphmxzIaVf0" frameborder="0"></iframe>]]></description><author>James Kleeh</author><guid>2018-03-09</guid><pubDate>Fri, 09 Mar 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: Browser Automation Testing with Geb &amp; the Grails® Framework</title><link>https://grails.apache.org/blog/2018-03-06.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/geb.html"><span class="hashtag">#geb</span></a></p>
<p>Geb brings together the power of WebDriver, the elegance of jQuery content selection, the robustness of page-object modeling, and the expressiveness of the Groovy language. Together with Spock, Geb integrates into Grails<sup>®</sup> apps to ease the creation of functionals/acceptance tests.</p>
<p>In this webinar, Geb Lead, Marcin Erdmann, and Grails team member, Sergio del Amo Caballero, discuss how Geb integrates seamlessly into the Grails workflow and how this combination leads to robust and well-tested applications.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/E7zjib3wrxk" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero &amp; Marcin Erdmann</author><guid>2018-03-06</guid><pubDate>Tue, 06 Mar 2018 00:00:00 GMT</pubDate></item><item><title>Grails® Development with Groovy Eclipse</title><link>https://grails.apache.org/blog/2018-03-02.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/groovy.html"><span class="hashtag">#groovy</span></a> <a href="https://grails.apache.org/blog/tag/eclipse.html"><span class="hashtag">#eclipse</span></a> <a href="https://grails.apache.org/blog/tag/gradle.html"><span class="hashtag">#gradle</span></a></p>
<p>In this blog post, we show the steps necessary to set up <a href="https://www.eclipse.org">Eclipse IDE</a> to develop Grails<sup>®</sup> 3 applications.</p>
<h2>Groovy Eclipse</h2>
<p>First step is to install <a href="https://github.com/groovy/groovy-eclipse">Groovy Eclipse</a>. Check the <a href="https://github.com/groovy/groovy-eclipse/wiki#how-to-install">installation instructions</a>.</p>
<p>Once, you have set up Groovy Eclipse, set up the compiler to use Groovy 2.4.13; the version used by the latest stable release of Grails 3.3.2.</p>
<p><img src="2018-03-02-img01.png" alt="Set up Groovy Compiler at Eclipse" /></p>
<h2>Eclipse Spock Plugin</h2>
<p>Install <a href="https://marketplace.eclipse.org/content/spock-plugin">Eclipse Spock Plugin</a></p>
<p><img src="2018-03-02-img02.png" alt="Eclipse Spock Plugin" /></p>
<h2>Buildship Gradle Plugin</h2>
<p>Install <a href="https://projects.eclipse.org/projects/tools.buildship">Buildship Gradle plugin</a>.</p>
<p><img src="2018-03-02-img03.png" alt="Buildship Gradle plugin" /></p>
<p>We are going to rely on Gradle tasks to drive our Grails development in Eclipse. Thus, you may want to enable Gradle views.</p>
<p><img src="2018-03-02-img04.png" alt="Gradle Views" /></p>
<h2>Gradle Tips</h2>
<p>When you work often with Gradle it becomes useful to get a verbose output while you run your tests:</p>
<pre><code class="language-groovy">tasks.withType(Test) {
      beforeTest { descriptor -&gt; logger.quiet &quot; -- $descriptor&quot; }
     testLogging {
         events &quot;passed&quot;, &quot;skipped&quot;, &quot;failed&quot;
         exceptionFormat 'full'
     }
 }
</code></pre>
<h3>Common Grails Gradle Tasks</h3>
<p>Run your app</p>
<p><code>./gradlew bootRun</code></p>
<p>Run unit tests</p>
<p><code>./gradlew test</code></p>
<p>Run integration/functional tests</p>
<p><code>./gradlew integrationTest</code></p>
<p>Run ALL tests unit/integration/functional</p>
<p><code>./gradlew check</code></p>
<p>Clean</p>
<p><code>./gradlew clean</code></p>
<p>Build your artifacts</p>
<p><code>./gradlew assemble</code></p>
<p>Dependency report</p>
<p><code>./gradlew dependencies</code></p>]]></description><author>Sergio Del Amo Caballero</author><guid>2018-03-02</guid><pubDate>Fri, 02 Mar 2018 00:00:00 GMT</pubDate></item><item><title>Webinar: Developing React Apps with Grails® 3</title><link>https://grails.apache.org/blog/2018-02-09.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a> <a href="https://grails.apache.org/blog/tag/react.html"><span class="hashtag">#react</span></a> <a href="https://grails.apache.org/blog/tag/javascript.html"><span class="hashtag">#javascript</span></a></p>
<h2>Overview</h2>
<p>React is the JavaScript view library from our friends at Facebook. Rather than providing a &quot;full-stack framework&quot; for the front end, React focuses entirely on being the 'V' in MVC.</p>
<p>In this 60-minute webinar, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#klein-z">Zachary Klein</a>, demonstrates how to leverage React in your projects. You'll learn several ways to use these two frameworks together and get an introduction to the React profile for Grails apps.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Overview of React and build tooling</li>
<li>3 Approaches to building Grails projects with React</li>
<li>The React profile</li>
<li>Spring Security REST</li>
<li>Unified deployment</li>
</ul>
<p>This webinar is a useful tutorial for Grails developers interested in adding React or another front-end framework/library to their projects. Front-end developers are also encouraged to discover what the Grails framework has to offer in a modern web development workflow.</p>
<p><a href="https://objectcomputing.com/files/9315/1855/8037/2018-02-09-Grails-React-Webinar-Slides.pdf">Slides</a></p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/tjQHQDwaxto" frameborder="0"></iframe>]]></description><author>Zachary Klein</author><guid>2018-02-09</guid><pubDate>Fri, 09 Feb 2018 00:00:00 GMT</pubDate></item><item><title>Quickcast #9: GORM Many-to-One Relationship – Replacing a Collection</title><link>https://grails.apache.org/blog/2018-02-08.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>GORM, a powerful Groovy-based data-access toolkit for the JVM, enables simplified creation of many-to-one relationships.</p>
<p>In this short video tutorial, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio Del Amo Caballero</a>, explains how to efficiently replace a many-to-one collection with a minimal number of queries and by leveraging cascade behavior.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/7Ypy6osALxY" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2018-02-08</guid><pubDate>Thu, 08 Feb 2018 00:00:00 GMT</pubDate></item><item><title>Grails® Test Leakage</title><link>https://grails.apache.org/blog/2017-12-05.html</link><description><![CDATA[</p>
<p>From Rob Fletcher book, <a href="https://shop.oreilly.com/product/0636920038597.do">Spock: Up and Running</a></p>
<blockquote>
<p>TEST LEAKAGE</p>
<p>A very important feature of any unit test is that it should be idempotent. That is to say, the test should produce the same result regardless of whether it is run alone or with other tests in a suite and regardless of the order in which the tests in that suite are run. When side effects from a test affect subsequent tests in the suite, we can describe that test as leaking.
Test leakage is caused by badly managed resources. Typical causes of leakage include data in a persistent store that is not removed, changes to a class’ metaclass that are unexpectedly still in place later, mocks injected into objects reused between tests, and uncontrolled changes to global state such as the system clock.
Test leakage can be very difficult to track down. Simply identifying which test is leaking can be time consuming. For example, the leaking test might not affect the one running directly after it, or continuous integration servers might run test suites in a different order from that of the developer’s computers, leading to protests of but, it works on my machine!”</p>
</blockquote>
<p>In this blog post, we discuss how to avoid test leakage in Grails<sup>®</sup> integration and functional tests. In particular, <em>data in a persistent store that is not removed</em>.</p>
<p>Lets us create a simple Grails App:</p>
<pre><code>curl -O start.grails.org/myapp.zip -d version=3.3.2 -d profile=rest-api
</code></pre>
<p>with a Domain Class</p>
<p><em>grails-app/domain/demo/Book.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.rest.Resource

@Resource
class Book {
    String title
}
</code></pre>
<p>and a GORM Data Service</p>
<p><em>grails-app/services/demo/BookDataService.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.gorm.services.Service

@Service(Book)
interface BookDataService {
    Book saveBook(String title)
    void deleteBook(Serializable id)
    int count()
}
</code></pre>
<h2>Integration Test</h2>
<p>If you create the next integration specification:</p>
<p><em>src/integration-test/groovy/demo/BookDataServiceSpec.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.testing.mixin.integration.Integration
import spock.lang.Specification

@Integration
class BookDataServiceSpec extends Specification {

    BookDataService bookDataService

    void &quot;test save book&quot;() {
        when:
        Book book = bookDataService.saveBook('Practical Grails 3')

        then:
bookDataService.count() == old(bookDataService.count()) + 1
        book
    }
}
</code></pre>
<p>You will have a test leakage. After the specification is executed, the <code>book</code> database table will be:</p>
<table>
    <thead><tr><th>id</th><th>title</th></tr></thead>
    <tbody><tr><td>1</td><td>Practical Grails 3</td></tr></tbody>
</table>
<p>The previous test leaks one <code>book</code> row.</p>
<p>To solve it, you could add a cleanup block:</p>
<p><em>src/integration-test/groovy/demo/BookDataServiceSpec.groovy</em></p>
<pre><code class="language-groovy">@Integration
class BookDataServiceSpec extends Specification {

    BookDataService bookDataService

    void &quot;test save book&quot;() {
        when:
        Book book = bookDataService.saveBook('Practical Grails 3')

        then:
        Book.count() == old(Book.count()) + 1

        cleanup: 
        bookDataService.deleteBook(book.id)
    }
}
</code></pre>
<p>or use <code>@Rollback</code> annotation.</p>
<blockquote>
<p>The Rollback annotation ensures that each test method runs in a transaction that is rolled back. Generally this is desirable because you do not want your tests depending on order or application state.</p>
</blockquote>
<p><em>src/integration-test/groovy/demo/BookDataServiceSpec.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.gorm.transactions.Rollback
import grails.testing.mixin.integration.Integration
import spock.lang.Specification

@Rollback
@Integration
class BookDataServiceSpec extends Specification {

    BookDataService bookDataService

    void &quot;test save book&quot;() {
        when:
        Book book = bookDataService.saveBook('Practical Grails 3')

        then:
        bookDataService.count() == old(bookDataService.count()) + 1
        book
    }
}
</code></pre>
<h2>Functional Test</h2>
<p>You may have noticed that we have annotated the Domain class with <code>@Resource</code> transformation.</p>
<blockquote>
<p>Simply by adding the Resource transformation and specifying a URI, your domain class will automatically be available as a REST resource in either XML or JSON formats. The transformation will automatically register the necessary RESTful URL mapping and create a controller called BookController.</p>
</blockquote>
<p>We add a functional test to test the API exposed by the transformation:</p>
<p><em>src/integration-test/groovy/demo/BookResourceSpec.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.plugins.rest.client.RestBuilder
import grails.plugins.rest.client.RestResponse
import grails.testing.mixin.integration.Integration
import groovy.json.JsonOutput
import spock.lang.Specification

@Integration
class BookResourceSpec extends Specification {

    BookDataService bookDataService

    void &quot;test save book&quot;() {
        given:
        RestBuilder restBuilder = new RestBuilder()

        when:
        RestResponse resp = restBuilder.post(&quot;http://localhost:${serverPort}/book&quot;) {
            accept('application/json')
            contentType('application/json')
            json(JsonOutput.toJson([title: 'Practical Grails 3']))
        }

        then:
        bookDataService.count() == old(bookDataService.count()) + 1
        resp.json.id
    }
}
</code></pre>
<p>The previous tests causes a test leakage. After the specification is executed, the <code>book</code> database table will be:</p>
<table>
    <thead><tr><th>id</th><th>title</th></tr></thead>
    <tbody><tr><td>1</td><td>Practical Grails 3</td></tr></tbody>
</table>
<p>You may be tempted to add a <code>@Rollback</code> annotation to the functional test. However, that will not solve
the test leakage. <code>@Rollback</code> only impacts changes within the test method. By using a REST
client you are sending requests to the server which run the changes in a completely
different thread, thus the same transaction management doesn't apply.</p>
<p>You can solve the functional test leakage by adding a <code>cleanup</code> block.</p>
<p><em>src/integration-test/groovy/demo/BookResourceSpec.groovy</em></p>
<pre><code class="language-groovy">package demo

import grails.plugins.rest.client.RestBuilder
import grails.plugins.rest.client.RestResponse
import grails.testing.mixin.integration.Integration
import groovy.json.JsonOutput
import spock.lang.Specification

@Integration
class BookResourceSpec extends Specification {

    BookDataService bookDataService

    void &quot;test save book&quot;() {
        given:
        RestBuilder restBuilder = new RestBuilder()

        when:
        RestResponse resp = restBuilder.post(&quot;http://localhost:${serverPort}/book&quot;) {
            accept('application/json')
            contentType('application/json')
            json(JsonOutput.toJson([title: 'Practical Grails 3']))
        }

        then:
        bookDataService.count() == old(bookDataService.count()) + 1
        resp.json.id

        cleanup:
        bookDataService.deleteBook(resp.json.id as Serializable)
    }
}
</code></pre>
<p>To sump up, be careful when writing integration and functional tests to avoid test leakage.
While <code>@Rollback</code> annotation may help you in integration tests, you will need to
manually cleanup in functional tests.</p>]]></description><author>Sergio Del Amo Caballero</author><guid>2017-12-05</guid><pubDate>Tue, 05 Dec 2017 00:00:00 GMT</pubDate></item><item><title>Eric Helgeson Named 2017 Grails® Rock Star</title><link>https://grails.apache.org/blog/2017-11-30.html</link><description><![CDATA[</p>
<p>The Grails<sup>®</sup> Rock Star Award recognizes a member of the Grails Community for his or her outstanding contributions to the success of the Framework.</p>
<p>Yesterday at G3 Summit 2017, Eric Helgeson was awarded the Grails Rock Star Award. Eric is the author of the book <a href="https://www.grails3book.com/">Practical Grails 3</a>, and he is often seen in the <a href="https://grails.slack.com/">Grails Slack Community</a> answering and helping other users. Moreover, Eric contributes to the Grails Community with code, plugin development, issues reporting, etc.</p>
<p>Also, Graeme Rocher and Jeff Scott Brown, Grails framework co-founders, were awarded Grails lifetime contributor awards for their contributions in the past decade to the framework success.</p>
<p><strong>Congratulations to Eric, Graeme, and Jeff for these well deserved awards.</strong></p>
<p><img src="2017-11-30-img01.png" alt="Eric Helgeson, Graeme Rocher, and Jeff Scott Brown were honored at G3 Summit 2017 for their contributions to the Grails framework." /></p>]]></description><author>Sergio Del Amo Caballero</author><guid>2017-11-30</guid><pubDate>Thu, 30 Nov 2017 00:00:00 GMT</pubDate></item><item><title>Grails® React Profiles</title><link>https://grails.apache.org/blog/2017-11-21.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
<p>As of Grails<sup>®</sup> 3.3.2, there are now two distinct <a href="https://grails.apache.org/docs/latest/guide/profiles.html">Profiles</a> for using <a href="https://reactjs.org/">React</a> in your Grails projects. These profiles are essentially the same as those described in the <a href="/blog/2017-11-21.html">announcement post</a>, with some updates.</p>
<h2>React-Webpack Profile for Grails apps</h2>
<p>This profile provides a monolithic project structure with React code embedded within the Grails project. Formerly, to use this version of the profile you had to specific it's version explictly. Now, this profile can be used when creating a new Grails 3.3.2 app like so:</p>
<pre><code>grails create-app myapp -profile react-weback
</code></pre>
<p>You can also choose this project when generating your project from the <a href="https://start.grails.org/">Grails Application Forge</a>, either from the web app or via the API:</p>
<pre><code>curl -O start.grails.org/myapp.zip -d profile=react-webpack
</code></pre>
<p>Besides the convenience of having a distinct name for the project, the new name better reflects the dependence of the <code>react-webpack</code> profile on its parent profile, <code>webpack</code>. You can use the <code>webpack</code> profile directly if you want to pick your own frontend JavaScript libraries in your project.</p>
<p>The documentation for the <code>react-webpack</code> profile is available at <a href="https://grails-profiles.github.io/react-webpack/latest"><code>https://grails-profiles.github.io/react-webpack/latest</code></a></p>
<h2>New Start Task</h2>
<p>The <code>react</code> profile now provides both <code>start</code> and <code>bootRun</code> tasks for the <code>client</code> project. <code>bootRun</code> is intended to be used when running both <code>server</code> and <code>client</code> in parallel; otherwise, the client app can now be started using either <code>./gradlew start</code> or <code>yarn start</code> /<code>npm start</code>.</p>
<p>The documentation for the <code>react</code> profile is available at <a href="https://grails-profiles.github.io/react/latest"><code>https://grails-profiles.github.io/react/latest</code></a></p>
<h2>React 16</h2>
<p>Both the <code>react</code> and <code>react-webpack</code> profiles have been upgraded to use React 16. In addition, the <code>react</code> profile is now using the latest (1.0.17, as of time of writing) release of <a href="https://github.com/facebookincubator/create-react-app"><code>create-react-app</code></a>.</p>
<h2>Known Issues</h2>
<p>Both of these profiles (as well as the <code>angular</code> profile) leverage the <a href="https://github.com/node-gradle/gradle-node-plugin">Gradle Node Plugin</a> to wrap the Node.js build tools when running via Grails or Gradle commands.</p>
<p>Unfortunately, there are a couple of issues with the underlying Gradle task management with this plugin. In particular, the following two issues are known and being investigated:</p>
<ol>
<li>Node process sometimes fails to stop when run from Gradle. This is due to an issue in <a href="https://github.com/gradle/gradle/issues/1128">Gradle</a>. You may need to kill the process manually in order to restart the app.</li>
<li>Errors when running React tests via Gradle. This error seems to be specific to the latest versions of macOS. A related issue has been <a href="https://github.com/facebook/jest/issues/1767">reported against Jest</a>, the testing framework used in this profile for React tests. One workaround is to not use Gradle to manage the Node.js installation - instead, you can install Node manually (or using <a href="https://github.com/objectcomputing/grails-team-blog/blob/gh-pages/_posts/javascript">NVM</a>), and then set the <code>download</code> flag in the Gradle-Node plugin config to <code>false</code> in <code>build.gradle</code>:</li>
</ol>
<pre><code>node {
    version = '8.7.0'
    yarnVersion = '1.3.2'
    download = false
</code></pre>
<p>You can now run the tests either using <code>./gradlew client:test</code>, or <code>yarn test</code>.</p>]]></description><author>Zachary Klein</author><guid>2017-11-21</guid><pubDate>Tue, 21 Nov 2017 00:00:00 GMT</pubDate></item><item><title>Webinar: Grails® 3 for Spring Developers</title><link>https://grails.apache.org/blog/2017-11-09.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/webinar.html"><span class="hashtag">#webinar</span></a></p>
<h2>Overview</h2>
<p>Grails<sup>®</sup> 3 is a full stack framework built on top of Spring Boot. In addition to all of the capabilities offered by Boot, developers using Grails 3 benefit from the enormous productivity gains and other features (e.g., GORM, Profiles, etc.) that Grails 3 packs in!</p>
<p>In this webinar, Spring Developer Advocate, Josh Long (@starbuxman), and Grails framework co-founder, Jeff Scott Brown (@jeffscottbrown), introduce the Grails framework from the perspective of a Spring developer and demonstrate how these awesome technologies play so well together.</p>
<p>The session will be of interest to anyone looking to build robust JVM web applications with high productivity, while keeping the application code expressive and simple.</p>
<p>Grails developers will find many interesting tips and tricks during the demonstrations but no prior experience with the Grails framework is necessary.</p>
<h2>Outline</h2>
<p>The following topics are covered in this webinar:</p>
<ul>
<li>Quick Intro to Spring &amp; the Grails framework</li>
<li>REST</li>
<li>JSON views</li>
<li>Testing</li>
<li>Plugins</li>
<li>Security</li>
<li>Deployment</li>
<li>Customizing Spring Boot in a Grails app</li>
</ul>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/71Avk4IcEPs" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown &amp; Josh Long</author><guid>2017-11-09</guid><pubDate>Thu, 09 Nov 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #8: Grails® React Profile</title><link>https://grails.apache.org/blog/2017-10-30.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.apache.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
<p>In this short video tutorial, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#klein-z">Zachary Klein</a>, demonstrates how to use the Grails 3 React profile to build Grails applications with a React frontend.</p>
<p>In particular, Zak shows you how to create a single project build, which allows you to mix React code with common Grails-view technologies, such as GSP.</p>
<p>Moreover, he discusses the different Gradle tasks bundled with the profile and the typical workflow you may use while using it.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/JVLn7kWkjp0" frameborder="0"></iframe>]]></description><author>Zachary Klein</author><guid>2017-10-30</guid><pubDate>Mon, 30 Oct 2017 00:00:00 GMT</pubDate></item><item><title>Grails® 3.3 GA Released</title><link>https://grails.apache.org/blog/2017-07-26.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>Just in time for <a href="https://gr8conf.us/">Gr8Conf US</a>, the <a href="https://objectcomputing.com/products/2gm-team">Grails<sup>®</sup> team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://grails.apache.org/docs/3.3.x/">Grails 3.3 GA</a>.</p>
<p>Grails 3.3 includes a number of significant improvements, most notably to GORM with GORM 6.1, which we <a href="/blog/2017-03-27.html">released earlier</a> in order to gather feedback from Grails 3.2.x users.</p>
<p>GORM 6.1 includes some real breakthrough innovations, including <a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#dataServices">Data Services</a> that allow you to define interfaces that are automatically implemented and work seamlessly with GORM's multi-tenancy features.</p>
<p>Other highlights of Grails 3.3 include the new <a href="https://async.grails.org/latest/guide/index.html#events">EventBus</a> abstraction which integrates with existing reactive libraries such as RxJava. Events are also for the first time transaction aware so that consumers are only notified if the surrounding transaction is successful, which simplifies code greatly.</p>
<p>Overall there is an abundance of new features and improvements that developers will be able to take advantage of, from the <a href="https://testing.grails.org/">new testing framework</a> to improvemments to <a href="https://views.grails.org/latest/">JSON Views</a>.</p>
<p>All of these new features and more are covered in the <a href="https://grails.apache.org/docs/3.3.x/guide/introduction.html#whatsNew">What's New guide</a>. Thanks to the Grails community who contributed greatly to making the release a success and we look forward <a href="https://github.com/apache/grails-core/issues">to your feedback</a>!</p>]]></description><author>Graeme Rocher</author><guid>2017-07-26</guid><pubDate>Wed, 26 Jul 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #7: Logging with Grails® 3</title><link>https://grails.apache.org/blog/2017-07-12.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this 20-minute video, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#caballero">Sergio del Amo Caballero</a>, introduces several tips and tricks related to logging with a Grails 3 application.</p>
<p>Sergio discusses changes to logger names in Grails 3.3 and things to bear in mind when logging in Grails artifacts and Groovy POGOs.</p>
<p>Moreover, he explains the benefits of using Slf4j, parameterized logging, how to configure rolling logging, how to use an external configuration file, and more.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/3TppFy3lq1A" frameborder="0"></iframe>]]></description><author>Sergio del Amo Caballero</author><guid>2017-07-12</guid><pubDate>Wed, 12 Jul 2017 00:00:00 GMT</pubDate></item><item><title>Running a Grails® 3 App With a Self-Signed SSL Certificate</title><link>https://grails.apache.org/blog/2017-06-28.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/ssl.html"><span class="hashtag">#ssl</span></a> <a href="https://grails.apache.org/blog/tag/deployment.html"><span class="hashtag">#deployment</span></a></p>
<p>The <a href="https://grails.apache.org/docs/latest/ref/Command%20Line/run-app.html">Grails<sup>®</sup> <em>run-app</em> command documentation</a> describes how to use the <em>-https</em> flag to serve your app over HTTPS.</p>
<blockquote>
<p>https - Start an HTTPS server (on port 8443 by default) alongside the main server. Just to be clear, the application will be accessible via HTTPS and HTTP. A self-signed key will be generated. Intended for development use only.</p>
</blockquote>
<p>If you run the following command:</p>
<pre><code>grails run-app -https // with HTTPS
</code></pre>
<p>Your app will be served at <em>https://localhost:8443</em></p>
<p>However, as stated in the documentation, the <em>https</em> flag is intended for development use only. In real-world applications, an SSL certificate from a <a href="https://en.wikipedia.org/wiki/Certificate_authority">Certificate Authority</a>, would be used to verify your application's identity with clients. However, it is also possible to generate a self-signed certificate for testing purposes. A self-signed certificate doesn't provide the identity protection that a CA offers, but the steps involved in configuring a self-signed certificate with your Grails app will be largely the same with a CA certificate.</p>
<h2>Generate Your Self-Signed SSL Certificate</h2>
<p>You can generate a self-signed certificate using the <a href="https://www.openssl.org/"><code>openssl</code></a> command-line utility. This is installed by default on most Unix-based OS's, and can be installed on <a href="https://sourceforge.net/projects/openssl-for-windows/">Windows</a> as well.</p>
<p>We can use <code>openssl</code>'s <code>req</code> command to create a self-signed certificate:</p>
<p><code>openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -days 365</code></p>
<p>We're using several command options:</p>
<ul>
<li><strong>x509</strong> This option outputs a self-signed certificate instead of a certificate request.</li>
<li><strong>newkey</strong> This option creates a new certificate request and a new private key. <code>rsa:nbits</code>, where <code>nbits</code> is the number of bits, generates an RSA key nbits in size.</li>
<li><strong>keyout</strong> This specifies the filename for the the newly created private key.</li>
<li><strong>out</strong> This specifies the output filename to write the certificate</li>
<li><strong>days</strong> When used with the <code>-x509</code> option, <code>days</code> specifies the number of days to certify the certificate for. The default is 30.</li>
</ul>
<p>You can learn about other <code>req</code> options by running <code>man req</code></p>
<p>The previous command will prompt you to supply metadata about the certificate, such as Country, Organization, etc. Moreover, it will ask you to provide a PEM pass phrase. Enter a random password and keep it safe; we will need in the next step.</p>
<p>Now you have you self-signed certificate. Unfortunately the Grails framework (and Spring Boot) doesn’t support the PEM format directly. Instead, we need to use the PKCS12 format for our keys. Fortunately, there is another <code>openssl</code> command to make the conversion:</p>
<p><code>openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 -name tomcat -caname root</code></p>
<p>Again, we're using a few options:</p>
<ul>
<li><strong>export</strong> This option specifies that a PKCS#12 file will be created rather than parsed.</li>
<li><strong>name</strong>  This specifies the certificate entry for the certificate and private key. When we edit our <code>application.yml</code> file, we will use this name as the <code>keyAlias</code></li>
<li><strong>in</strong> This specifies filename of the PKCS#12 file to be parsed.</li>
<li><strong>inkey</strong> File from which to read the private key.</li>
<li><strong>caname</strong> This specifies the &quot;friendly name&quot; for other certificates</li>
</ul>
<p>You can learn more about the <code>pkcs121</code> command by running <code>man pks12</code></p>
<h2>Modify Grails Configuration to Use the Certificate</h2>
<p>Update <code>grails-app/conf/application.yml</code> with the following lines:</p>
<pre><code>server:
    port: 8443
    ssl:
        keyStore: /certificates/keystore.p12
        keyStorePassword: secret
        keyAlias: tomcat
</code></pre>
<p>You can read more about pkcs121 by running <code>man pks12</code></p>
<h2>Using Java KeyStores</h2>
<p>If you are deploying your app to a container like Tomcat, you will need to use a <a href="https://en.wikipedia.org/wiki/Keystore">Java KeyStore (JKS)</a> to store your SSL certificate. We can use the <a href="https://docs.oracle.com/javase/8/docs/technotes/tools/windows/keytool.html"><code>keytool</code></a> command-line utility (provided by Java) to create a JKS from our PKCS#12 keystore.</p>
<p>Use the <code>importkeystore</code> command to import and create the new keystore:</p>
<pre><code>keytool -importkeystore -srckeystore keystore.p12 -srcstoretype pkcs12 -srcalias tomcat -destkeystore keystore.jks -deststoretype jks -deststorepass secret -destalias tomcat
</code></pre>
<ul>
<li><strong>srckeystore</strong> Source keystore (in our case, <code>keystore.p12</code>)</li>
<li><strong>srcstoretype</strong> Source keystore type</li>
<li><strong>srcalias</strong> Certificate entry in the source keystore (in our case, &quot;tomcat&quot;)</li>
<li><strong>destkeystore</strong> File name for the JKS</li>
<li><strong>deststoretype</strong> Keystore type (JKS)</li>
<li><strong>deststorepass</strong> Password for the JKS</li>
<li><strong>destalias</strong> Certificate entry in the JKS</li>
</ul>
<p>Now we can update our <code>application.yml</code> to use the JKS file instead of the PKCS#12 keystore.</p>
<pre><code>server:
    port: 8443
    ssl:
        enabled: true
        keyStore: /certificates/keystore.jks
        keyStorePassword: secret
        keyAlias: tomcat
</code></pre>
<h2>Example:</h2>
<p><a href="https://github.com/grails-samples/grails-ssl">Github Repository with a Grails sample application</a></p>]]></description><author>Zachary Klein</author><guid>2017-06-28</guid><pubDate>Wed, 28 Jun 2017 00:00:00 GMT</pubDate></item><item><title>Checked Exceptions Rollback Transactions Since GORM 6.0.0</title><link>https://grails.apache.org/blog/2017-06-27.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
<p><a href="https://pragprog.com/book/vslg2/programming-groovy-2">Programming Groovy 2</a>:</p>
<blockquote>
<p>Groovy has less ceremony than Java. That's crystal-clear in exception handling. Java forces us to handle checked exceptions. Groovy does not force us to handle exceptions that we don't want to handle or that are inappropriate at the current level of code. Any exception we don't handle is automatically passed on to a higher level.</p>
</blockquote>
<p>Although the distinction between checked exceptions and runtime exceptions in Groovy is blurred, <strong>GORM versions before 6.0.0 did not roll back transactions for checked <code>Exceptions</code></strong>. However, they rollbacked transactions for runtime exceptions.</p>
<p>Grails<sup>®</sup> 3.2.0 shipped with GORM 6.0.0. One of the changes introduced by GORM 6.0.0 is that if a transactional method throws an <code>Exception</code> (both checked or runtime exception), the transaction will automatically be rolled back. Thus, same behavior for checked and runtime exceptions as you may expect in Groovy.</p>
<p>The previous behavior is better illustrated  with an example:</p>
<p>Given a Checked Exception</p>
<pre><code class="language-groovy">package demo

import groovy.transform.CompileStatic

@CompileStatic
class CustomCheckedException extends Exception {
}
</code></pre>
<p>and a RuntimeException</p>
<pre><code class="language-groovy">package demo

import groovy.transform.CompileStatic

@CompileStatic
class CustomRuntimeException extends RuntimeException {
}
</code></pre>
<p>and the next service:</p>
<pre><code class="language-groovy">package demo

import grails.transaction.Transactional
import groovy.transform.CompileStatic

@CompileStatic
@Transactional
class BookService {

    void addNewBookChecked() {
        def book = new Book(name: 'The definitive guide to grails 3')
        book.save()
        throw new CustomCheckedException()
    }

    void addNewBookRuntime() {
        def book = new Book(name: 'The definitive guide to grails 3')
        book.save()
        throw new CustomRuntimeException()
    }

    void addNewBookRegular() {
        def book = new Book(name: 'The definitive guide to grails 2')
        book.save()
    }

    @Transactional(readOnly = true)
    int count() {
        Book.where { }.count() as int
    }
}
</code></pre>
<p>The next specification passes for versions of GORM 6.0.0 or beyond.</p>
<pre><code class="language-groovy">package demo

import spock.lang.Specification
import spock.lang.Subject
import grails.test.mixin.integration.Integration

@Integration
class BookServiceIntegrationSpec extends Specification {

    @Subject
    BookService bookService

    def &quot;calling a service method which does not throw any exception results in adding a new book&quot;() {
        when:
        bookService.addNewBookRegular()

        then:
        bookService.count() == old(bookService.count()) + 1
    }

    def &quot;calling a service method which throws a runtime exception, rollback transaction and it does not add a new book&quot;() {
        when:
        bookService.addNewBookRuntime()

        then:
        thrown CustomRuntimeException
        bookService.count() == old(bookService.count())
    }

	// Fails with GORM versions &lt; 6.0.0
    def &quot;calling a service method which throws a Checked exception, rollback transaction and it does not add a new book&quot;() {
        when:
        bookService.addNewBookChecked()

        then:
        thrown CustomCheckedException
        bookService.count() == old(bookService.count())
    }
}
</code></pre>]]></description><author>Sergio Del Amo Caballero</author><guid>2017-06-27</guid><pubDate>Tue, 27 Jun 2017 00:00:00 GMT</pubDate></item><item><title>Why You Should Avoid Using Autowiring for Grails® Domain Classes</title><link>https://grails.apache.org/blog/2017-05-09.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
<p>You should not inject services into a domain class.</p>
<p>Why?</p>
<p>Autowiring a service into a domain class can have a big performance impact.</p>
<p>Imagine you query 1,000 records from a database, and those records are mapped into a GORM entities. Injecting a service into each of those 1,000 GORM entities will have a performance cost.</p>
<p>Thus, <a href="https://github.com/apache/grails-core/releases/tag/v3.2.8">starting with Grails<sup>®</sup> 3.2.8</a> auto wiring of GORM entities is disabled when you create an app from scratch. In Grails 3.3.0 or above it is disabled by default.</p>
<p>Let me illustrate this with an example.</p>
<p>The following code will not get the service <em>greetingService</em> injected into a domain class unless you enable auto wiring.</p>
<pre><code class="language-groovy">package demo

class Greeter {

    def greetingService

    String name

    String sayHello() {
        &quot;${name}${greetingService.sayHi()}&quot;
    }
}
package demo

class GreetingService {
    String sayHi() {
        'Hello'
    }
}

package demo

class HelloController {

    def index() {
        def person = new Greeter(name: 'Sergio')

        render person.sayHello()
    }
}
</code></pre>
<p>If you are autowiring services into your domain instances as in the above example, you will need to re-enable it.</p>
<p>For versions of Grails 3.3.0 or above, you can turn on autowire on a single domain class:</p>
<p>grails-app/domain/demo/Book.groovy</p>
<pre><code class="language-groovy">class Book {
    BookService bookService

    String name

   static mapping = {
       autowire true
   }
   ...
   ..
   .
}
</code></pre>
<p>You can turn on autowire for all your domain classes using the <a href="https://gorm.grails.org/latest/hibernate/manual/index.html#_the_default_mapping_constraints%5BDefault">Default Mapping</a> setting:</p>
<p>grails-app/conf/application.groovy</p>
<pre><code class="language-groovy">grails.gorm.default.mapping = {
        autowire true
}
</code></pre>
<p>For versions below Grails 3.3.0, you can re-enable it changing the <em>grails.gorm.autowire</em> configuration parameter.</p>
<p>grails-app/conf/application.yml</p>
<pre><code>grails:
    gorm:
        autowire: true
</code></pre>
<p><strong>If Spring autowiring of domain instances is enabled, read performance will degrade.</strong></p>
<p>Try to avoid the injection of services in domain classes. the Grails framework has an excellent services layer. You should place your business logic there.</p>]]></description><author>Sergio Del Amo Caballero</author><guid>2017-05-09</guid><pubDate>Tue, 09 May 2017 00:00:00 GMT</pubDate></item><item><title>Grails® Angular Profiles</title><link>https://grails.apache.org/blog/2017-04-12.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/angular.html"><span class="hashtag">#angular</span></a></p>
<p>In order to be consistent with the Angular team's guidelines on naming conventions, we have renamed the Angular profiles that the Grails<sup>®</sup> framework provides. This change will take affect in Grails 3.2.9. Any existing applications will not be impacted by this change. This will only affect your project if you create a new application with Grails 3.2.9 or above, or if you upgrade an existing application.</p>
<p>Previously we had:</p>
<table>
<thead>
<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
</thead>
<tbody>
<tr><td>angular</td><td>3.2.2</td><td>https://github.com/grails-profiles/angular</td><td>1.x</td></tr>
<tr><td>angular2</td><td>1.0.5</td><td>https://github.com/grails-profiles/angular2</td><td>2.x</td></tr>
</tbody>
</table>
<p>The &quot;angular&quot; profile was renamed to &quot;angularjs.&quot; Then the &quot;angular2&quot; profile was renamed to &quot;angular.&quot;</p>
<p>Since &quot;angularjs&quot; is a new module, we restarted the version to 1.0.0.</p>
<p>Since &quot;angular&quot; already exists, the version had to be higher than the current version. Since the existing version is 3.2.2, we chose 4.0.0. That also happens to fall in line with the Angular version supported, however the new profile may not follow the Angular version it supports.</p>
<p>Now we have:</p>
<table>
<thead>
<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
</thead>
<tbody>
<tr><td>angularjs</td><td>1.0.0</td><td>https://github.com/grails-profiles/angularjs</td><td>1.x</td></tr>
<tr><td>angular</td><td>4.0.0</td><td>https://github.com/grails-profiles/angular</td><td>4.x</td></tr>
</tbody>
</table>
<h2>Potential Issues Caused by This Change</h2>
<h3><a href="https://github.com/grails-profiles/angularjs">Angular Profile</a></h3>
<p>If you have an existing application created with the &quot;angular&quot; profile, you are using the profile for Angular 1.x.</p>
<pre><code class="language-groovy">dependencies {
    profile org.grails.profiles:angular
}
</code></pre>
<p>Since the Grails framework manages the version of the profile for you, if you were to upgrade to a newer version of the Grails framework, you will get the newer version of the angular profile. That means that previously you had the Angular 1.x profile and after upgrading, you will have the Angular 4.x profile.</p>
<p>Fortunately the change will not change the behavior of your application in any way. The only problem you may encounter is if you attempt to use the commands provided by the AngularJS profile. You will find the commands (<code>create-ng-controller</code>, <code>create-ng-directive</code>, etc) won't work as they exist in the &quot;angularjs&quot; profile, while you have the &quot;angular&quot; profile.</p>
<p>To get the commands working again, simply change the dependency to &quot;angularjs&quot;.</p>
<pre><code class="language-groovy">dependencies {
    profile org.grails.profiles:angular //Change to &quot;angularjs&quot;
}
</code></pre>
<p>In addition, you should change the profile set in the configuration.</p>
<pre><code class="language-yaml">grails:
    profile: angular //Change to &quot;angularjs&quot;
</code></pre>
<h3><a href="https://github.com/grails-profiles/angular">Angular2 Profile</a></h3>
<p>If you have an existing application with the &quot;angular2&quot; profile and you upgrade to Grails 3.2.9 and above, you will find Gradle can't find the dependency because the Grails framework is no longer providing a version for that dependency. To fix the problem, simply change the dependency in <code>build.gradle</code>.</p>
<pre><code class="language-groovy"> dependencies {
     profile org.grails.profiles:angular2  //Change to &quot;angular&quot;
 }
</code></pre>
<p>In addition, you should change the profile set in the configuration.</p>
<pre><code class="language-yaml">grails:
    profile: angular2 // Change to &quot;angular&quot;
</code></pre>
<h2>Scaffolding Plugin Changes</h2>
<p>In addition to the profiles, the plugins that provide scaffolding also needed to be renamed in the same manner.</p>
<blockquote>
<p>NOTE: At the time of this post, the Angular 2.x+ scaffolding is still in a release candidate stage.</p>
</blockquote>
<p>Before:</p>
<table>
<thead>
<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
</thead>
<tbody>
<tr><td>angular-scaffolding</td><td>1.0.1</td><td>https://github.com/grails-plugins/grails-angular-scaffolding</td><td>1.x</td></tr>
<tr><td>angular2-scaffolding</td><td>1.0.0.RC1</td><td>https://github.com/grails-plugins/grails-angular2-scaffolding</td><td>2.x +</td></tr>
</tbody>
</table>
<p>After:</p>
<table>
<thead>
<tr><th>Name</th><th>Latest Version</th><th>Repo Location</th><th>Angular Versions Supported</th></tr>
</thead>
<tbody>
<tr><td>angularjs-scaffolding</td><td>1.0.3</td><td>https://github.com/grails-plugins/grails-angularjs-scaffolding</td><td>1.x</td></tr>
<tr><td>angular-scaffolding</td><td>2.0.0.RC1</td><td>https://github.com/grails-plugins/grails-angular-scaffolding</td><td>2.x +</td></tr>
</tbody>
</table>
<p>The only change necessary is to update your <code>build.gradle</code>.</p>
<h3><a href="https://github.com/grails-plugins/grails-angular-scaffolding">Angular 2.x +</a></h3>
<pre><code class="language-groovy">buildscript {
    dependencies {
        //Change to &quot;angular-scaffolding:2.0.0.RC1&quot;
        classpath org.grails.plugins:angular2-scaffolding:1.0.0.RC1 
    }
}
dependencies {
    //Change to &quot;angular-scaffolding:2.0.0.RC1&quot;
    compile org.grails.plugins:angular2-scaffolding:1.0.0.RC1  
}
</code></pre>
<h3><a href="https://github.com/grails-plugins/grails-angularjs-scaffolding">Angular 1.x</a></h3>
<pre><code class="language-groovy">buildscript {
    dependencies {
        //Change to &quot;angularjs-scaffolding:1.0.3&quot;
        classpath org.grails.plugins:angular-scaffolding:1.0.1  
    }
}
dependencies {
    //Change to &quot;angularjs-scaffolding:1.0.3&quot;
    compile org.grails.plugins:angular-scaffolding:1.0.1  
}
</code></pre>
<h2>Conclusion</h2>
<p>The goal of this change was to make determining which profile/scaffolding plugin should be used less confusing in the future. If you encounter any problems as a result of this change that were not expected, please file an issue.</p>]]></description><author>James Kleeh</author><guid>2017-04-12</guid><pubDate>Wed, 12 Apr 2017 00:00:00 GMT</pubDate></item><item><title>How to Add Build Info to Your Project</title><link>https://grails.apache.org/blog/2017-04-02.html</link><description><![CDATA[</p>
<h2>Introduction</h2>
<p>When you build and run Grails<sup>®</sup> 3 applications, often you may want to know about the build environment via the running application.</p>
<p>Since the early days of the Grails framework, we were able to add arbitrary properties to the <code>application.properties</code> file. The Grails framework provides this information through the <code>grails.util.Metadata</code> class, and for views this is easily made available through the tag.</p>
<p>Since Grails 3 is built with <a href="https://gradle.org/">Gradle</a>, the old <code>application.properties</code> is no longer in use. Instead we'll add properties to <code>grails.build.info</code></p>
<h2>The Basics</h2>
<p>When you build/run your Grails applications, one of tasks that Gradle always executes is <code>buildProperties</code>. This task takes a small set of build information from your project and places it in a file, which the Grails <code>Metadata</code> class later reads. This file is located in <code>META-INF</code> and is named <code>grails.build.info</code>.</p>
<p>At build time, you can find this file at <code>build/resources/main/META-INF/grails.build.info</code>. The contents of this file looks like:</p>
<pre><code class="language-property">#Thu, 02 Feb 2017 15:30:37 +0100

info.app.version=0.1
info.app.name=metadata
grails.env=production
info.app.grailsVersion=3.2.5
</code></pre>
<p>This info primarily comes from <code>build.gradle</code> and <code>gradle.properties</code> (the curious can check out the source code in <a href="https://github.com/apache/grails-core/blob/6c85ec239aa8cc4a9f646bb345c70c327ddb2dbc/grails-gradle-plugin/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy#L179">grails-core</a>). This file will be part of your final application when you build your <code>.jar</code> or <code>.war</code> file.</p>
<p>In a <code>.gsp</code>, this information is available by using the meta tag like this: (see the <a href="https://gsp.grails.org/latest/guide/index.html#tags">tag</a> documentation).</p>
<h2>Adding More Information to <code>grails.build.info</code></h2>
<p>With the Gradle build system, it is possible to hook into the build process and execute our own code. In this case we want Gradle to complete writing <code>grails.build.info</code>, and then we want to add additional properties to the file.</p>
<p>To accomplish this, add the following snippet to <code>build.gradle</code> in your project:</p>
<pre><code class="language-groovy">buildProperties.doLast {
    // Find the right file
    File grailsBuildInfoFile = it.outputs.files.files.find { it.name == 'grails.build.info' }
    if(!grailsBuildInfoFile) return // No need to continue if the file is not there
    Properties properties = new Properties()
    // Read properties from the file
    grailsBuildInfoFile.withInputStream {
        properties.load(it)
    }
    // Add new properties from various sources
    properties.setProperty('build.time', new Date().format(&quot;yyyy-MM-dd HH:mm:ss&quot;))
    // Get a System property
    properties.setProperty('build.java.version', System.getProperty('java.version'))
    // Get the host name where the build was created
    properties.setProperty('build.host', InetAddress.localHost.hostName)
    // Add property set by your CI (in this case Bamboo)
    Map&lt;String, String&gt; env = System.getenv()
    if(env.bamboo_buildNumber) {
        properties.setProperty('build.number', env.bamboo_buildNumber)
        properties.setProperty('build.git.revision', env.bamboo_planRepository_revision)
        properties.setProperty('build.git.branch', env.bamboo_planRepository_branch)
    }
    // Write the properties back to the file
    grailsBuildInfoFile.withOutputStream {
        properties.store(it,null)
    }
}
</code></pre>
<p>This example shows:</p>
<ul>
<li>How to set <code>build.time</code> from the time that the build was executed</li>
<li>How to set values from <code>System.properties</code></li>
<li>How to get your build host name</li>
<li>How to read environment variables set by your build server (in the above example by <a href="https://www.atlassian.com/software/bamboo">Atlassian Bamboo</a>)</li>
</ul>
<p>Now that we have this build information captured in <code>grails.build.info</code>, we can show it in our application in a <code>.gsp</code> page.</p>
<p>For example:</p>
<pre><code class="language-html">&lt;table&gt;
    &lt;thead&gt;
        &lt;tr&gt;&lt;th&gt;Name&lt;/th&gt;&lt;th&gt;Value&lt;/th&gt;&lt;/tr&gt;
    &lt;/thead&gt;
    &lt;tbody&gt;
        &lt;tr&gt;&lt;td&gt;Build time&lt;/td&gt;&lt;td&gt;&lt;g:meta name=&quot;build.time&quot;&gt;&lt;/g:meta&gt;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Build java version&lt;/td&gt;&lt;td&gt;&lt;g:meta name=&quot;build.java.version&quot;&gt;&lt;/g:meta&gt;&gt;&lt;/td&gt;&lt;/tr&gt;
        &lt;tr&gt;&lt;td&gt;Build host&lt;/td&gt;&lt;td&gt;&lt;g:meta name=&quot;build.host&quot;&gt;&lt;/g:meta&gt;&gt;&lt;/td&gt;&lt;/tr&gt;
    &lt;/tbody&gt;
&lt;/table&gt;
</code></pre>
<p>... and so on.</p>
<blockquote>
<p>NOTE: If you use the Spring Boot Actuator endpoints, you can write <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#production-ready-application-info-custom">your own custom InfoContributor</a> that uses Grails <code>Metadata</code>!</p>
<p>Alternatively, you can leverage the <a href="https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#production-ready-application-info-autoconfigure">Auto-configured InfoContributors</a> to:</p>
<ul>
<li><a href="https://guides.grails.org/adding-commit-info/guide/index.html">add git commit info</a>
-expose build info by copying <code>grails.build.info</code> to a <code>build-info.properties</code> file (<a href="https://github.com/spring-projects/spring-boot/blob/v1.5.2.RELEASE/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/BuildInfoContributor.java">BuildInfoContributor</a>)</li>
<li>expose environment info by configuring properties starting with <code>'info.'</code> such as <code>'info.app.name'</code> (<a href="https://github.com/spring-projects/spring-boot/blob/v1.5.2.RELEASE/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/info/EnvironmentInfoContributor.java">EnvironmentInfoContributor</a>)</li>
</ul>
</blockquote>
<h2>Conclusion</h2>
<p>This blog-post shows how you can easily add build information to your Grails 3 application by leveraging the tasks already available within the Gradle build, and how you can show them in your application.</p>]]></description><author>Søren Berg Glasius &amp; Colin Harrington</author><guid>2017-04-02</guid><pubDate>Sun, 02 Apr 2017 00:00:00 GMT</pubDate></item><item><title>GORM 6.1 Released</title><link>https://grails.apache.org/blog/2017-03-27.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>Today, <a href="https://objectcomputing.com/products/2gm-team">the Grails<sup>®</sup> team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://gorm.grails.org/6.1.x/">GORM 6.1 GA</a>.</p>
<p>This release includes <a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">a number of new and exciting features</a> that we are happy to share with you today. Notably:</p>
<ul>
<li><a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#dataServices">GORM Data Services</a> allow you to easily define interfaces or abstract classes that are automatically implemented for you at compile time.</li>
<li>Multi-Tenancy AST Transformations</li>
<li>Support for JPA annotations and Bean Validation API annotations</li>
<li>Package Scanning for easier unit testing</li>
<li>Support for Hibernate 5.2+</li>
<li>Automatic HQL escaping for GString queries</li>
<li>Support for MongoDB 3.4 and the new Decimal128 Type</li>
<li>Support for Neo4j 3.1 and the Neo4j 1.2 Bolt Java Driver</li>
<li>Massive improvements to the Neo4j support including support for relationship entities, paths and more.</li>
</ul>
<p>There is too much goodness to go through all of it in a blog post, so I encourage you to read the <a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">release notes</a> and check out the dedicated documentation for each implementation:</p>
<ul>
<li><a href="https://gorm.grails.org/6.1.x/hibernate/manual/index.html#releaseHistory">GORM for Hibernate</a></li>
<li><a href="https://gorm.grails.org/6.1.x/mongodb/manual/index.html#releaseNotes">GORM for MongoDB</a></li>
<li><a href="https://gorm.grails.org/6.1.x/neo4j/manual/index.html#releaseNotes">GORM for Neo4j</a></li>
</ul>
<p>Or alternatively come see my talk about GORM 6.1 in person at Greach in Madrid!</p>
<p>GORM 6.1 will become the default version of GORM to be used in the upcoming Grails 3.3, in the meantime you can use GORM 6.1 in Grails 3.2 simply by changing the <code>gormVersion</code> setting in <code>gradle.properties</code>:</p>
<pre><code class="language-groovy">gormVersion=6.1.0.RELEASE
</code></pre>
<p>To celebrate the release we have prepared the first of a series of new guides to cover GORM 6.1. Among the many new features are huge improvements to support Neo4j. Using the official Neo4j sample application, the new guide describes how you can <a href="https://guides.grails.org/neo4j-movies/guide/index.html">build a graph application with the Grails framework, GORM 6.1 and Neo4j</a>! Enjoy!</p>]]></description><author>Graeme Rocher</author><guid>2017-03-27</guid><pubDate>Mon, 27 Mar 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #6: Developing Grails® 3 Applications with IntelliJ IDEA</title><link>https://grails.apache.org/blog/2017-01-20-4.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>Grails<sup>®</sup> 3 is a high-productivity framework for building web applications for the JVM.</p>
<p>IntelliJ IDEA is a high-productivity Integrated Development Environment (IDE) for building a variety of application types. IDEA has always had great support for building Grails applications and, in particular, has the best support of any IDE for developing with Grails 3.</p>
<p>In this 20-minute video, Grails framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, introduces several tips and tricks related to building Grails 3 applications in IDEA.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XsCCsTRdezw" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown</author><guid>2017-01-20-4</guid><pubDate>Fri, 20 Jan 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #4: Angular Scaffolding</title><link>https://grails.apache.org/blog/2017-01-20-2.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.apache.org/blog/tag/rest.html"><span class="hashtag">#rest</span></a></p>
<p>In this Quickcast, 2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team member, <a href="https://objectcomputing.com/products/2gm-team#kleeh">James Kleeh</a>, walks you through the process of using the Angular scaffolding for Grails apps to build a fully functional web app, using a simple blog format for demonstration.</p>
<p>The tutorial explains how to have the Grails framework set up a REST endpoint and all the Angular modules needed to get the web app running.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/tT4BdlRFAis" frameborder="0"></iframe>]]></description><author>James Kleeh</author><guid>2017-01-20-2</guid><pubDate>Fri, 20 Jan 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #5: Retrieving Runtime Config Values in Grails® 3</title><link>https://grails.apache.org/blog/2017-01-20-3.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this short video tutorial, Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, highlights some of the great features of the Grails framework.</p>
<p>In fewer than 18 minutes, Jeff describes several techniques for retrieving configuration values at runtime and discusses the pros and cons of each. Visit <a href="https://objectcomputing.com/news/2016/08/31/retrieving-config-values-grails-3">this Grails blog post</a> for an accompanying article.</p>
<p>For this Quickcast, you’ll need no more than a basic understanding of the Grails framework.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/Qw5hjwT9EOc" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown</author><guid>2017-01-20-3</guid><pubDate>Fri, 20 Jan 2017 00:00:00 GMT</pubDate></item><item><title>Quickcast #3: Multi-Project Builds</title><link>https://grails.apache.org/blog/2017-01-20-1.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this video, Grails<sup>®</sup> framework co-founder Graeme Rocher walks you through multi-project builds in Grails apps.</p>
<p>The Grails framework does a few handy things with multi-project builds and plugins, not the least of which being that Grails compiles your plugins first and puts the class and resources of those plugins directly in the classpath. This lets you make changes to your plugins and instantly see those changes in your build.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/yNA0ce5fG9s" frameborder="0"></iframe>]]></description><author>Graeme Rocher</author><guid>2017-01-20-1</guid><pubDate>Fri, 20 Jan 2017 00:00:00 GMT</pubDate></item><item><title>G3 Summit 2016 Wrap-up!</title><link>https://grails.apache.org/blog/2016-12-14.html</link><description><![CDATA[</p>
<p><img src="2016-12-14-img01.jpg" alt="The OCI Grails team at G3 Summit 2016" /></p>
<p>Last month, nearly the entire <a href="https://objectcomputing.com/products/2gm-team">2GM (Groovy, Grails<sup>®</sup> framework, and Micronaut) team</a> from [Object Computing, Inc.] (https://objectcomputing.com/) (OCI) converged on Fort Lauderdale for the inaugural edition of the G3 Summit, the conference for the Apache Groovy, Grails framework, and Gradle Community. The event is organized by <a href="https://www.nofluffjuststuff.com/home/main">No Fluff Just Stuff</a> and is a fantastic opportunity for developers to mingle with committers, authors, and project leaders in the greater Groovy community.</p>
<p>OCI team members presented over 30 workshops and breakout sessions during the event, in addition to socializing with attendees between sessions and after hours. We’ve asked a few team members to share their experiences at the conference. We hope you will join us next year!</p>
<h2>Will Buck, Software Engineer</h2>
<p>For me, the inaugural G3 Summit was a hit! The Groovy community is always great to get together with and this event was no exception. I thought the Westin Beach in Fort Lauderdale was a fantastic venue with great food, the keynotes were all exciting and informative, and the presentation blocks were all packed with quality information that got me fired up to try things out on personal and work projects.</p>
<p><img src="2016-12-14-img02.jpg" alt="Keynote presentation at G3 Summit 2016" /></p>
<p>Highlights of the event for me were:</p>
<ul>
<li>Iván Lopez’s session on Docker, which had an amazingly well put together sample project that he did a great job touring in his presentation</li>
<li>Jack Frosch’s session on microservices, which also had a wonderful sample project out on Github and really helped me &quot;put the pieces together&quot; on Netflix’s OSS in this space (Zuul, Eureka, and Hystrics)</li>
<li><a href="https://twitter.com/groovypuzzlers">Groovy Puzzlers</a> (my first time getting to attend one, hilarious &quot;technical&quot; comedy routine)</li>
<li>Magician Michael Carducci making James Kleeh’s ring disappear during his magic routine at the closing happy hour</li>
<li>The Single-Page Application &quot;breakout&quot; session on Tuesday, which was a great discussion of real problems attendees were having in their workplaces and ways we’d collectively found to solve them. This in particular was huge for me, as a big reason I joined the OCI Grails team was to hear from OSS users and think about ways I could contribute to solutions that anyone could enjoy</li>
<li><strong>Swimming in the Atlantic</strong> after the conference ended, which I don’t think I’ve ever done</li>
<li>The mealtime conversations about getting Grails apps into the workplace, personal stories about life as a software developer, and children’s fascination with Villains (I found another kindred spirit whose daughter wants to be Darth Vader!)</li>
</ul>
<p>Jay Zimmerman and the NFJS tour crew have the kinks worked out on throwing a great conference event and G3 Summit was no exception. I’d highly recommend this to both regulars of the Groovy community and newcomers interested in learning all the great things in our ecosystem!</p>
<p><img src="2016-12-14-img03.jpg" alt="One highlight of the conference: swimming in the Atlantic Ocean!" /></p>
<h2>Søren Glasius, Software Engineer</h2>
<p>This first edition of the G3 Summit was a blast. When traveling to a conference from winter cold Denmark, going to Florida was great.</p>
<p>I arrived early and had a chance to cruise with Ívan and Álvaro from the OCI Grails Team in a <a href="https://twitter.com/ilopmar/status/802889186906808320">yellow Ford Mustang Convertible</a>.</p>
<p>But it wasn't all fun and games. The conference was a four-day show of Groovy-ness. The first day was packed with workshops where the attendees had a chance to get in depth knowledge on their favorite G* technology.</p>
<p>Tuesday kicked off with an insightful keynote by <strong>Guillaume Laforge</strong> covering the current state of <a href="https://groovy-lang.org/">Apache Groovy</a>, followed by Graeme Rocher showing the <a href="https://guides.grails.org/">new Grails Guides portal</a> and the new <a href="https://start.grails.org/#/index">Grails Application Forge</a>. The keynotes were followed by great talks throughout the day.</p>
<p>On Wednesday I gave two talks: &quot;<a href="https://www.youtube.com/watch?v=ZXRklokhxuE">Get to Know the Grails framework</a>&quot; and &quot;<a href="https://www.youtube.com/watch?v=RuK90qD6RJU">Tour de Plugin</a>,&quot; and on Thursday I gave a talk named &quot;<a href="https://www.youtube.com/watch?v=T0sxNY1_GFg">Fields Plugin - Deep Dive</a>&quot; (see links for screencasts).</p>
<p>My personal favorite experience was when sat down and talked to a (former?) Ruby on Rails developer, who wanted to start using the Grails framework in his projects. To see the smile on his face when he saw Grails apps shine and when he realized that the journey from Rails to Grails apps would be much easier than he had anticipated.</p>
<p>For me, G3 Summit was well worth the travel from Europe. Thank you to Jay Zimmerman for inviting me to the show, and to his crew who did a great job putting on a great show. I look forward to next year’s edition of G3 Summit.</p>
<h2>Zachary Klein, Software Engineer</h2>
<p>The inaugural G3 Summit was a unique and amazing event. The NFJS crew know how to put together a <strong>first-class conference</strong>, and this was no exception. The speaker line-up was very strong, and from the first workshops till the closing sessions there was no shortage of high-quality content.</p>
<p>Highlights for me would be:</p>
<ul>
<li>Venkat Subramaniam’s &quot;Programming Groovy with Java 8&quot; and “Functional Programming for Groovy Programmers”</li>
<li>Presentations from my OCI colleagues
<ul>
<li>James Kleeh. &quot;Angular Scaffolding” and &quot;Creating Custom Profiles&quot;</li>
<li>Jack Frosch. &quot;Building a Microservice Federation&quot;</li>
</ul>
</li>
</ul>
<p><img src="2016-12-14-img04.jpg" alt="All-Star Panel" /></p>
<p>The two &quot;all-star&quot; panel discussions were lively and informative, with a wide-range of topics ranging from the future of Groovy/Grails/Gradle to how we as developers can improve our skills and stay abreast of the new developments in our field. Last but not least, the interactions between sessions with attendees and speakers were a fresh and welcome reminder of the strength and welcoming nature of the Groovy community – you’re all a great bunch of folks to work with!</p>
<h2>Ryan Vanderwerf, Software Engineer</h2>
<p>SpringOne2GX has turned into G3 Summit! Groovy, Grails framework and Gradle represent the largest base of G(Groovy)-based tech in the space, but there are so many other projects that are also popular. Jay Zimmerman kicked this one off with his extreme professionalism as all of his NFJS conferences with perfect execution. I was glad to see many new and many familiar faces this year. The venue was nice and right on the beach!</p>
<p><img src="2016-12-14-img05.jpg" alt="Ryan Vanderwerf on the beach at G3 Summit 2016" /></p>
<p>Things were small and friendly which allowed open conversations with everyone at the two mixers/happy hours on the roof top. I stuck my head in on workshop day in all of the rooms, they were very well attended, especially for 7 hour workshops!</p>
<p>I spent most of my time at Dan Wood’s <a href="https://ratpack.io/">Ratpack</a> workshop. He started off in Java for the first few lessons then went improvisational by switching things to Groovy on the fly. I am sure it was way less typing - but in doing things in Java he removed some magic so you would see what is really going on with the framework. I enjoyed it and learned new things!</p>
<p>That night were was a great kick-off keynote by Venkat Subramaniam and a cocktail reception afterwards.</p>
<p>On Tuesday the conference was in full swing, with Guillaume Laforge giving a great opening keynote, and Graeme Rocher following up with all of the new and exciting things coming from the Grails team and community. They include:</p>
<ul>
<li>The <a href="https://start.grails.org/#/index">Grails Application Forge</a></li>
<li>Work towards a micro-service profile</li>
<li>New profile support for Angular and React</li>
<li>Plans for Grails 3.3</li>
<li>Many GORM improvements</li>
</ul>
<p><img src="2016-12-14-img06.jpg" alt="Paul King presenting Groovy – the Awesome Parts" /></p>
<p>The day followed with 90 minute sessions by:</p>
<ul>
<li>Paul King (&quot;Groovy - the Awesome Parts&quot;)</li>
<li>Jeff Scott Brown (“Runtime Metaprogramming”)</li>
<li>Ken Kousen (Grails 3 workshop)</li>
<li>Ivan Lopez (“Dockerize your Grails apps!”)</li>
<li>Raju Gandi (“Gradle from The Ground Up”)</li>
</ul>
<p><img src="2016-12-14-img07.jpg" alt="Jeff Brown presenting Testing Grails 3" /></p>
<p>After lunch more sessions by:</p>
<ul>
<li>Venkat Subramaniam (&quot;Java 8 and Groovy&quot;)</li>
<li>Guillaume Laforge (“What Can You Learn from <a href="https://glaforge.appspot.com/article/analyzing-gradle-grails-and-apache-groovy-source-code-hosted-on-github-with-bigquery">Groovy source files on Github</a>”)</li>
<li>Alvaro Sanchez-Mariscal (“Mastering Grails 3 Plugins”)</li>
<li>Jeff Scott Brown (“Testing Grails 3”)</li>
<li>Gary Hale (“Gradle Worse Practices”)</li>
</ul>
<p>Plus a Grails Roadmap Q&amp;A session by Graeme Rocher</p>
<p>The OCI Grails team organized several informal Q&amp;A sessions throughout the day where people could come and go and ask more detailed questions that wouldn’t fit during a talk. Lots of interesting people came and voiced their opinions, asked for advice, and shared what they were doing or wanted to do.</p>
<p>Finishing the day was:</p>
<ul>
<li>&quot;GORM Inside and Out&quot; by Graeme Rocher</li>
<li>Paul King with a “Deep Dive into AST Transforms”</li>
<li>Jeff Scott Brown with “Grails 3 for Spring Boot Developers”</li>
<li>James Kleeh with “Angular Scaffolding”</li>
<li>Jon Schneider with &quot;Distributed Refactoring at <a href="https://www.netflix.com/">Netflix</a>”</li>
</ul>
<p>That slot was hard for me to choose because I hadn’t seen most of them before; I went to Paul's AST talk, which did not disappoint.</p>
<p>Tuesday wrapped up with a keynote by Gradle founder and CEO Hans Dockter, in which he announced many new features around wrangling dependencies, such as substitution and  replacement. After that was a panel discussion and audience Q&amp;A.</p>
<p>On Wednesday the conference got going full force with great talks by:</p>
<ul>
<li>Jack Frosch sharing Java to Groovy experiences</li>
<li>David Clark with high-performance Groovy</li>
<li>Søren Glasius with &quot;Get to Know Grails&quot;</li>
<li>James Kleeh with “Creating Custom Profiles”</li>
<li>Ken Kousen on “Gradle Recipes for Android”</li>
</ul>
<p>I attended James Kleeh’s talk on custom profiles, which had a lot of good information he put together and documented while building the Angular profiles.</p>
<p>Next up was:</p>
<ul>
<li>Dan Wood with an &quot;Intro to Ratpack&quot;</li>
<li>Venkat with “Typing in Groovy”</li>
<li>Jeff Scott Brown with “Monitoring and Metrics for Grails”</li>
<li>Jack Frosch with “Building a Microservice Federation”</li>
<li>Chip Dickson and Charles Walker doing a joint talk on “Gradle Migration Blueprints”</li>
</ul>
<p>After lunch we had:</p>
<ul>
<li>David Clark on “Modern Groovy DSLs”</li>
<li>Venkat on Spock</li>
<li>Jeff Scott Brown on “Restful Grails 3”</li>
<li>Alvaro on “Grails apps, Angular and Spring Security”</li>
<li>Ethan Hall on Linkedin usage of Gradle</li>
<li>and yet another informational Q&amp;A Session with SPA (I hung out there to learn myself!)</li>
</ul>
<p>The talks just keep on coming all the way until 6:30 - this is a marathon!</p>
<p>Next slot is:</p>
<ul>
<li>Dan Woods with &quot;Groovy in the Cloud&quot;</li>
<li>Ivan Lopez with Groovy Annotations</li>
<li>Jeff Scott Brown with “Polyglot Development with Grails apps”</li>
<li>Zachary Klein with “Using React and Grails 3”</li>
<li>Scott Hickey with Mutual of Omaha and Jenkins</li>
<li>A GORM Q&amp;A Session.</li>
</ul>
<p>Last slot of talks I gave a new version of my “Alexa Tell my I’m Groovy” where I shared all of the latest efforts my friend Lee Fox and I did with overhaul of the Java SDK which the Grails Plugin and Lazybones Lambda use to make Skills quickly. I demoed the various types of apps/Skills you can make and shared how I made them.</p>
<p>David Clark had a “Concurrent Groovy” talk at the same time, Colin Harrington had a talk on “Grails View Layer”, Søren Glasius on “Tour de Plugin”, Zak Klein and Will Buck on “Grails apps, Gradle and Node.js”, and Grails 3.2 Q&amp;A session.</p>
<p>We wrapped up with a great great “Groovy Puzzlers” Season 3 session with Baruch Sadorgursky and Guillaume Laforge, and finally another nice cocktail reception!</p>
<p>The last day ended a bit slow, with breakfast and panel discussion, followed by a single slot of sessions.</p>
<p>I gave my talk &quot;Getting Groovy with Google Glass and Android Wear&quot; - by this time it seems most people went home. However, those who came participated in a great discussion about Glass, Wear, modifying cars, and home automation, which I enjoyed.</p>
<p>Venkat gave a Functional Programming talk, Ken a talk on functional testing with Geb, Søren a talk on <a href="https://github.com/grails-fields-plugin/grails-fields">the Fields plugin</a>, Michael Carducci with CI on Gradle/Jenkins, and Jeff held a Grails Upgrade Q&amp;A Session.</p>
<p>We finished up the conference with lunch, which was a nice touch at the end I don’t normally see at conferences!</p>
<p><img src="2016-12-14-img08.jpg" alt="The OCI Grails team enjoying post-conference feast" /></p>
<p>Overall it was a great conference and would love to see even more attendance next year. I think the 90 minute format is great for a deeper dive into the tech instead of a overview at 60 minutes. The venue is great for nice weather and folks up north getting a break from the cold.</p>
<p>The last night several teammates went out for Cuban food, which was delicious! On Friday Ivan, Alvaro and I walked around the marina areas and had a nice Italian lunch before hopping on a plane back to Austin.</p>
<p>I hope to see everyone and more new faces next year!!!</p>]]></description><author>Will Buck, Ryan Vanderwerf, Zachary Klein, and Søren Berg Glasius</author><guid>2016-12-14</guid><pubDate>Wed, 14 Dec 2016 00:00:00 GMT</pubDate></item><item><title>Introducing the React Profile for Grails®</title><link>https://grails.apache.org/blog/2016-11-14.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/react.html"><span class="hashtag">#react</span></a></p>
<h2>React Profiles for the Grails<sup>®</sup> framework</h2>
<p>Grails 3 offers great support for the Angular framework, including the Angular Scaffolding plugin as well as profiles for both Angular 1.x and 2.x. Recently new profiles have been released to provide support for creating React applications with Grails 3.</p>
<p>This post will cover <em>two new profiles for React</em>, one aimed at monolithic Grails applications, and a second profile which makes use of the brand new <a href="https://github.com/facebookincubator/create-react-app"><code>create-react-app</code> CLI</a> and generates a multi-project client/server structure.</p>
<p><img src="2016-11-14-img01.png" alt="" /></p>
<h2>React &amp; Webpack Profiles</h2>
<p>If you've read the previous post on <a href="/blog/2016-05-28.html">Using React with the Grails framework</a>, you've probably noticed that there's quite a bit of wiring that has to happen to get React working properly in the context of a Grails application. This is a place where profiles shine, and now you can get an entire React/Grails project setup immediately upon app generation, including some basic sample React code.</p>
<pre><code>grails create-app myReactApp --profile=org.grails.profiles:react:1.0.2
</code></pre>
<p>The <code>react:1.x</code> profile is based on another new profile, <code>org.grails.profiles:webpack:1.x</code>.  The <code>webpack</code> profile can be used standalone as well, if you want to use webpack with another JavaScript framework in a Grails project. In addition, the <code>webpack</code> profile offers a single feature which will configure the <code>babel</code> transpiler with support for ES6 - it also includes sample code to demonstrate the feature.</p>
<pre><code>grails create-app myWebpackApp --profile=org.grails.profiles:webpack:1.0.2 --features=babel
</code></pre>
<p>Both the <code>webpack</code> and <code>react:1.x</code> profiles will expect the JavaScript source files to be kept under <code>/src/main/webapp</code>. You can simply start up your app, and webpack will run automatically and bundle the JavaScript into the Grails asset pipeline.  Custom Gradle tasks such as <code>bundle</code> (to generate the webpack bundle on app startup) and <code>webpack</code> (to run webpack in &quot;watch&quot; mode and reload any changes) are defined. You may also run the corresponding npm scripts if you have npm installed (scripts are defined in <code>package.json</code>).</p>
<p>For instance, you can run webpack alongside your Grails app with this command:</p>
<pre><code>./gradlew webpack //or: npm run webpack
</code></pre>
<p>Now when you make changes to your JavaScript/React code under <code>/src/main/webapp</code>, webpack will automatically regenerate the bundle. Just refresh your page to see the changes.</p>
<p>In addition, the <code>react</code> profile adds a <code>mochaTest</code> task which will run React tests with the mocha test runner. Test sources are kept under <code>/src/test/js</code>, and a simple test is provided. Simply run:</p>
<pre><code>./gradlew mochaTest //or: npm test
</code></pre>
<h2>React Profile - Multi-Project Edition</h2>
<p>The react profile is being released with two branches, currently <code>1.0.2</code> and <code>2.0.1</code>.</p>
<p>The <code>react:2.0.1</code> profile is complete rewrite of the 1.x version, and it leverages the new React CLI from Facebook, <code>create-react-app</code>. For more information on the features provided by <code>create-react-app</code>, please read the <a href="https://github.com/facebookincubator/create-react-app">documentation on Github</a>.</p>
<p>In short, <code>create-react-app</code> provides us with a complete webpack/React project, with custom scripts defined to build, run and test our React app. It is designed for standalone React apps, which makes it a perfect choice for a client/frontend application backed by a separate server application. That is exactly what <code>react:2.0.1</code> provides.</p>
<p><img src="2016-11-14-img02.png" alt="" /></p>
<p>Please note that <code>react:2.0.1</code> depends upon the new CORS support in Grails 3.2.1, so you will need to be using that version of Grails or newer.</p>
<p>To get started with this profile, specify it when generating your app:</p>
<pre><code>grails create-app myReactMultiApp --profile=org.grails.profiles:react:2.0.1
</code></pre>
<p>Take a look at the directory structure - you will see a typical Gradle multi-project build, with separate client and server projects.</p>
<pre><code>-rw-r--r--  1 zak  staff    65 Nov  1 13:10 build.gradle
drwxr-xr-x  9 zak  staff   306 Nov  1 13:15 client
drwxr-xr-x  3 zak  staff   102 Nov  1 13:10 gradle
-rwxr--r--  1 zak  staff  4971 Nov  1 13:10 gradlew
-rwxr--r--  1 zak  staff  2314 Nov  1 13:10 gradlew.bat
drwxr-xr-x  8 zak  staff   272 Nov  1 13:12 server
-rw-r--r--  1 zak  staff    26 Nov  1 13:10 settings.gradle
</code></pre>
<p><code>server</code> is of course our Grails application. The profile will generate a Grails app using the <code>rest-api</code> profile, which provides support for creating domain classes as restful resources as well as JSON and Markup views.</p>
<p><code>client</code> is our React app. It has been rewritten with React-Bootstrap (Bootstrap 3) and will connect with <code>server</code> via REST calls - it has no Grails dependencies of any kind.</p>
<pre><code>-rw-r--r--   1 zak  staff  44412 Nov  1 13:10 README.md
-rw-r--r--   1 zak  staff    669 Nov  1 13:10 build.gradle
-rw-r--r--   1 zak  staff    404 Nov  1 13:10 package.json
drwxr-xr-x   4 zak  staff    136 Nov  1 13:10 public
drwxr-xr-x  10 zak  staff    340 Nov  1 13:10 src
</code></pre>
<p>This project structure (with the exception of <code>build.gradle</code>, which is specific to the <code>react:2.0.1</code> profile) is all courtesy of <code>create-react-app</code>, and includes an excellent <code>README</code> file. In short, the <code>src/</code> directory is where the React code is kept, <code>public/</code> is for public resources that you wish to make available from your React app without going through webpack's bundling - this directory also includes a template <code>index.html</code> file which is used to generate the React app's home page.  Again, see the <code>create-react-app</code> documentation for more details.</p>
<p>One significant customization of the <code>client</code> project (besides the Grails-branded UI) is the file <code>src/config.js</code>. This file is used to specify the URL of the backend, by default <code>http://localhost:8080</code>. It also obtains the current version of the React app from 'package.json'.</p>
<p>As with the 1.x version of the <code>react</code> profile, this profile define custom Gradle tasks, including a <code>bootRun</code> task to startup the client app. You can either start up the <code>server</code> and <code>client</code> apps separately:</p>
<pre><code>./gradlew server:bootRun

//in another terminal
./gradlew client:bootRun
</code></pre>
<p>Or you can take advantage of Gradle's parallel execution to run both client and server apps in a single command:</p>
<pre><code>./gradlew bootRun -parallel
</code></pre>
<p>Other tasks defined in <code>client</code> wrap the <code>create-react-app</code> scripts for building and testing the React app. You can run them with the Gradle wrapper, or run the npm scripts directly if you have npm installed.</p>
<pre><code>./gradlew client:test //or, from the client project dir: npm test

./gradlew client:build //or, from the client project dir: npm run build
</code></pre>
<p>Again, please see the <code>create-react-app</code> documentation for more information on leveraging these scripts and the other features provided by <code>create-react-app</code>.</p>
<h2>Wrap-Up</h2>
<p>These two profiles offer two ways to use React in the context of a Grails application. If you want to use React within your existing Grails application, either to render components on a GSP or to replace some or all of your GSP pages, then use <code>react:1.0.1</code> (or the latest version of the 1.x branch).</p>
<p>If you prefer a completely separate frontend for your Grails application, and/or want to take advantage of the features of the <code>create-react-app</code> CLI, then the <code>react:2.0.1</code> (or latest version of the 2.x branch) is made for you.</p>
<p>Whichever one you choose, here's hoping these profiles help you enjoy using React with Grails 3!</p>
<h2>Links</h2>
<ul>
<li><code>create-react-app</code>: <a href="https://github.com/facebookincubator/create-react-app">https://github.com/facebookincubator/create-react-app</a></li>
<li>&quot;Using React with the Grails framework&quot;: <a href="/blog/2016-05-28.html">/blog/2016-05-28.html</a></li>
</ul>]]></description><author>Zachary Klein</author><guid>2016-11-14</guid><pubDate>Mon, 14 Nov 2016 00:00:00 GMT</pubDate></item><item><title>Deploying Grails® 3.2 to JBoss 7.1 EAP</title><link>https://grails.apache.org/blog/2016-11-10.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/deployment.html"><span class="hashtag">#deployment</span></a></p>
<p>Following on from our post describing <a href="">how to deploy Grails<sup>®</sup> 3 to JBoss 6.4 EAP</a>, I recently undertook a new adventure to deploy Grails 3.2.3 to <a href="https://www.jboss.org/">JBoss 7.1 EAP</a>.</p>
<p>Like every new version of JBoss there are dependency challenges and tweaks to overcome in order to get to the point where you can deploy an application.</p>
<h2>Configuring Gradle</h2>
<p>After you have created a Grails application using the <code>grails create-app</code> command the first thing that needs to be done is to modify the dependencies to versions compatible with JBoss 7.1.</p>
<p>JBoss 7.1 is based on Servlet 3.0 and earlier versions of the Bean Validation API. This means that you need to use Tomcat 7, which is based on Servlet 3.0, which you can do by specifying the Tomcat version in <code>build.gradle</code>:</p>
<pre><code class="language-groovy">ext['tomcat.version'] = '7.0.72'
</code></pre>
<p>The above uses Spring Boot's ability to override the default versions of the <code>org.springframework.boot:spring-boot-starter-tomcat</code> dependency. Speaking of the <code>spring-boot-starter-tomcat</code> dependency, you need to make it provided:</p>
<pre><code class="language-groovy">provided &quot;org.springframework.boot:spring-boot-starter-tomcat&quot;
</code></pre>
<p>Since the classes within the Tomcat JARs are already provided by Tomcat these should not be included in the WAR. Next you should also specify the Servlet 3.0 API as provided:</p>
<pre><code class="language-groovy">provided &quot;javax.servlet:javax.servlet-api:3.0.1&quot;
</code></pre>
<p>This does two things, firstly it ensures the Servlet API dependencies are not in the WAR and secondly it forces the Grails framework to use Servlet 3.0 instead of the default 3.1.</p>
<p>The next challenge is the Bean Validation API, in earlier versions of JBoss it was possible to exclude the validation module and ship with a custom version of the Bean Validation API, this no longer seems to be possible with JBoss 7 so you have to downgrade the version of Hibernate Validator used by the Grails framework:</p>
<pre><code class="language-groovy">compile &quot;org.hibernate:hibernate-validator:4.3.2.Final&quot;
</code></pre>
<p>The JAXB dependency also seems be a required dependency of JBoss 7 so you have to add that:</p>
<pre><code class="language-groovy">runtime 'javax.xml.bind:jaxb-api:2.2.12'
</code></pre>
<p>Finally, generally with JBoss 7 you should deploy with a JNDI datasource so you should make the database driver dependency you are using <code>provided</code> scope. For example for MySQL:</p>
<pre><code class="language-groovy">provided &quot;mysql:mysql-connector-java&quot;
</code></pre>
<h2>JBoss Deployment Descriptors</h2>
<p>The next step to getting JBoss configured correctly is to provide a <code>src/main/webapp/WEB-INF/jboss-deployment-structure.xml</code> file, the contents of which should look like the following:</p>
<pre><code class="language-xml">&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;jboss-deployment-structure xmlns=&quot;urn:jboss:deployment-structure:1.1&quot;&gt;
    &lt;deployment&gt;
        &lt;exclusions&gt;
            &lt;module name=&quot;org.jboss.logging&quot; /&gt;
            &lt;module name=&quot;org.hibernate&quot; /&gt;
            &lt;module name=&quot;org.hibernate.validator&quot; /&gt;
        &lt;/exclusions&gt;
    &lt;/deployment&gt;
&lt;/jboss-deployment-structure&gt;
</code></pre>
<p>The reason for this is to isolate and exclude dependencies you don't want to inherit from JBoss 7. I also recommend disabling Spring Boot re-packaging of the WAR file if you don't plan to run as a standalone WAR. You can do that by adding the following to <code>build.gradle</code>:</p>
<pre><code class="language-groovy">bootRepackage.enabled = false
</code></pre>
<h2>JNDI DataSource Configuration</h2>
<p>To configure a JNDI datasource you should first define the production data source as using JNDI:</p>
<pre><code class="language-yaml">environments:
    development:
        dataSource:
            dbCreate: create-drop
            url: jdbc:h2:mem:devDb
    test:
        dataSource:
            dbCreate: update
            url: jdbc:h2:mem:testDb
    production:
        dataSource:
            jndiName: &quot;java:jboss/datasources/MyDataSource&quot;
            dbCreate: none   
</code></pre>
<p>Note that you typically do not want the Grails tooling to create the schema for you so we set <code>dbCreate</code> to <code>none</code>. You can then run <code>grails schema-export</code> to generate a <code>build/ddl.sql</code> file that you can use to create the database in your production environment.</p>
<p>On the JBoss side if you are using standalone deployment, you need to modify the <code>standalone/configuration/standalone.xml</code> file to configure your JNDI datasource. For example for MySQL adding the following section within the <code>&lt;datasources&gt;</code> block will do:</p>
<pre><code class="language-xml">    &lt;datasource jndi-name=&quot;java:jboss/datasources/MyDataSource&quot; pool-name=&quot;MyDataSource&quot;&gt;
        &lt;connection-url&gt;jdbc:mysql://localhost:3306/my-database&lt;/connection-url&gt;
        &lt;driver&gt;com.mysql&lt;/driver&gt;
        &lt;transaction-isolation&gt;TRANSACTION_READ_COMMITTED&lt;/transaction-isolation&gt;
        &lt;pool&gt;
            &lt;min-pool-size&gt;10&lt;/min-pool-size&gt;
            &lt;max-pool-size&gt;100&lt;/max-pool-size&gt;
            &lt;prefill&gt;true&lt;/prefill&gt;
        &lt;/pool&gt;
        &lt;security&gt;
            &lt;user-name&gt;root&lt;/user-name&gt;
        &lt;/security&gt;
        &lt;statement&gt;
            &lt;prepared-statement-cache-size&gt;32&lt;/prepared-statement-cache-size&gt;
            &lt;share-prepared-statements&gt;true&lt;/share-prepared-statements&gt;
        &lt;/statement&gt;
    &lt;/datasource&gt;
</code></pre>
<h2>Deploying the Application</h2>
<p>Once you have prepared your application for deployment to deploy the app you can run <code>gradle assemble</code> to build a WAR file and then copy the generated WAR file located in <code>build/libs</code> to JBoss 7's <code>standalone/deployments</code> directory and then run <code>bin/standalone.sh</code>.</p>
<p>Note that if you receive an exception that looks like the following:</p>
<pre><code class="language-groovy">16:45:35,789 WARN  [org.jboss.as.ee] (MSC service thread 1-6) JBAS011006: Not installing optional component org.springframework.web.context.request.async.StandardServletAsyncWebRequest due to exception: org.jboss.as.server.deployment.DeploymentUnitProcessingException: JBAS011054: Could not find default constructor for class org.springframework.web.context.request.async.StandardServletAsyncWebRequest
    at org.jboss.as.ee.component.ComponentDescription$DefaultComponentConfigurator.configure(ComponentDescription.java:606)
</code></pre>
<p>This is apparently <a href="https://stackoverflow.com/questions/13786685/spring3-2-and-jboss-as-7">normal behaviour</a> and can be safely ignored.</p>
<h2>This Is WAY Too Hard</h2>
<p>I agree. Deploying to &quot;enterprise&quot; containers is not fun. It can, however, be a requirement where you work. In order to simplify these steps I have created a JBoss 7 profile for Grails apps that tries to encapsulate all these changes. Simply run:</p>
<pre><code class="language-bah">grails create-app myapp --profile org.grails.profiles:web-jboss7:1.0.0.RC1
</code></pre>
<p>This will create an application in the <code>myapp</code> directory with all the changes necessary apart from preparing the JNDI datasource. Hopefully the profile encourages more JBoss 7 folks to give the Grails framework a try. Happy deploying!</p>]]></description><author>Graeme Rocher</author><guid>2016-11-10</guid><pubDate>Thu, 10 Nov 2016 00:00:00 GMT</pubDate></item><item><title>Configuring Rolling Logging with Logback</title><link>https://grails.apache.org/blog/2016-11-01.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/logging.html"><span class="hashtag">#logging</span></a> <a href="https://grails.apache.org/blog/tag/logback.html"><span class="hashtag">#logback</span></a> <a href="https://grails.apache.org/blog/tag/config.html"><span class="hashtag">#config</span></a></p>
<p>A common requirement in web applications is to support a rolling log system, so that log files are rolled over on a schedule and archived after a certain point. Grails<sup>®</sup> 3 uses Logback (considered the successor to log4j) as its logging library, and it's quite simple to configure a rolling appender using Logback's Groovy config format.</p>
<p>The Grails framework includes a default Logback configuration at <code>grails-app/conf/logback.groovy</code>. By default (as of Grails 3.2.1), this file (which follows the standard Logback groovy config format) configures a single appender, an instance of <code>ConsoleAppender</code> called <code>STDOUT</code>, and conditionally (when in development mode) an instance of <code>FileAppender</code> called <code>FULL_STACKTRACE</code>. These may then be used by logger instances, which can target specific package names and log levels, and write to one or more appenders. You have access to the Grails <code>Environment</code>, so you can configure different combinations of appenders for development and production.</p>
<p>The default <code>logback.groovy</code> file in Grails 3.2.1 is shown below.</p>
<pre><code class="language-groovy">//grails-app/confg/logback.groovy
import grails.util.BuildSettings
import grails.util.Environment

// See https://logback.qos.ch/manual/groovy.html for details on configuration
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = &quot;%level %logger - %msg%n&quot;
    }
}

def targetDir = BuildSettings.TARGET_DIR
if (Environment.isDevelopmentMode() &amp;&amp; targetDir != null) {
    appender(&quot;FULL_STACKTRACE&quot;, FileAppender) {
        file = &quot;${targetDir}/stacktrace.log&quot;
        append = true
        encoder(PatternLayoutEncoder) {
            pattern = &quot;%level %logger - %msg%n&quot;
        }
    }
    logger(&quot;StackTrace&quot;, ERROR, ['FULL_STACKTRACE'], false)
    root(ERROR, ['STDOUT', 'FULL_STACKTRACE'])
}
else {
    root(ERROR, ['STDOUT'])
}
</code></pre>
<p>Let's add an instance of <a href="https://logback.qos.ch/manual/appenders.html#RollingFileAppender"><code>RollingFileAppender</code></a> for our production environment. Let's say we want to split out our log files by day, and keep 30 days worth of log files around (deleting any older ones). In addition, we don't have unlimited hard drive space, so we'll also set a file size cap so that the total disk space used by our logs never exceeds 2GB.</p>
<p>Here's our new appender:</p>
<pre><code class="language-groovy">//grails-app/confg/logback.groovy
import ch.qos.logback.core.rolling.RollingFileAppender
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy
import ch.qos.logback.core.util.FileSize


def HOME_DIR = &quot;.&quot;

appender(&quot;ROLLING&quot;, RollingFileAppender) {
  encoder(PatternLayoutEncoder) {
      pattern = &quot;%level %logger - %msg%n&quot;
  }
  rollingPolicy(TimeBasedRollingPolicy) {
      fileNamePattern = &quot;${HOME_DIR}/logs/myApp-%d{yyyy-MM-dd_HH-mm}.log&quot;
      maxHistory = 30
      totalSizeCap = FileSize.valueOf(&quot;2GB&quot;)
  }
}
</code></pre>
<p>An instance of <code>RollingFileAppender</code> needs two &quot;policies&quot;, a <code>rollingPolicy</code> (to define how to perform the rollover), and a <code>triggerPolicy</code> (which specifies when the rollover should occur). In this case, our <code>rollingPolicy</code> is <code>TimeBasedRollingPolicy</code>, which happens to implement the <code>TriggeringPolicy</code> interface and therefore satisfies both policy requirements. <code>TimeBasedRollingPolicy</code> is one of the most common rolling policies, and it will meet the majority of rolling log requirements.</p>
<p><code>TimeBasedRollingPolicy</code> gets both it's rolling behavior (creating a new log file with the current date/time in the file name) and it's triggering behavior (rollover will occur based on the specified timestamp pattern) from the <code>fileNamePattern</code> property.</p>
<blockquote>
<h2>What's In a Name?</h2>
<p>Maybe you'd rather not have the filenames of your log files contain the trigger interval. No worries, <code>RollingFileAppender</code> also supports a <code>file</code> property which can override this behavior, so your log files can be rolled over monthly (for example) without actually containing the date string in their filenames. See the documentation for <a href="https://logback.qos.ch/manual/appenders.html#RollingFileAppender"><code>RollingFileAppender</code></a> for more details.</p>
</blockquote>
<p>The trigger policy is the most interesting part here - it takes an approach that bases the rollover occurrence on how specific you define the timestamp in the <code>fileNamePattern</code>.  So if you specify down to the month, rollover will occur each month. Specify a pattern down to the day, and it will occur daily). It's easier to understand when you see it in action, so here's some example patterns taken from Logback's documentation:</p>
<pre><code class="language-groovy">  fileNamePattern = &quot;/myApp-log.%d{yyyy-MM}.log&quot;	      //Rollover at the beginning of each month, file format: myApp-log.2016-11.log
  fileNamePattern = &quot;/myApp-log.%d{yyyy-ww}.log&quot;	      //Rollover at the first day of each week. Note that the first day of the week depends on the locale.
  fileNamePattern = &quot;/myApp-log.%d{yyyy-MM-dd_HH}.log&quot;	//Rollover at the top of each hour.
</code></pre>
<p>Note that in the above examples we are configuring the timestamp in the filename of the log files. We can also use the timestamp to create a file directory structure, like this example:</p>
<pre><code class="language-groovy">fileNamePattern = &quot;/logs/%d{yyyy/MM}/myApp.log&quot;	//Rollover at the beginning of each month.
//Each log file will be stored in a year/month directory, e.g: /logs/2016/11/myApp.log, /logs/2016/12/myApp.log, /logs/2017/01/myApp.log
</code></pre>
<p>Finally, adding a <code>zip</code> or <code>gz</code> file extension to our <code>fileNamePattern</code> will apply the selected compression to the rolled-over log files:</p>
<pre><code class="language-groovy">fileNamePattern = &quot;/myApp-log.%d{yyyy/MM}.gz&quot;	      //Rollover at the beginning of each month, compress the rolled-over file with GZIP
</code></pre>
<p>Going back to our previous example, we're setting a couple more properties on our <code>TimeBasedRollingPolicy</code> -  <code>maxHistory</code> and <code>totalSizeCap</code>. These are pretty simple to understand; <code>maxHistory</code> sets the upper limit on how many log files to preserve (when the max is reached the oldest file is deleted), and <code>totalSizeCap</code> sets a cap on how much disk space our log files are allowed to use (again, when the cap is reached the oldest files are deleted). There are other useful options you can set here, see the <a href="https://logback.qos.ch/manual/appenders.html#TimeBasedRollingPolicy"><code>TimeBasedRollingPolicy</code> documentation</a> for a full list and explanation.</p>
<blockquote>
<h2>Warning!</h2>
</blockquote>
<blockquote>
<p>While the Logback docs suggest that <code>totalSizeCap</code> can be specified as a plain String (i.e, &quot;2GB&quot;), I've found that it needs to be specified as a <code>FileSize</code> to avoid casting exceptions - so make sure to use <code>FileSize.valueOf(&quot;2GB&quot;)</code> to evaluate your total size. This also applies to the <code>maxFileSize</code> property used in the <code>SizeBasedRollingPolicy</code> and <code>TimeAndSizeBasedRollingPolicy</code>.</p>
</blockquote>
<p>There are several more <a href="https://logback.qos.ch/manual/appenders.html#onRollingPolicies">rolling &amp; triggering policies</a> that are available, including <a href="https://logback.qos.ch/manual/appenders.html#SizeBasedTriggeringPolicy"><code>SizeBasedTriggerPolicy</code></a> and <a href="https://logback.qos.ch/manual/appenders.html#SizeAndTimeBasedRollingPolicy"><code>SizeAndTimeBasedTriggeringPolicy</code></a>, and <code>FixedWindowRollingPolicy</code></p>
<p>Finally, let's specify that we want our new <code>RollingFileAppender</code> to be used in production mode only, while keeping the default <code>ConsoleAppender</code> for development mode.</p>
<pre><code class="language-groovy">//grails-app/confg/logback.groovy
import grails.util.BuildSettings
import grails.util.Environment
import ch.qos.logback.core.rolling.RollingFileAppender
import ch.qos.logback.core.rolling.TimeBasedRollingPolicy
import ch.qos.logback.core.util.FileSize

def HOME_DIR = &quot;.&quot;

// See https://logback.qos.ch/manual/groovy.html for details on configuration
appender('STDOUT', ConsoleAppender) {
    encoder(PatternLayoutEncoder) {
        pattern = &quot;%level %logger - %msg%n&quot;
    }
}

appender(&quot;ROLLING&quot;, RollingFileAppender) {
  encoder(PatternLayoutEncoder) {
      pattern = &quot;%level %logger - %msg%n&quot;
  }
  rollingPolicy(TimeBasedRollingPolicy) {
      fileNamePattern = &quot;${HOME_DIR}/logs/myApp-%d{yyyy-MM-dd_HH-mm}.log&quot;
      maxHistory = 30
      totalSizeCap = FileSize.valueOf(&quot;2GB&quot;)
  }
}

def targetDir = BuildSettings.TARGET_DIR
if (Environment.isDevelopmentMode() &amp;&amp; targetDir != null) {
    appender(&quot;FULL_STACKTRACE&quot;, FileAppender) {
        file = &quot;${targetDir}/stacktrace.log&quot;
        append = true
        encoder(PatternLayoutEncoder) {
            pattern = &quot;%level %logger - %msg%n&quot;
        }
    }

    logger(&quot;StackTrace&quot;, ERROR, ['FULL_STACKTRACE'], false)
    root(ERROR, ['STDOUT', 'FULL_STACKTRACE'])
}
else {
    root(ERROR, ['ROLLING'])
}
</code></pre>
<p>And with that, we have our rolling log system. Enjoy!</p>
<h2>Resources</h2>
<ul>
<li>Logback documentions: <a href="https://logback.qos.ch/documentation.html">https://logback.qos.ch/documentation.html</a></li>
<li>Logback Groovy config (from the official docs): <a href="https://logback.qos.ch/manual/groovy.html">https://logback.qos.ch/manual/groovy.html</a></li>
<li>DZone - Logback Configuration Using Groovy:  <a href="https://dzone.com/articles/logback-configuration-using-groovy">https://dzone.com/articles/logback-configuration-using-groovy</a></li>
</ul>]]></description><author>Zachary Klein</author><guid>2016-11-01</guid><pubDate>Tue, 01 Nov 2016 00:00:00 GMT</pubDate></item><item><title>How to Use Travis-CI to Build and Deploy Your Plugin</title><link>https://grails.apache.org/blog/2016-10-03.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a> <a href="https://grails.apache.org/blog/tag/travis.html"><span class="hashtag">#travis</span></a></p>
<h2>Introduction</h2>
<p>When you create a Grails<sup>®</sup> 3 plugin and you want to share it with the world, wouldn't it be great if building and deploying was taken care of by a CI server?</p>
<p>In this blog I will show you how to set up a Grails Plugin project that will be built and deployed on the <a href="https://travis-ci.org/">Travis-CI infrastructure</a>.</p>
<p>Let us start out by setting up the project, so that it can be deployed to Bintray. Then we will add a Travis build to the mix. Finally we will explore how to handle snapshot deployment to <a href="https://oss.jfrog.org/">JFrog's open source repository</a>.</p>
<h2>How Travis-CI Works</h2>
<p>Travis-CI works by monitoring your GitHub repository and whenever it sees changes, it will make a build of your project. The change can be a new commit pushed to GitHub, a new tag pushed to GitHub, or a pull request to your project on GitHub.</p>
<p>If you want a deeper knowledge on how Travis-CI works, please <a href="https://docs.travis-ci.com/">see the documentation</a>.</p>
<h2>Getting Started</h2>
<p>While you might have a plugin already, let us start this example by creating a plugin. The plugin will not have any functionality; it is only here to show the steps.</p>
<pre><code class="language-bash">grails create-plugin -profile plugin demoplugin
cd demoplugin
</code></pre>
<p>To get Travis-CI working the project has to live on GitHub.</p>
<h3>Setting Up a GitHub Repository</h3>
<p>The first step is to enable Git for the local repository, add the project files, and commit it:</p>
<pre><code class="language-bash">git init
git add .
git commit -m &quot;Initial commit&quot;
</code></pre>
<p>Now go to <a href="https://github.com/">GitHub</a> where we create a new repository:</p>
<p><img src="2016-10-03-img01.png" alt="Create a new repository" /></p>
<p><img src="2016-10-03-img02.png" alt="" /></p>
<p><img src="2016-10-03-img03.png" alt="" /></p>
<p>And push the first commit to GitHub:</p>
<pre><code class="language-bash">git remote add origin https://github.com/sbglasius/demoplugin.git
git push -u origin master
</code></pre>
<h3>Publishing Plugin to Bintray</h3>
<p>Before configuring Travis, let us update the configuration to enable publishing the plugin to Bintray and the Grails Plugin Portal.</p>
<p><code>build.gradle</code> already contains the building blocks for this:</p>
<pre><code class="language-groovy">// ...
group &quot;org.grails.plugins&quot;
// ...
apply plugin:&quot;org.grails.grails-plugin&quot;
// ...
grailsPublish {
    // TODO: Provide values here
    user = 'user'
    key = 'key'
    githubSlug = 'foo/bar'
    license {
        name = 'Apache-2.0'
    }
    title = &quot;My Plugin&quot;
    desc = &quot;Full plugin description&quot;
    developers = [johndoe:&quot;John Doe&quot;]
    portalUser = &quot;&quot;
    portalPassword = &quot;&quot;    
}
</code></pre>
<p>As can be seen, some values are not filled in, like credentials and <code>githubSlug</code>. Let us add those values in a way where credentials are not visible in the public GitHub repository.</p>
<p>My code snippet will contain two ways to fetch configuration values:</p>
<pre><code class="language-groovy">grailsPublish {
    user = System.getenv(&quot;BINTRAY_USER&quot;) ?: project.bintrayUser
    key = System.getenv(&quot;BINTRAY_KEY&quot;) ?: project.bintrayKey
    githubSlug = 'https://github.com/sbglasius/demoplugin'
    license {
        name = 'Apache-2.0'
    }
    title = &quot;Demo Plugin&quot;
    desc = &quot;A Demo Plugin, no need to publish&quot;
    developers = [johndoe:&quot;John Doe&quot;]
    portalUser = System.getenv(&quot;GRAILS_PORTAL_USER&quot;) ?: project.grailsPortalUser
    portalPassword = System.getenv(&quot;GRAILS_PORTAL_PASSWORD&quot;) ?: project.grailsPortalPassword
}
</code></pre>
<p>The configuration values are now read from either the running environment (this is where Travis will provide them, more on this later) or they will be taken from the project configuration or Gradle's global configuration (<code>~/.gradle/gradle.properties</code>). That is where I recommend storing these credentials.</p>
<p>The format for <code>~/.gradle/gradle.properties</code> is like this:</p>
<pre><code class="language-properties">bintrayUser=user
bintrayKey=[secret]

grailsPortalUser=user
grailsPortalPassword=[secret]
</code></pre>
<p>With this in place, it is now possible to publish the plugin to Bintray. This can be done like this:</p>
<pre><code class="language-bash">./gradlew bintrayUpload
</code></pre>
<p>Before moving on to Travis, let me push this to GitHub:</p>
<pre><code class="language-bash">git add .
git commit -m &quot;Build script for Gradle&quot;
git push
</code></pre>
<h2>Set Up Travis Command Line</h2>
<p>Before we can use Travis, we need to install the Travis Command line. Travis Command line requires Ruby, and since my machine is a Mac, Ruby is included. For other OSes, please go <a href="https://www.ruby-lang.org/en/">here</a> for more information.</p>
<p>Install Travis</p>
<pre><code class="language-bash">gem install travis
</code></pre>
<h2>Adding Travis to the Project</h2>
<p>The first thing we will do is initialize Travis for the project.</p>
<pre><code class="language-bash">$ travis init
Detected repository as sbglasius/demoplugin, is this correct? |yes|
Main programming language used: |Ruby| Groovy
.travis.yml file created!
sbglasius/demoplugin: enabled :)
</code></pre>
<p>Take a look in <code>.travis.yml</code>. You should see one line of code:</p>
<pre><code class="language-yml">language: groovy
</code></pre>
<p>Let us push this change to GitHub:</p>
<pre><code class="language-bash">git add .travis.yml
git commit -m &quot;Added travis config&quot;
git push
</code></pre>
<p>This will result in the first Travis build – a failed build. When Travis tries to run <code>gradle assemble</code> it fails with the following error:</p>
<pre><code class="language-text">FAILURE: Build failed with an exception.
* Where:
Build file '/home/travis/build/sbglasius/demoplugin/build.gradle' line: 50
* What went wrong:
A problem occurred evaluating root project 'demoplugin'.
&gt; Could not find property 'bintrayUser' on root project 'demoplugin'.
* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output.
BUILD FAILED
</code></pre>
<p>As we can see from the error, it cannot find the <code>bintrayUser</code> in the properties – since it is not defined yet together with the other credential properties.</p>
<p>Travis has the ability to set environment variables defined in .travis.yml, but we do not want credentials in clear text. Fortunately, Travis support <a href="https://docs.travis-ci.com/user/environment-variables#Defining-Variables-in-.travis.yml">encrypting environment variables</a>. It is important to understand that the variables added here will only work for the GitHub account associated with the project.</p>
<h3>Adding Environment Variables to <code>.travis.yml.</code></h3>
<p>Let us add four variables to the configuration under <code>env.global</code>:</p>
<pre><code class="language-bash">travis encrypt BINTRAY_USER=user --add env.global
travis encrypt BINTRAY_KEY=*** --add env.global
travis encrypt GRAILS_PORTAL_USER=user --add env.global
travis encrypt GRAILS_PORTAL_PASSWORD=[secret] --add env.global
</code></pre>
<p>Now <code>.travis.yml</code> looks like this:</p>
<pre><code class="language-yml"> language: groovy
env:
  global:
  - secure: iU4Y3JVWFteYl6J9MIlKv4H6nT0...
  - secure: xPW7KBPVHe64hMloY30Oa5WowYO...
  - secure: mhCnvHfjPX+wudLOfo6B8MFVGBV...
  - secure: QF0+kEZLjL3ZJe0U/5jKC1dijgm...
</code></pre>
<p>and then commit and push to GitHub.</p>
<p><em>Now the build goes green on Travis</em>, but it is still not publishing the plugin to Bintray. That's up next.</p>
<h2>Publish to Bintray with Travis</h2>
<p>Travis should test <code>master</code> on GitHub every time code is committed. It should build pull-requests but should only release the plugin to Bintray, when Git is tagged with a new version.</p>
<p>The developers of Travis have thought of this and allow us to use a bash script to make more fine-grained logic. The basic script could look like this:</p>
<pre><code class="language-bash">#!/usr/bin/env bash

set -e
./gradlew clean check assemble --stacktrace

EXIT_STATUS=0
echo &quot;Publishing archives for branch $TRAVIS_BRANCH&quot;
if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' &amp;&amp; $TRAVIS_PULL_REQUEST == 'false' ]]; then
  if [[ -n $TRAVIS_TAG ]]; then
    echo &quot;Pushing build to Bintray&quot;
    ./gradlew bintrayUpload notifyPluginPortal || EXIT_STATUS=$?
  fi
fi
exit $EXIT_STATUS
fi
</code></pre>
<p>The script is currently a bit more advanced than it needs to be; that is because more functionality will be added later.</p>
<p>To execute the script on Travis-CI add these few lines to <code>.travis.yml</code>:</p>
<pre><code class="language-yml">before_script:
- rm -rf target
script: ./travis-build.sh
</code></pre>
<p>I prefer them before the <code>env:</code> block. To allow Travis to actually execute the script, it's important that the script execute flag on <code>travis-build.sh</code> is set:</p>
<pre><code class="language-bash">chmod 755 travis-build.sh
</code></pre>
<p>Add, commit, and push this to GitHub like before.</p>
<p>The result will be a successful build, but not a deployment to Bintray. This is of course due to the <code>if</code> statement in the bash script, which checks if a git tag is set. If it is the <code>master</code> branch and if it's not a pull-request.</p>
<h3>Tag and Release</h3>
<p>I now want to make a release of my plugin. To do so, I need to bump the plugin version in <code>build.gradle</code>, commit the change, tag the commit, and push it to GitHub.</p>
<p>Let me start with <code>build.gradle</code></p>
<pre><code class="language-groovy">version &quot;0.2&quot;
</code></pre>
<p>and the commit, tag, and push:</p>
<pre><code class="language-bash">git commit -a -m &quot;Bump revision to 0.2&quot;
git tag &quot;0.2&quot;
git push --tags
</code></pre>
<p>Notice, that I added <code>--tags</code> to the <code>git</code> command to get tags pushed to GitHub.</p>
<p>That's it. The build is automated, and a release can be created on Bintray by using Travis-CI and GitHub tagging.</p>
<h2>Deploy Snapshots to JFrog OSS Artifactory</h2>
<p>To have snapshot published to a public repo for others to use it, we can resort to Jfrog OSS Artifactory <a href="https://oss.jfrog.org/">oss.jfrog.org (OJO)</a>, since Bintray does not support snapshot builds. (This section is inspired by the <a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-greach-2016">blog post by Álvaro Sánchez</a>). Before you can publish to OJO, please read <a href="https://www.jfrog.com/confluence/display/RTF/Deploying+Snapshots+to+oss.jfrog.org">this document</a>.</p>
<h3>Setup Build Scripts</h3>
<p>Let us start with <code>build.gradle</code>:</p>
<pre><code class="language-groovy">buildscript {
   //...
}
plugins {
  id &quot;com.jfrog.artifactory&quot; version &quot;4.4.0&quot;
}

version &quot;0.3-SNAPSHOT&quot;
group &quot;demoplugin&quot;
//...
grailsPublish {
   //...
}
artifactory {
    contextUrl = 'https://oss.jfrog.org'
    publish {
        repository {
            repoKey = 'oss-snapshot-local'
            username = System.getenv(&quot;BINTRAY_USER&quot;) ?: project.bintrayUser
            password = System.getenv(&quot;BINTRAY_KEY&quot;) ?: project.bintrayKey
        }
        defaults {
            publications('maven')
        }
    }
}
</code></pre>
<p>Since OJO and Bintray are tightly coupled, it is the same credentials used.</p>
<p>Updated <code>travis-build.sh</code></p>
<pre><code class="language-bash">#!/usr/bin/env bash

set -e
./gradlew clean check assemble --stacktrace

EXIT_STATUS=0
echo &quot;Publishing archives for branch $TRAVIS_BRANCH&quot;
if [[ -n $TRAVIS_TAG ]] || [[ $TRAVIS_BRANCH == 'master' &amp;&amp; $TRAVIS_PULL_REQUEST == 'false' ]]; then
  if [[ -n $TRAVIS_TAG ]]; then
    echo &quot;Pushing build to Bintray&quot;
    ./gradlew bintrayUpload || EXIT_STATUS=$?
  else
    echo &quot;Publishing snapshot to OJO&quot;
    ./gradlew artifactoryPublish || EXIT_STATUS=$?
  fi
fi
exit $EXIT_STATUS
fi
</code></pre>
<p>Commit and push to GitHub and go watch the build on Travis-CI. Notice, that the build ends with a push to OJO.</p>
<p>That's it. Travis-CI will now publish both snapshot versions and tagged versions to OJO and Bintray.</p>
<p>But wait – there is a bit more.</p>
<h2>Optimizing Travis-CI setup</h2>
<p>Take a look at the log-output from Travis-CI and notice that it downloads Gradle and all of the maven dependencies on each build.</p>
<p>Travis-CI supports caching of these artifacts and a couple of other options.</p>
<p>Add the following to <code>.travis.yml</code> just below the <code>language: groovy</code> block:</p>
<pre><code class="language-yml">sudo: false # run on container-based infrastructure

before_cache:
  - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock
cache:
  directories:
    - $HOME/.gradle/caches/
    - $HOME/.gradle/wrapper/
    - $HOME/.m2/repositories/
</code></pre>
<p>This will reduce downloads and build time on Travis-CI.</p>
<h2>Conclusion</h2>
<p>Travis-CI is a great tool to build and deploy your Grails plugin; it will help you maintain your code when receiving pull requests from the community. Happy CI'ing!</p>]]></description><author>Søren Berg Glasius</author><guid>2016-10-03</guid><pubDate>Mon, 03 Oct 2016 00:00:00 GMT</pubDate></item><item><title>Grails® 3.2 and GORM 6.0 Released</title><link>https://grails.apache.org/blog/2016-09-28.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>Today we are pleased to announce the GA releases of <a href="https://github.com/apache/grails-core/releases/tag/v3.2.0">Grails<sup>®</sup> 3.2</a> and <a href="https://gorm.grails.org/latest/">GORM 6.0</a>.</p>
<p>Each of these releases represents a significant step forward for the framework and marks the second major release since <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) began sponsoring development.</p>
<h2>GORM 6.0</h2>
<p><a href="https://gorm.grails.org/6.0.x">GORM 6.0</a> continues our goal of making GORM a standalone technology that can be used outside of the Grails framework. By separating GORM from the Spring container, it is now easier to bootstrap and use GORM in a range of different scenarios, from usage in Grails apps to Spring Boot apps to within a unit test.</p>
<p>In addition we have addressed often-requested features in GORM including:</p>
<ul>
<li>Multiple Data Sources Support for MongoDB and Neo4j</li>
<li>Unified multi-tenancy support for Hibernate, MongoDB and Neo4j</li>
<li>GORM for MongoDB 3.3 driver</li>
<li>GORM for Neo4j 3.0 and Bolt Driver support</li>
<li>Unified configuration across all implementations</li>
</ul>
<p>There is so much new and improved functionality in GORM that we prepared a dedicated &quot;<a href="https://gorm.grails.org/latest/whatsNew/manual/index.html">What's New&quot; guide</a> just for GORM 6.0.</p>
<p>Also, check out the <a href="https://gorm.grails.org/latest/">brand new GORM 6 website</a> for links to documentation for each implementation of GORM.</p>
<h2>RxGORM</h2>
<p>In additional to the traditional GORM API, a new API for GORM has been introduced based on <a href="https://github.com/ReactiveX/RxJava/wiki">RxJava</a> called <a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM</a>. With RxGORM you can write non-blocking, reactive data access code for supported implements.</p>
<p>For the first release of RxGORM, implementations for <a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">MongoDB</a> and <a href="https://gorm.grails.org/6.0.x/rx/rest-client/manual/index.html">REST</a> are provided, with more implementations planned.</p>
<h2>Grails 3.2</h2>
<p>Grails 3.2 bundles all of the goodness of GORM 6, plus a whole bunch of new features in the core framework:</p>
<ul>
<li>RxJava support via a <a href="/plugins.html#plugin/rxjava">new plugin</a>.</li>
<li>Improved <a href="https://views.grails.org/">JSON View</a> support.</li>
<li>AngularJS scaffolding</li>
<li>REST improvements</li>
<li>Latest and greatest libraries (Spring Boot 1.4, Gradle 3.0, etc.)</li>
</ul>
<p>These are just some of the highlights. I recommend checking out the dedicated <a href="https://grails.apache.org/docs/3.2.x/guide/introduction.html#whatsNew">&quot;What's New&quot;</a> section in the brand new Asciidoctor-based <a href="https://grails.apache.org/docs/3.2.x">user guide</a> for more information.</p>
<p>Finally, thanks to all those who contributed feedback and issue reports to the release. We look forward to the continued participation of the Grails community as the framework continues to evolve.</p>]]></description><author>Graeme Rocher</author><guid>2016-09-28</guid><pubDate>Wed, 28 Sep 2016 00:00:00 GMT</pubDate></item><item><title>How to Migrate from Resources Plugin to Asset-Pipeline</title><link>https://grails.apache.org/blog/2016-09-12.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/plugins.html"><span class="hashtag">#plugins</span></a></p>
<h2>Introduction</h2>
<p>Since Grails<sup>®</sup> 2.4.0, <a href="https://github.com/wondrify/asset-pipeline">asset-pipeline</a> has been the default plugin recommended to manage the static resources in a Grails application. In earlier versions of the Grails framework, the <a href="https://github.com/grails-plugins/grails-resources">resources</a> plugin was an option, but with Grails 3, the only viable option is using asset-pipeline because resources is not available in Grails 3.</p>
<p>If you want to know how to migrate from resources to asset-pipeline, this post is for you.</p>
<h2>Let's Migrate!</h2>
<p>I recommend you start the migration analyzing your layouts because probably those files contain most of your static resources (javascripts and css files). Imagine that the content of your <code>main.gsp</code> layout is the following:</p>
<pre><code class="language-html">&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'bootstrap.min.css') }&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'jquery-ui-1.10.3.full.min.css') }&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'jquery-ui-1.10.3.custom.min.css') }&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'jquery.gritter.css') }&quot; /&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'ui.jqgrid.css') }&quot; /&gt;

&lt;script src=&quot;${resource(dir:'assets/js', file:'bootstrap.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery-2.0.3.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery-ui-1.10.3.custom.min.js') }&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery-ui-1.10.3.full.min.js') }&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.mobile.custom.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.slimscroll.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.gritter.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.hotkeys.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.easy-pie-chart.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.maskedinput.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.dataTables.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'jquery.dataTables.bootstrap.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js/jqGrid', file:'jquery.jqGrid.min.js')}&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;${resource(dir:'assets/js/jqGrid/i18n', file:'grid.locale-en.js')}&quot;&gt;&lt;/script&gt;
</code></pre>
<p>As you can see, there are a bunch of css and javascript files that are mostly related to jQuery, but all of those files are on the same directory. When doing the migration, we're also going to reorganize the files in a better way.</p>
<p>By default, asset-pipeline creates the directories <code>images</code>, <code>javascripts</code>, and <code>stylesheets</code> under <code>grails-app/assets</code> directory. Any file you copy into those directories can be served by the plugin. The easy way would be to copy all of the css and javascript files to those directories and change the way we import the resources.</p>
<p>For example, with the following directory structure:</p>
<pre><code class="language-bash">.
├── javascripts
│   └── bootstrap.min.js
└── stylesheets
    └── bootstrap.min.css
</code></pre>
<p>You could replace the following code:</p>
<pre><code class="language-html">&lt;!-- Using resources --&gt;
&lt;link rel=&quot;stylesheet&quot; href=&quot;${resource(dir: 'assets/css', file:'bootstrap.min.css') }&quot; /&gt;
&lt;script src=&quot;${resource(dir:'assets/js', file:'bootstrap.min.js')}&quot;&gt;&lt;/script&gt;
</code></pre>
<p>With this one:</p>
<pre><code class="language-html">&lt;!-- Using asset-pipeline --&gt;
&lt;asset:stylesheet src=&quot;bootstrap.min&quot; &gt;&lt;/asset:stylesheet&gt;
&lt;asset:javascript src=&quot;bootstrap.min&quot; &gt;&lt;/asset:javascript&gt;
</code></pre>
<p>Please notice that you don't need to include the <code>.js</code> or <code>.css</code> extension because asset-pipeline will add it when looking for the files in those directories.</p>
<p>As I said, you could just copy all those files and create a lot of entries in your layout using <code>asset:stylesheet</code> and <code>asset:javascript</code>, but we can do it better.</p>
<h2>Defining Bundles</h2>
<p>If you take a look at the content of the <code>grails-app/assets</code> directory created by default, you can find the files <code>application.js</code> and <code>aplication.css</code>.</p>
<p>Let's take a look at the content of the <code>application.css</code> file:</p>
<pre><code class="language-css">/*
* This is a manifest file that'll be compiled into application.css, which will include all the files
* listed below.
*
* Any CSS file within this directory can be referenced here using a relative path.
*
* You're free to add application-wide styles to this file and they'll appear at the top of the
* compiled file, but it's generally better to create a new file per style scope.
*
*= require bootstrap
*= require grails
*= require main
*= require mobile
*= require_self
*/
</code></pre>
<p>We're defining a bundle called <code>application</code> (the name of the file) that will contain <code>bootstrap</code>, <code>grails</code>, <code>main</code>, and <code>mobile</code> stylesheet files. Starting with that we're going to add the rest of the original files we were using with resources plugin:</p>
<pre><code class="language-css">/*
*= require bootstrap.min
*= require jquery/css/jquery-ui-1.10.3.full.min
*= require jquery/css/jquery-ui-1.10.3.custom.min
*= require jquery/css/jquery.gritter
*= require jqGrid/ui.jqgrid
*/
</code></pre>
<p>You can create arbitrary bundles of your js and css files, defining files in the root of those directories and declaring the files you want to add to that bundle. Now we're going the create a bundle for the javascript files:</p>
<pre><code class="language-javascript">//
// require bootstrap.min
//= require jquery/js/jquery-2.0.3.min
//= require jquery/js/jquery-ui-1.10.3.custom.min
//= require jquery/js/jquery-ui-1.10.3.full.min
//= require jquery/js/jquery.mobile.custom.min
//= require jquery/js/jquery.slimscroll.min
//= require jquery/js/jquery.gritter.min
//= require jquery/js/jquery.hotkeys.min
//= require jquery/js/jquery.easy-pie-chart.min
//= require jquery/js/jquery.maskedinput.min
//= require jquery/js/jquery.dataTables.min
//= require jquery/js/jquery.dataTables.bootstrap

//= require jqGrid/jquery.jqGrid.min
//= require jqGrid/i18n/grid.locale-en
</code></pre>
<p>With these two bundles defined, the only thing you need to do is replace all those javascript and stylesheet imports in your layout with the following lines:</p>
<pre><code class="language-html">&lt;asset:stylesheet src=&quot;application&quot; &gt;&lt;/asset:stylesheet&gt;
&lt;asset:javascript src=&quot;application&quot; &gt;&lt;/asset:javascript&gt;
</code></pre>
<p>Now we can run the application, open the inspector and see what happens:</p>
<p><img src="2016-09-12-img01.jpg" alt="Javascripts" /></p>
<p><img src="2016-09-12-img02.jpg" alt="Stylesheets" /></p>
<p>All the javascript and css files are loaded in debug mode. This means that the resources won't be optimized and you'll have hot-reloading of the changes. This is the default behavior during development. For production all files will be minified and included in one file per bundle:</p>
<p><img src="2016-09-12-img03.jpg" alt="assets-minifies-prod" /></p>
<h2>Organizing Bundles</h2>
<p>One last thing about organizing the bundles is that if we want to create our custom directories, we need to create a top level directory in <code>grails-app/assets</code>, and inside that directory, we can create our arbitrary structure. I've named this directory <code>libs</code>, but you can use the name you want:</p>
<pre><code class="language-bash">.
├── javascripts
│   ├── application.js
│   └── bootstrap.min.js
├── libs
│   ├── jqGrid
│   │   ├── i18n
│   │   │   └── grid.locale-en.js
│   │   ├── jquery.jqGrid.min.js
│   │   └── ui.jqgrid.css
│   └── jquery
│       ├── css
│       │   ├── jquery.gritter.css
│       │   ├── jquery-ui-1.10.3.custom.min.css
│       │   └── jquery-ui-1.10.3.full.min.css
│       └── js
│           ├── jquery-2.0.3.min.js
│           ├── jquery.dataTables.bootstrap.js
│           ├── jquery.dataTables.min.js
│           ├── jquery.easy-pie-chart.min.js
│           ├── jquery.gritter.min.js
│           ├── jquery.hotkeys.min.js
│           ├── jquery.maskedinput.min.js
│           ├── jquery.mobile.custom.min.js
│           ├── jquery.slimscroll.min.js
│           ├── jquery-ui-1.10.3.custom.min.js
│           └── jquery-ui-1.10.3.full.min.js
└── stylesheets
    ├── application.css
    └── bootstrap.min.css
</code></pre>
<p>Effectively, asset-pipeline treats each of the subdirectories of <code>grails-app/assets</code> as another root for locating assets.</p>
<h2>Conclusion</h2>
<p>As you have seen in this post, it's pretty simple to organize the static resources using asset-pipeline plugin and migrate from resources.</p>
<p>If you want to take a closer look to the code, this example application is available <a href="https://github.com/ilopmar/example-asset-pipeline">here</a>.</p>]]></description><author>Iván López</author><guid>2016-09-12</guid><pubDate>Mon, 12 Sep 2016 00:00:00 GMT</pubDate></item><item><title>Retrieving Config Values In Grails® 3</title><link>https://grails.apache.org/blog/2016-08-31.html</link><description><![CDATA[</p>
<h2>Introduction</h2>
<p>The Grails<sup>®</sup> framework leverages the “Convention Over Configuration” design paradigm, which functions to decrease the number of decisions that a developer using the framework is required to make without losing flexibility. This is one of the ways Grails significantly increases developer productivity!</p>
<p>While Grails applications often involve considerably less configuration than similar applications built with other frameworks, some configuration may still be necessary. This post will detail a number of mechanisms that make it easy for Grails developers gain access to those configuration values at runtime.</p>
<h3>application.yml</h3>
<p>The default configuration file for Grails 3 applications is <code>grails-app/conf/application.yml</code>. In this file, <a href="https://yaml.org/">YAML</a> syntax is supported.</p>
<pre><code class="language-yaml">dataSource:
    pooled: true
    jmxExport: true
    driverClassName: org.h2.Driver
</code></pre>
<p>That file defines 3 configuration properties.</p>
<pre><code class="language-plaintext">dataSource.pooled = true
dataSource.jmxExport = true
dataSource.driverClassName = 'org.h2.Driver'
</code></pre>
<p>This article will not go into detail about YAML syntax. For that see <a href="https://yaml.org/">the main YAML site</a>. Instead, this article will focus on Grails 3 specific features related to accessing those configuration values.</p>
<h2>The Config Property in GrailsApplication</h2>
<p>The <a href="https://grails.apache.org/docs/3.1.10/api/grails/core/GrailsApplication.html">GrailsApplication</a> interface defines the <a href="https://grails.apache.org/docs/3.1.10/api/grails/core/GrailsApplication.html#getConfig()">getConfig</a> method which returns a <a href="https://grails.apache.org/docs/3.1.10/api/grails/config/Config.html">Config</a> object. In the Spring application context is a bean named <code>grailsApplication</code> which is an instance of a class which implements the <code>GrailsApplication</code> interface. Retrieving the config object from this bean is one way to gain access to config values.</p>
<pre><code class="language-yaml"># grails-app/conf/application.yml
max:
    line:
        numbers: 42
</code></pre>
<pre><code class="language-groovy">// grails-app/init/BootStrap.groovy

import grails.core.GrailsApplication

class BootStrap {

    // this property will be auto-wired from
    // the Spring application context...
    GrailsApplication grailsApplication

    def init = { servletContext -&gt;
        // retrieve the max.line.numbers config value
        def maxLineNumbers =  grailsApplication.config.getProperty('max.line.numbers')

        // ...

    }
}
</code></pre>
<blockquote>
<p>NOTE: <code>config.getProperty('max.line.numbers')</code> is preferred over something like <code>config.max.line.numbers</code>. The latter can result in unexpected behavior when retrieving values that do not exist and also is less performant.</p>
</blockquote>
<h3>Type Conversions</h3>
<p>There is an overloaded version of the <code>getProperty</code> method that accepts a type. This overloaded method will convert the corresponding config value to the specified type.</p>
<pre><code class="language-groovy">// retrieve the max.line.numbers config value
// returns null if the config value does not
// exist or if the type conversion fails
Integer maxLineNumbers =  config.getProperty('max.line.numbers', Integer)
</code></pre>
<h3>Default Values</h3>
<p>There is another overloaded version of the <code>getProperty</code> method which accepts both a type and a default value.</p>
<pre><code class="language-groovy">// retrieve the max.line.numbers config value
// returns 2112 if the config value does not
// exist or if the type conversion fails
Integer maxLineNumbers =  config.getProperty('max.line.numbers', Integer, 2112)
</code></pre>
<h3>Required Properties</h3>
<p>For required properties you could write application code that reacts however is appropriate if the property doesn't exist. You could also use the <a href="https://grails.apache.org/docs/3.1.10/api/grails/config/ConfigMap.html#getRequiredProperty(java.lang.String,%20java.lang.Class)">getRequiredProperty</a> method which will throw an exception if a requested property does not exist.</p>
<pre><code class="language-groovy">// retrieve the max.line.numbers config value
// throws IllegalStateException if the
// config value does not exist
Integer maxLineNumbers =  config.getRequiredProperty('max.line.numbers', Integer)
</code></pre>
<h2>Config Dependency Injection</h2>
<p>For config values that are needed during request processing, an application may want to retrieve the value only once instead of retrieving it repeatedly during each request that requires access to the config value. For example, the following is not ideal because the application is paying the performance price of retrieving the config value every time the controller action is invoked.</p>
<pre><code class="language-groovy">import grails.config.Config

class SomeController {

    def someAction() {
        Config config = grailsApplication.config
        // this would happen for every request to this action...
        int maxLineNumbers = config.getProperty('max.line.numbers', Integer, 10)

        // ...
    }
}
</code></pre>
<h3>Config Injection Using GrailsConfigurationAware</h3>
<p>An alternative is to retrieve the config value only once and then hold on to it so that it may be used later as many times as necessary. One way to do this is to have the config injected into any bean by implementing the <a href="https://grails.apache.org/docs/3.1.10/api/grails/core/support/GrailsConfigurationAware.html">GrailsConfigurationAware</a> interface. There is a bean post processor that will discover all beans that implement at that interface and that post processor will invoke the <a href="https://grails.apache.org/docs/3.1.10/api/grails/core/support/GrailsConfigurationAware.html#setConfiguration(grails.config.Config)">setConfiguration</a> method on those beans, passing the config object as an argument.</p>
<pre><code class="language-groovy">import grails.config.Config
import grails.core.support.GrailsConfigurationAware

class WidgetService implements GrailsConfigurationAware {

    int area

    def someServiceMethod() {
        // this method may use the area property...
    }

    @Override
    void setConfiguration(Config co) {
        int width = co.getProperty('widget.width', Integer, 10)
        int height = co.getProperty('widget.height', Integer, 10)
        area = width * height
    }
}
</code></pre>
<h3>Config Injection Using @Value</h3>
<p>Another option for injecting config values is to use the <a href="https://docs.spring.io/spring/docs/4.2.6.RELEASE/javadoc-api/org/springframework/beans/factory/annotation/Value.html">@Value</a> annotation.</p>
<pre><code class="language-groovy">import org.springframework.beans.factory.annotation.Value

class WidgetService {

    int area

    @Value('${widget.width}')
    int width

    def someServiceMethod() {
        // this method may use the width property...
    }
}
</code></pre>
<p>In the example above, an exception will be thrown if the <code>widget.width</code> config value does not exist. In order to provide a default value with the <code>@Value</code> annotation, provide the default value after a <code>:</code> in the expression supplied to the annotation.</p>
<pre><code class="language-groovy">import org.springframework.beans.factory.annotation.Value

class WidgetService {

    @Value('${widget.width:50}')
    int width

    def someServiceMethod() {
        // this method may use the area property...
    }
}
</code></pre>
<h2>Conclusion</h2>
<p>The examples above detail several approaches for retrieving config values at runtime. Grails intentionally provides several options, each with its own strengths and flexibility. Knowing where and when config values need to be accessible will help dictate which approach makes the most sense for a particular use case.</p>]]></description><author>Jeff Scott Brown</author><guid>2016-08-31</guid><pubDate>Wed, 31 Aug 2016 00:00:00 GMT</pubDate></item><item><title>GR8Conf US 2016 Wrap-up!</title><link>https://grails.apache.org/blog/2016-08-01.html</link><description><![CDATA[</p>
<p><img src="2016-08-01-img01.png" alt="The OCI Grails® team at GR8Conf US 2016" /></p>
<p>Well I've just started to clear my fuzzy head getting back from <a href="https://gr8conf.us/">GR8Conf US</a> in Minneapolis, where OCI was a platinum sponsor this year. Lots of good stuff came out of the show, things announced, good workshops. There were 4 concurrent tracks of talks for 2 days, and 1 day of workshops. In all, the OCI Grails team delivered 4 workshops and 8 talks - most of the team creates these talks on their own time as well in addition to our regular responsibilities. We are dedicated!</p>
<p><img src="2016-08-01-img02.jpg" alt="" /></p>
<p>I grew up in a suburb in St. Paul and had not been back since I started speaking at Gr8Conf 3-4 years ago. What a beautiful city it is now! So much stuff going on, sports games, music, breweries and a pretty clean downtown. Can't recommend enough to come visit here in the summer - that said I would avoid it in the thick of winter - it's so cold they build sky-bridges to connect the buildings to minimize the outside elements! Check out one of these great buildings at night. The picture below is looking out from the University of St. Thomas, the venue.</p>
<p><img src="2016-08-01-img03.png" alt="Skyline" /></p>
<h2>Day 1: Workshops</h2>
<p><img src="2016-08-01-img04.jpg" alt="Ryan and Lee presenting Alexa, Tell Me I'm Groovy" /></p>
<p>I started the day doing my Groovy Lego Mindstorms EV3 talk where we worked with putting Groovy apps on the robots, then used the Grails framework to control the robots like Mars rovers. I Then did a 2nd half day workshop with my friend Lee Fox on Amazon Alexa. We built Groovy Lambda Skills as well as Grails 3 Skills.</p>
<p><img src="2016-08-01-img05.jpeg" alt="Jeff Scott Brown presenting at GR8Conf US 2016" /></p>
<p>Jeff Brown then did 2(!) back-to-back workshops on 'Getting Started with Grails 3' and 'Rest with Grails 3' (*Pic by Annyce Davis).</p>
<p>Danny Hyun did a Groovy intro workshop where he taught people to use a Pokemon Java API to help them catch them all in Groovy (all day).
Marcin Erdmann (His first stateside appearance at Gr8?) did an all day Ratpack sandbox workshop.</p>
<h2>Day 2: Talks</h2>
<p><img src="2016-08-01-img06.jpg" alt="Graeme Rocher presenting the keynote presentation" /></p>
<p>Graeme Rocher kicked off the conference with his keynote about all the goodness upcoming in Grails 3.2, GORM 6, and how overall better things are about Grails 3 as well as the future.</p>
<p>Here we start the 4 parallel tracks, with one being 'Groovy for Java Developers' by Puneet Behl where he teaches how Groovy makes life better for Java devs.</p>
<p>In the same slots were &quot;Getting Started with Grails 3&quot; by OCI Grails team member Colin Harrington gave a great Grails 3 intro talk.</p>
<p>Also there was &quot;GroovyFX - Groove JavaFX&quot; by Alexander Sasha Klein on all the goodies aroung GroovyFX.</p>
<p>Next up: Dynamic GORM by Burt Beckwith, Monitoring and Metrics with Grails 3 by OCI Grails Team co-founder Jeff Scott Brown. Craig Burke always brings the laughs with &quot;Practical and Stupidly Impractical Groovy DSLs. Android Groovy plugin maintainer Andrew Reitz did a good talk on testing Gradle plugins, which is something people often overlook but is needed.</p>
<p><img src="2016-08-01-img07.jpeg" alt="Ryan and Lee presenting Alexa, Tell Me I'm Groovy Day 2" /></p>
<p>Next slot after lunch: Lee Fox and I do the &quot;Alexa Tell me I'm Groovy&quot; talk which we covered AWS Groovy Lambda Skills and The Grails 3 plugin. Lee made a superhero quiz game and Baruch from JFrog stepped up to test his skills. Needless to say he said his name and Alexa said 'I heard bottles' and proceeded to ask 'Bottles' trivia questions. So that is Baruch's new nickname, try it out next time you see him :) The audience got lots of laughs from all the Alexa antics we did. It gets better, we used a Grails app we wrote for Alexa to live-tweet the audience reaction. So much fun!</p>
<p>While this was going on fellow OCI Grails team member Alvaro Sanchez-Mariscal did 'Mastering Grails 3 Plugins' with some solid advice on Grails 3 to avoid pain later. Asset-pipeline creator Dave Estes did a great talk on the ins and outs of asset-pipeline which every Grails developer should learn and know. Finishing this slot is Jenn Strater's talk on a TDD Approach to Documenting Restful APIs which a lot of people were excited about all of the documentation tools she showed off.</p>
<p>Last talk slot of the day:</p>
<p>Bob the Builder by Sascha Klein shared his tips of using builder patterns for daily survival. Teammate Alvaro continued with another talk on Creating apps with the Grails framework, AngularJS, and Spring Security which is a shorter talk version of the workshop he did at Gr8Conf.eu this year. Annyce Davis a new speaker I met this year did a great talk on From the Grails framework to Android: A Simple Journey. Finishing the talks for the day was Jenn Strater with &quot;CodeNarc Revisited.&quot;</p>
<p><img src="2016-08-01-img08.jpeg" alt="Alvaro presenting on Grails, Angular, and DDS" /></p>
<p>Kenneth Kousen closed up the day with a great keynote that talked about all the value Groovy and all the community has to offer.</p>
<p><img src="2016-08-01-img09.jpeg" alt="Ken Kousen delivering a keynote at GR8Conf US 2016" /></p>
<p>After the talks and keynote, Object Partners was kind enough to bus everyone to their new offices in North Minneapolis for Gr8ConfUS beer, appetizers, and Groovy Puzzlers with Baruch(Bottles) and Dan Woods.</p>
<p><img src="2016-08-01-img10.jpeg" alt="Groovy Puzzlers with Baruch(Bottles) and Dan Woods" /></p>
<p><img src="2016-08-01-img11.jpeg" alt="Gr8ConfUS Beer" /></p>
<h2>Day 3 Talks</h2>
<p>We roll into day 3 running with (almost) a complete track of talks about Ratpack by Dan Woods (9am after late night karaoke, impressive!), non web Ratpack with John Engelman, and testing Rackpack with Danny Hyun. Back to chronological order, Puneet Behl talked about Giving back to the community by helping migrate 2.x plugins to 3.x. Annyce David talked about Gradle Plugin Goodness, and Ryan Applegate talked about scaling Grails apps at SmartThings.</p>
<p>Craig Burke talked about AngularJS in Grails apps as well as trolled Kyle Boon and myself pretty hard (His test is totally rigged I say!). Jeff Brown from OCI Grails Team talked about Groovy Metaprogramming, and Charlie Knudsen talked about a strategy to get to zero downtime deployments.</p>
<p><img src="2016-08-01-img12.jpeg" alt="Colin Harrington's presentation about how to secure your Grails application via Spring Security Plugins" /></p>
<p>Next slot we had fellow OCI Grails teammate Colin Harrington talk about how to secure your Grails application via Spring Security Plugins. Sacha Klein also gave a Groovy with Jenkins talk about using Groovy in your CI pipeline. Todd Miller talked about Spring Cloud in production with tools like Eureka and Hystrix/Turbine to monitor your apps. Craig Atkinson also gave a great Spock and Geb into talk.</p>
<p>After lunch Burt Beckwith talked about Spring Security, Christian Oestreich talked about monitoring Grails 3 applications, Craig Atkinson gave another great functional testing talk with Geb. Stephen Pember gave a mind-bender talk on Reactive Streams and Groovy to finish out the time slot.</p>
<p>Last talks of the day are now underway with &quot;Grails Reactive Event-Driven Architecture&quot; by Christian Oestreich (He maintains several Grails plugins like CXF/Client), Dockerize It All by Puneet Behl, and last but not least a JOOQ intro talk by Stephen Pember.</p>
<p>Wrapping up the conference, John Engelman gave the closing keynote about writing software in the Agile age, culture devops, and other good stuff.</p>
<p>After that, Ken Kousen and Baruch(Bottles) Sadogursky did a live Groovy podcast with a studio audience!. The link for it is <a href="https://www.youtube.com/watch?v=MWRWnKfbnIs">here</a>.</p>
<p><img src="2016-08-01-img13.jpeg" alt="Gr8Ladies-sponsored happy hour" /></p>
<p>Once the broadcast concluded, most of the attendees went home, but many speakers and attendees stayed and went to the Gr8Ladies sponsored happy hour. That extended to the roof later, where the Ratpack folks really showed their dance moves, especially Danny Hyun!</p>
<p><img src="2016-08-01-img14.png" alt="Ratpack folks showing off their dance moves, especially Danny Hyun" /></p>
<p>Special thanks to out to all the volunteers and helpers for the conference, especially Bobby Warner, Shaun Jurgenmeyer, Eric Kinsella, Doug Sabers, and Jenn Strater!</p>
<p>I hope to be back again next year, as you won't find a nicer, friendlier accessible bunch than the folks at the Gr8Conf conferences. Come for the content, stay for the socialization and networking! The more I go to these events, I find the value scale for networking goes higher and higher, which is something you just can't get off youtube videos and posted slides. Come to see what others are doing or not doing because it didn't work - It could save your next project from failure!</p>
<hr />
<h2>Slide Decks From the Conference</h2>
<p>(cobbled together and ripped from tweets and Grails Diary)</p>
<h3>Workshops</h3>
<p><a href="https://www.dropbox.com/sh/ah2uxd9he0x4p4f/AACGHZEiY-PP9Zl3qpLCI4XOa?dl=0">Exercises for Getting started with Grails 3 (Jeff Scott Brown)</a></p>
<p><a href="https://www.slideshare.net/ryanvanderwerf/getting-groovy-with-lego-mindstorms-ev3-gr8conf-us-2016">Getting Groovy with Lego Mindstorms (Ryan Vanderwerf)</a></p>
<p><a href="https://www.slideshare.net/ryanvanderwerf/amazon-alexa-workshop-grpovy-and-grails-gr8conf-us-2016">Amazon Alexa Workshop (Ryan Vanderwerf and Lee Fox</a> also labs <a href="https://sites.google.com/site/alexaskillslab/">here</a></p>
<p><a href="https://danhyun.github.io/2016-gr8conf-groovy-workshop/">Groovy Workshop 2016 (Daniel Hyun)</a></p>
<h3>Talks – Day 2</h3>
<p><a href="https://slides.com/colinharrington/getting-started-with-grails-3-gr8confus-2016#/">Getting started with Grails 3 (Colin Harrington)</a></p>
<p><a href="http://www.craigburke.com/practical-groovy-dsl/">Practical and Stupidly Impractical Groovy DSLs (Code) (Craig Burke)</a></p>
<p><a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-us-2016">Alexa, Tell Me I'm Groovy (Ryan Vanderwerf / Lee Fox)</a></p>
<p><a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-gr8conf-us-2016">Mastering Grails 3 plugins (Alvaro Sanchez-Mariscal)</a></p>
<p><a href="https://speakerdeck.com/jlstrater/codenarc-revisited-gr8conf-us-2016">Codenarc Revisited (Jenn Strater)</a></p>
<p><a href="https://www.adavis.info/2016/07/talk-from-grails-to-android.html">From Grails to Android (Annyce Davis)</a></p>
<p><a href="https://speakerdeck.com/jlstrater/a-test-driven-approach-to-documenting-restful-apis-with-spring-rest-docs-gr8conf-us">A Test-Driven Approach to Documenting RESTful APIs with Spring REST Docs (Jenn Strater)</a></p>
<h3>Talks – Day 3</h3>
<p><a href="https://slides.com/colinharrington/springsecuritysurvey-gr8conf-us-2016#/">Securing your Grails application: A survey/layout of the security plugin space (Colin Harrington)</a></p>
<p><a href="https://speakerdeck.com/rappleg/scaling-grails-at-smartthings">Scaling Grails at SmartThings (Ryan Applegate)</a></p>
<p><a href="https://www.adavis.info/2016/07/talk-gradle-plugin-goodness.html">Gradle Plugin Goodness (Annyce Davis)</a></p>
<p><a href="https://www.slideshare.net/alvarosanchezmariscal/creating-applications-with-grails-angular-js-and-spring-security-gr8conf-us-2016">Creating applications with Grails, Angular JS and Spring Security - (code) (Alvaro Sanchez-Mariscal)</a></p>
<p><a href="https://craigatk.github.io/spock-geb-intro/">Intro to Spock and Geb (Craig Atkinson)</a></p>
<p><a href="https://github.com/Grails-Plugin-Consortium/gr8conf-monitoring-metrics">Monitoring Grails 3 Applications (Christian Oestreich)</a></p>
<p><a href="https://github.com/Grails-Plugin-Consortium/gr8conf-event-driven-microservices">Grails Reactive Event-Driven Architecture (Christian Oestreich)</a></p>
<p><a href="https://craigatk.github.io/geb-tips-tricks/#/">Geb Tips and Tricks (Craig Atkinson)</a></p>
<p><a href="https://danhyun.github.io/2016-gr8confus-testing-ratpack-apps/">Testing Ratpack Applications (Danny Hyun)</a></p>
<p><a href="https://www.slideshare.net/StevePember/reactive-streams-and-the-wide-world-of-groovy-64526341">Reactive Streams and the Wide World of Groovy (Steve Pember)</a></p>
<p><a href="https://www.slideshare.net/StevePember/an-introduction-to-jooq">An Introduction to jOOQ - code (Steve Pember)</a></p>
<h3>Some Other Recaps</h3>
<p><a href="https://www.adavis.info/2016/07/gr8conf-us-2016-recap.html">Annyce Davis</a></p>
<p><a href="https://rpalcolea.github.io/blog/2016/GR8Conf-US-Recap-2016.html">Roberto Perez A.</a></p>
<p>I look forward to the next edition in 2017!</p>
<p>— Ryan Vanderwerf and the rest of the OCI/Grails Team</p>]]></description><author>Ryan Vanderwerf</author><guid>2016-08-01</guid><pubDate>Mon, 01 Aug 2016 00:00:00 GMT</pubDate></item><item><title>Grails® 3.2 M2 and GORM 6.0 M2 Released</title><link>https://grails.apache.org/blog/2016-07-22.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>Today the <a href="https://objectcomputing.com/products/2gm-team">Grails team</a> at <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) is pleased to announce the release of <a href="https://github.com/apache/grails-core/releases/tag/v3.2.0.M2">Grails<sup>®</sup> 3.2 Milestone 2</a>, which includes <a href="https://gorm.grails.org/6.0.x">GORM 6 Milestone 2</a> - the biggest GORM release ever!</p>
<p>The <a href="https://gorm.grails.org/6.0.x">new version of GORM</a> is really the theme of this release. There are so many great new features that we wrote a dedicated <a href="https://gorm.grails.org/6.0.x/whatsNew/manual/index.html">&quot;What's New&quot;</a> guide just for GORM (to go along with the new dedicated GORM documentation).</p>
<p>Just to summarize the new features in GORM include:</p>
<ul>
<li><a href="https://gorm.grails.org/6.0.x/neo4j/manual/index.html">GORM for Neo4j</a> 3.0 Bolt Driver Support</li>
<li><a href="https://gorm.grails.org/6.0.x/mongodb/manual/index.html">GORM for MongoDB</a> 3.2 Drivers</li>
<li><a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM - GORM for RxJava</a></li>
<li><a href="https://gorm.grails.org/1.0.x/rx/rest-client/manual">RxGORM for REST</a> built on RxNetty</li>
<li><a href="https://gorm.grails.org/6.0.x/rx/manual/index.html">RxGORM for MongoDB</a> built on the MongoDB Rx Driver</li>
<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#multipleDataSources">Universal Multiple Data Sources Support</a> includin a new <a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#connectionSources">ConnectionSources API</a></li>
<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#multiTenancy">Multi Tenancy Support</a> for Hibernate, MongoDB and Neo4j</li>
<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#outsideGrails">Spring Container Free Bootstrapping</a></li>
<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#configuration">Unified Configuration API</a></li>
<li><a href="https://gorm.grails.org/6.0.x/hibernate/manual/index.html#testing">Improved Unit Testing</a></li>
</ul>
<p>Of course GORM 6.0 is usable in all versions of Grails 3.x.</p>
<p>On the Grails side, Grails 3.2 ships with release candidates of the new AngularJS 1.0 scaffolding (Angular 2.0 support is coming) and JSON Views 1.1 plugins as well as numerous improvements to the profiles.</p>
<p>Grails 3.2 has also been updated to the latest and greatest dependencies including Spring Boot 1.4 RC1 and Spring 4.3.</p>
<p>Check out the <a href="https://grails.apache.org/docs/3.2.x/guide/introduction.html#whatsNew">What's New in Grails 3.2 Guide</a> for information on all the updates.</p>
<p>We're inching closer to an RC now so it is a great time to try your applications and <a href="https://github.com/apache/grails-core/issues">report issues</a>!</p>
<p>If you want to hear more come and see us at Gr8Conf US in Minneapolis USA, or G3 Summit in Fort Lauderdale USA!</p>]]></description><author>Graeme Rocher</author><guid>2016-07-22</guid><pubDate>Fri, 22 Jul 2016 00:00:00 GMT</pubDate></item><item><title>Grails® Angular Scaffolding</title><link>https://grails.apache.org/blog/2016-07-06.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/angular.html"><span class="hashtag">#angular</span></a></p>
<p>Creating a single-page application (SPA) has never been easier than it is with the new <a href="https://github.com/grails-plugins/grails-angular-scaffolding">Grails<sup>®</sup> Angular Scaffolding Plugin</a>! This post will give you a short tutorial on how to use it.</p>
<hr />
<p>The easiest way to get started with the scaffolding is to use the angular profile in Grails 3.2.0 or higher, which installs and configures the plugin automatically. See the <a href="https://grails-plugins.github.io/grails-angular-scaffolding/latest">documentation</a> for information on how to get the plugin installed into an existing application.</p>
<p>For this tutorial, we will be working with the following domain classes.</p>
<pre><code class="language-groovy">    package com.myblog

    import grails.rest.Resource

    @Resource(uri=&quot;/post&quot;)
    class Post {
        URL url
        PostContent postContent
        static embedded = ['postContent']
        static hasMany = [comments: Comment , tags: Tag]
        static constraints = {
        }
    }
    //---------------------------------
    package com.myblog

    class PostContent {
        String title
        String body
        Date published
        static constraints = {
        }
    }
    //---------------------------------
    package com.myblog

    import grails.rest.Resource

    @Resource(uri=&quot;/tag&quot;)
    class Tag {
        String name
        static constraints = {
        }
    }
    //---------------------------------
    package com.myblog

    import grails.rest.Resource

    @Resource(uri=&quot;/comment&quot;)
    class Comment {
        String text
        static belongsTo = [post: Post]
        static constraints = {
        }
    }
</code></pre>
<h2>Generating Assets</h2>
<p>Generating client-side assets with this plugin is very easy. In this example, the domain class you would like to have assets generated for is <code>com.myblog.Post</code>:</p>
<pre><code>    grails ngGenerateAll com.myblog.Post
</code></pre>
<p>To specify you wish any generated files to overwrite existing files:</p>
<pre><code>    grails ngGenerateAll com.myblog.Post true
</code></pre>
<p>You can also execute the same command with gradle:</p>
<pre><code>    ./gradlew ngGenerateAll -Pargs=&quot;com.myblog.Post true&quot;
</code></pre>
<p>Some assets that are generated are common to all scaffolded modules. The scaffolding will generate those assets in the “core” module. The core module will be created in the same package as the module being generated if it doesn’t exist already.</p>
<p>If a core module already exists, it will not be overwritten, even if the overwrite parameter is true.</p>
<p>The following structure will be produced.</p>
<p><img src="2016-07-06-img01.png" alt="Structure" /></p>
<p>Note that other modules were created along with the post module.</p>
<p>A module for the <code>Comment</code> domain was created because the scaffolding will convert the list of comments to be instances of the <code>Comment</code> JavaScript domain.</p>
<p>The module for the <code>Tag</code> domain was also created by the scaffolding. The purpose of doing so is to facilitate retrieving a list of tags to choose from when creating a <code>Post</code>.</p>
<p>The modules for the <code>Tag</code> and <code>Comment</code> domains do not provide CRUD functionality. They exist solely to assist the <code>Post</code> module.</p>
<p>In the future, if you wish to scaffold the CRUD of <code>Tag</code>s or <code>Comment</code>s, execute the <code>ngGenerateAll</code> command with the second parameter set to “true” so the existing assets will be overwritten.</p>
<h2>Using the Assets</h2>
<p>If you are using the angular profile in Grails 3.2.0 or higher, none of the steps below are required because they are all done for you!</p>
<p>If you are working with an existing application, there are a few steps you must take to make everything work together as designed.</p>
<ol>
<li>
<p>Ensure that the required third-party libraries exist where the scaffolding expects them to be.</p>
<p>The scaffolding requires angular, angular-resource, and ui-router to function as designed. The default locations for those assets are:</p>
<ul>
<li>/angular/angular.js</li>
<li>/angular/angular-ui-router.js</li>
<li>/angular/angular-resource.js</li>
</ul>
<p>You can change the default locations with configuration. See the <a href="https://grails-plugins.github.io/grails-angular-scaffolding/latest/#_asset_paths">asset paths</a> section in the documentation to learn how to do so.</p>
</li>
<li>
<p>Ensure the required asset pipeline plugins have been imported.</p>
<p>The scaffolding is designed around the use of three asset pipeline plugins. Include the plugins in your project via the instructions in the links below.</p>
<ul>
<li><a href="https://github.com/craigburke/angular-annotate-asset-pipeline">Angular Annotate Asset Pipeline</a></li>
<li><a href="https://github.com/craigburke/angular-template-asset-pipeline">Angular Template Asset Pipeline</a></li>
<li><a href="https://github.com/craigburke/js-closure-wrap-asset-pipeline">JS Closure Wrap Asset Pipeline</a></li>
</ul>
</li>
<li>
<p>Ensure databinding handles the default date format.</p>
<p>The scaffolding relies on the default format Angular applies to dates when they are included in a request. In Grails 3.1.x, the date format is not included in the default list of date formats that databinding will attempt to use. You can easily add it yourself via configuration.</p>
</li>
</ol>
<pre><code>        grails:
            databinding:
                dateFormats:
                    - &quot;yyyy-MM-dd'T'HH:mm:ss.SSSX&quot;
</code></pre>
<ol start="4">
<li>
<p>Ensure the module is loaded on the page</p>
<p>If the &quot;parent&quot; module is already being required by your current code, there is nothing you need to do to get the newly generated module to be included wherever the parent module is. The scaffolding will automatically attempt to create a module dependency and require statement in the parent module.</p>
<p>Here is an example of what that might look like.</p>
</li>
</ol>
<pre><code>        grails ngGenerateAll com.myblog.Post
</code></pre>
<pre><code>*   If `grails-app/assets/javascripts/com/myblog/com.myblog.js` exists, it will be considered to be the parent module. The scaffolding will attempt to edit the file to add a dependency to the `post` module.

If a parent module does not exist or the parent module isn’t being included on the desired page, it is up to you to use asset pipeline to include it where it is needed.
</code></pre>
<ol start="5">
<li>
<p>Ensure a <code>ui-view</code> directive is on the page for the state to load HTML into.</p>
<p>See the ui-view [documentation](https://github.com/angular-ui/ui-router/wiki/Quick-Reference#ui-view target=) on how to do this.</p>
</li>
<li>
<p>Ensure the <code>ng-app</code> directive is on the page. <code>ng-app=&quot;com.myblog.post&quot;</code></p>
</li>
<li>
<p>Naviage to the route <code>[http://localhost:8080/#post](http://localhost:8080/#post)</code></p>
</li>
</ol>
<h2>CRUD</h2>
<p>The following images depict what you will see when you have successfully navigated to the ‘post’ route and begin creating <code>Post</code>s.</p>
<p>List
<img src="2016-07-06-img02.png" alt="List" /></p>
<p>Create
<img src="2016-07-06-img03.png" alt="Create" /></p>
<p>Note that clicking “Add Comment” at this time will not have any effect because the comment scaffolding has not been created.</p>
<p>Show
<img src="2016-07-06-img04.png" alt="Show" /></p>
<h2>Generating Associated Domains</h2>
<p>The logical next step will be to generate the <code>Tag</code> scaffolding so we can create tags. This will allow us to choose tags when creating or editing our <code>Post</code>.</p>
<pre><code>    grails ngGenerateAll com.myblog.Tag true
</code></pre>
<p>Note that the second parameter “true” is important because we already had a Tag module which we will need to overwrite in order for the scaffolding to function correctly.</p>
<p>In addition, we can generate the comment scaffolding so we can assign comments to posts.</p>
<pre><code>    grails ngGenerateAll com.myblog.Comment true
</code></pre>
<p>The following are screen captures of what you can expect once the associated domain classes are generated.</p>
<h3>Tag</h3>
<p>Create
<img src="2016-07-06-img05.png" alt="Create" /></p>
<p>Show
<img src="2016-07-06-img06.png" alt="Show" /></p>
<p>List
<img src="2016-07-06-img07.png" alt="List" /></p>
<h3>Comment</h3>
<p>Create
<img src="2016-07-06-img08.png" alt="Create" /></p>
<p>Show
<img src="2016-07-06-img09.png" alt="Show" /></p>
<p>List
<img src="2016-07-06-img10.png" alt="List" /></p>
<h2>Conclusion</h2>
<p>Now that all domain classes have scaffolding, you can manage your data in a single page application.</p>
<p>The scaffolding is designed as a starting point for rapid development. Explore the generated JavaScript code and make changes to meet your business requirements. If you run into any issues, please submit an issue on the github page <a href="https://github.com/grails-plugins/grails-angular-scaffolding/issues">here</a> or come chat with us about it in our <a href="https://grails.slack.com/">Slack</a> channel.</p>
<p>For a complete run through of installing and using the scaffolding in Grails 3.1.x, check out this <a href="/blog/2017-01-20-2.html">Quickcast</a>!</p>
<p>The example project created in the video is available <a href="https://github.com/grails-samples/angular-scaffolding-31x">here</a>.</p>]]></description><author>James Kleeh</author><guid>2016-07-06</guid><pubDate>Wed, 06 Jul 2016 00:00:00 GMT</pubDate></item><item><title>Building Alexa Skills with the Grails® framework</title><link>https://grails.apache.org/blog/2016-06-26.html</link><description><![CDATA[</p>
<p><img src="2016-06-26-img01.jpg" alt="building spoken-language apps and experiences for Amazon Echo" /></p>
<p>Recently I gave a talk at GR8Conf.eu about building applications for the Amazon Alexa platform. I talked about using Groovy with Lambdas to demonstrate Skills (Alexa Apps), as well as using the Grails<sup>®</sup> framework. I'll give this talk again at GR8Conf.us at the end of July and have even more good stuff to show. On top of that, after working on this for months, I have the material to deliver an Alexa workshop at GR8Conf.us (Thanks to Colin Harrington for helping with the idea). Good Times!</p>
<p>I wanted to write a post as a step-by-step on using a plugin I've recently developed to help you crank out Alexa apps (skills or speechlets). Amazon has a promotion right now: If you submit a new skill to their library, you can win a free t-shirt, so maybe you can make something cool with this and get one! You do not even need an Amazon device; you can point your browser to <a href="https://echosim.io/">https://echosim.io</a> to use their emulator.</p>
<p><img src="2016-06-26-img02.png" alt="Echo-ism" /></p>
<p>Let me first get started to explain how these things work and a little about the devices.</p>
<p>Starting a couple years ago, Amazon released a home device/speaker thing called the Echo. It's a household helper device with very nice multi-directional microphones and a nice speaker for playing music.</p>
<p>At first, I didn't get one or understand it; it sounded like a useless toy to me. However peers gobbled them up and started playing around with them. They weren't building apps for it but raved about how cool it was and how it helped them automate their homes and do useful things. Then they started saying they loved it so much they were buying more units and putting them all over their houses. Now my attention was had – of course the first thing that pops into my head was 'how can I get Groovy to work with this thing?'</p>
<p><img src="2016-06-26-img03.jpg" alt="Things Alexa Can Do" /></p>
<p>The first examples they give are all about AWS Lambda functions in Node; however they aren't fantastic on Java because they have a hard limit of 50mb jars you can upload. Surely you can't fit the whole Grails framework and dependencies in there to do much.</p>
<p>Still, we gave it a shot. I followed Benoit Hédiard's <a href="https://skillsmatter.com/skillscasts/7291-serverless-microservices-using-aws-lambda-and-groovy">presentation</a> on Groovy with Lambdas from GGX 2015. I sat down with a buddy of mine, Lee Fox (he will be at GR8Conf.us), and we hammered out a bunch of ideas we could build with it – in Groovy of course!</p>
<p>The first app we got working was a simple Twitter app that combined Groovy, Spring Social, and Skills to make a skill that would connect to Twitter and search for tweets, as well as give updates to your timeline. You can find the code <a href="https://github.com/rvanderwerf/alexa-twitter-groovy">here</a>.</p>
<p>Good! Now we're getting somewhere. I did a little digging and found they have some servlet support to make a standalone web service – now we can get Grails involved and make this less hideous.</p>
<p>Next we took it a level up. We didn't want the user to have to hard-code their Twitter API keys to run the app, and you can't publish a skill that pulls down someone else's Twitter info. So we built a Grails app that used Spring Security, Oath plugin, and Spring Security UI to allow a UI that lets you register and enter your own Twitter keys for your account. Source for that is <a href="https://github.com/rvanderwerf/twitterAuth">here</a>.</p>
<p>After that, it was time to make a plugin to help you make these skills, which I published while I was out at GR8Conf.eu <a href="https://github.com/rvanderwerf/grails-alexa-skills">here</a>. It works similar to the Quartz plugin, in that you have a CLI command to create a working template of a Skill to get you started.</p>
<p>I will show you here how to build a skill using the Grails plugin to get you started making your own Skills in a short amount of time.</p>
<h2>How Alexa Service Works</h2>
<p>The devices themselves, (which are currently the Echo, Tap, Dot, and FireTV) don't do a whole lot. They even publish the source to the devices for you to look at if you choose <a href="https://www.amazon.com/gp/help/customer/display.html?nodeId=201626480">here</a>.</p>
<p>The magic resides on the Amazon side that handles all the voice recognition and handling of requests. Basically what happens is the user initiates an action (skill) on the device, and it goes to the alexa service to figure out what you want to do. When your app is invoked, it calls back to your app via a JSON HTTPS call and initiates a series of Intents to make your app do things. Your app simply waits for the call and takes appropriate action (via JSON) to do what you want. It's up to you as the developer to make it do something useful.</p>
<p><img src="2016-06-26-img04.jpg" alt="Alexa Appkit Architecture" /></p>
<p>The picture above gives you an idea of how it works (from Amazon's site). Let's go over Intents and Sample utterances to have a better idea of what's going on.</p>
<h2>Intents</h2>
<p>Intents are sort of like simplified Intents on android if you have ever done Android coding. They signal an intention for a command to run to do something.</p>
<p>Let's look at an example one to get an idea:</p>
<pre><code class="language-json">{
  &quot;intents&quot;: [
    {
      &quot;intent&quot;: &quot;ResponseIntent&quot;,
      &quot;slots&quot;: [
        {
          &quot;name&quot;: &quot;Answer&quot;,
          &quot;type&quot;: &quot;AMAZON.LITERAL&quot;
        }
      ]
    },
    {
      &quot;intent&quot;: &quot;QuestionCountIntent&quot;,
      &quot;slots&quot;: [
        {
          &quot;name&quot;: &quot;Count&quot;,
          &quot;type&quot;: &quot;AMAZON.NUMBER&quot;
        }
      ]
    },
    {
      &quot;intent&quot;: &quot;AMAZON.HelpIntent&quot;
    }
  ]
}
</code></pre>
<p>Here this application can trigger three intents:</p>
<ol>
<li>ResponseIntent</li>
<li>QuestionCountIntent</li>
<li>HelpIntent</li>
</ol>
<p>You use JSON to tell it what these are.</p>
<p>You can define 'slots,' which are the expected responses. They comprise a name and Type. There are pre-defined data types you can use to help Amazon parse what is said. Number for example knows the user is going to say a number. Literal is a simple String. Some intents, like the help intent, don't need anything, as they are 'built in' (no inputs).</p>
<p>A little bit about slots:</p>
<p>They are entirely optional. You can do things like define a list of allowed responses (custom slots) that are valid things for the user to say. In this case the ResponseIntent is free form, and we sort out what we want to do by parsing the string we get from Amazon (translated via TTS).</p>
<h2>Sample Utterances</h2>
<p>Let's look at another example:</p>
<pre><code>    ResponseIntent {test|Answer}
    ResponseIntent {last player|Answer}
    ResponseIntent {test test|Answer}
    ResponseIntent {test test test|Answer}
    ResponseIntent {test test test test|Answer}
    QuestionCountIntent {Count} questions
</code></pre>
<p>Here we see the intent each utterances (what the person says) and map it to an intent.</p>
<ul>
<li>Amazon will generate common words like conjunctions and ignored things on their end, so you don't have to mess with handling things like 'and', 'the', 'or' etc.</li>
<li>Variables are surrounded by {}.</li>
<li>You can use the | operator to specify alternate options.</li>
</ul>
<p>If you want to say something to your skill, it must match the pattern here. For this case, we want to parse multi-world answers to a question. Basically, here we support one, two, three, or four word responses – anything else will be cut off/ignored.</p>
<p>The last item allows the user to answer how many questions they want to be asked.</p>
<h2>Requirements</h2>
<ul>
<li>A publicly available container (Self running Grails jar, Tomcat, Elastic Beanstalk, etc) to launch your app with HTTPS on port 443 (no way around this). Can be self-signed for DEV mode only.</li>
<li>If you want to use audio snippets via SSML, they must be hosted as above, but with a recognized CA (no self-signed). S3 Static HTTPS buckets are easiest.</li>
<li>SSL Certificate common name MUST match hostname (even for self-signed DEV certs)</li>
</ul>
<h2>Let's Make a Grails App Using the Plugin and I Will Explain More as We Go</h2>
<p>The plugin is for Grails 3.x only. Let's create a new app first:</p>
<pre><code>    grails create-app skillsTest
</code></pre>
<p>Now let's open build.gradle and add the plugin into the dependencies {} closure:</p>
<pre><code>    compile &quot;org.grails.plugins:alexa-skills:0.1.1&quot;
</code></pre>
<p>Now let's create a skill from the command line:</p>
<pre><code>    grails create-speechlet SkillsTest
    | Rendered template Speechlet.groovy to destination grails-app/speechlets/skillstest/SkillsTestSpeechlet.groovy
</code></pre>
<p>Now let's see what it's created in grails-app/speechlets:</p>
<pre><code class="language-groovy">@Slf4j
class SkillsTestSpeechlet implements GrailsConfigurationAware, Speechlet {

    def grailsApplication

    Config grailsConfig
    def speechletService


    def index() {
        speechletService.doSpeechlet(request,response, this)
    }

    /**
     * This is called when the session is started
     * Add an initialization setup for the session here
     * @param request SessionStartedRequest
     * @param session Session
     * @throws SpeechletException
     */
    public void onSessionStarted(final SessionStartedRequest request, final Session session)
            throws SpeechletException {
        log.info(&quot;onSessionStarted requestId={}, sessionId={}&quot;, request.getRequestId(),
                session.getSessionId())

    }

    /**
     * This is called when the skill/speechlet is launched on Alexa
     * @param request LaunchRequest
     * @param session Session
     * @return
     * @throws SpeechletException
     */
    public SpeechletResponse onLaunch(final LaunchRequest request, final Session session)
            throws SpeechletException {
        log.info(&quot;onLaunch requestId={}, sessionId={}&quot;, request.getRequestId(),
                session.getSessionId())

        return getWelcomeResponse()
    }

    /**
     * This is the method fired when an intent is called
     *
     * @param request IntentRequest intent called from Alexa
     * @param session Session
     * @return SpeechletResponse tell or ask type
     * @throws SpeechletException
     */
    public SpeechletResponse onIntent(final IntentRequest request, final Session session)
            throws SpeechletException {
        log.info(&quot;onIntent requestId={}, sessionId={}&quot;, request.getRequestId(),
                session.getSessionId())

        log.debug(&quot;invoking intent:${intentName}&quot;)
        PlainTextOutputSpeech speech = new PlainTextOutputSpeech()
        // Create the Simple card content.
        SimpleCard card = new SimpleCard(title:&quot;Twitter Search Results&quot;)
        def speechText = &quot;I will say something&quot;
        def cardText = &quot;I will print something&quot;
        // Create the plain text output.
        speech.setText(speechText)
        card.setContent(cardText)
        SpeechletResponse.newTellResponse(speech, card)

    }
    /**
     * Grails config is injected here for configuration of your speechlet
     * @param co Config
     */
    void setConfiguration(Config co) {
        this.grailsConfig = co
    }

    /**
     * this is where you do session cleanup
     * @param request SessionEndedRequest
     * @param session
     * @throws SpeechletException
     */
    public void onSessionEnded(final SessionEndedRequest request, final Session session)
            throws SpeechletException {
        log.info(&quot;onSessionEnded requestId={}, sessionId={}&quot;, request.getRequestId(),
                session.getSessionId())
        // any cleanup logic goes here
    }

    SpeechletResponse getWelcomeResponse()  {
        String speechText = &quot;Say something when the skill starts&quot;

        // Create the Simple card content.
        SimpleCard card = new SimpleCard(title: &quot;YourWelcomeCardTitle&quot;, content: speechText)

        // Create the plain text output.
        PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)

        // Create reprompt
        Reprompt reprompt = new Reprompt(outputSpeech: speech)

        SpeechletResponse.newAskResponse(speech, reprompt, card)
    }

    /**
     * default responder when a help intent is launched on how to use your speechlet
     * @return
     */
    SpeechletResponse getHelpResponse() {
        String speechText = &quot;Say something when the skill need help&quot;
        // Create the Simple card content.
        SimpleCard card = new SimpleCard(title:&quot;YourHelpCardTitle&quot;,
                content:speechText)
        // Create the plain text output.
        PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)
        // Create reprompt
        Reprompt reprompt = new Reprompt(outputSpeech: speech)
        SpeechletResponse.newAskResponse(speech, reprompt, card)
    }

    /**
     * if you are using account linking, this is used to send a card with a link to your app to get started
     * @param session
     * @return
     */
    SpeechletResponse createLinkCard(Session session) {

        String speechText = &quot;Please use the alexa app to link account.&quot;
        // Create the Simple card content.
        LinkAccountCard card = new LinkAccountCard()
        // Create the plain text output.
        PlainTextOutputSpeech speech = new PlainTextOutputSpeech(text:speechText)
        log.debug(&quot;Session ID=${session.sessionId}&quot;)
        // Create reprompt
        Reprompt reprompt = new Reprompt(outputSpeech: speech)
        SpeechletResponse.newTellResponse(speech, card)
    }

}
</code></pre>
<p>Also the plugin will generate a Controller class embedded in your Speechlet file. If you are using Spring Security, you will want to make sure that uri is accessible to the outside to the Alexa service can contact it (there are some requirements I'll fill you in on later):</p>
<pre><code class="language-groovy">/**
 * this controller handles incoming requests - be sure to white list it with SpringSecurity
 * or whatever you are using
 */
@Controller
class SkillsTestController {

    def speechletService
    def skillsTestSpeechlet


    def index() {
        speechletService.doSpeechlet(request,response, skillsTestSpeechlet)
    }

}

</code></pre>
<p>The speechlet artefact will be registered as a Spring bean so it's automatically injected. There is also a service the plugin provides to handle the boring stuff like verifying the request, checking the app ID (more on that later) and the plumbing that calls your skill.</p>
<h2>Built-in Events</h2>
<p>Looking at the code example above, you can see it made several methods for you. These are part of the skill (speechlet) lifecycle. The first one is:</p>
<h3><code>onSessionStarted</code></h3>
<p>This allows you to store variables for the duration of the session (the interactions as a whole of the app for that time). You can do some setup here and store variables you can use later. This is technically optional for you to implement.</p>
<h3><code>onLaunch</code></h3>
<p>This is called when you invoke the skill. When you say 'Alexa open skillTest' etc. this is you chance to say an opening message about your app, what it does, or what they will need to do.</p>
<h3><code>onIntent</code></h3>
<p>This is the meat and is required to be implemented. When your sample utterances maps to an Intent when the user says something this is invoked.</p>
<p>Here you should generate a card that will appear in the Alexa app on your phone (you can also get to this on your local network via browser by going to 'echo.amazon.com'. Cards are similar to Android cards (more popular in Android Wear) that simply show a message to the user so they can see what is going on.</p>
<p>You can make several kinds of cards which are Simple, Standard, and LinkAccount. Here we have a switch statement to figure out what Intent to process and call the code for the appropriate intent.</p>
<h3><code>onSessionEnded</code></h3>
<p>This is the last one, optional, where you can clean up session resources you might have created like database records for the run.</p>
<p>I've added a few other helper methods to see how to render a help response, link an account, and get some setup details from the Grails config. As a first pass, just try to get the default template working, then start to change things like changing the text, add an Intent, etc.</p>
<h2>Set Up Your App on Amazon Developer Portal</h2>
<p>This is separate from AWS. I am not aware of any APIs that will create all of this for you so you have to sign up for an account and do this by hand for each skill you want to run.</p>
<p><img src="2016-06-26-img05.png" alt="Amazon Developer Portal" /></p>
<ul>
<li>
<p>Pull down the 'twitterAuth' app <a href="https://github.com/rvanderwerf/twitterAuth">here</a> to get some Intents/Sample utterances to try. They are located in src/main/resources.</p>
</li>
<li>
<p>Sign up for the Amazon developer program <a href="https://developer.amazon.com/">here</a> if you haven't already</p>
</li>
<li>
<p>Click on Apps and Services -&gt; Alexa</p>
</li>
<li>
<p>Click on Alexa Skill Kit / Get Started -&gt; Add New Skill</p>
</li>
</ul>
<p><img src="2016-06-26-img06.png" alt="Create a New Alexa Skill" /></p>
<ul>
<li>Pick any name and any invocation name you want to start the app on your Echo / Alexa Device</li>
</ul>
<p><img src="2016-06-26-img07.png" alt="Interaction Model" /></p>
<ul>
<li>
<p>Copy the contents of src/main/resources/IntentSchema.json into Intent Schema.</p>
</li>
<li>
<p>Don't fill in anything for slots</p>
</li>
<li>
<p>Under Sample Utterances, copy the contents of the file src/main/resources/SampleUtterances.txt</p>
</li>
</ul>
<p><img src="2016-06-26-img08.png" alt="Configuration" /></p>
<ul>
<li>
<p>Under configuration copy the url for /twitterAuth/twitter/index for the endpoint for your server (choose amazon https not ARN). Click next.</p>
</li>
<li>
<p>Leave 'enable account linking' turned off.</p>
</li>
<li>
<p>For domain list, enter a domain that matches your SSL cert the oauth tokens will be valid for. You may use a self-signed cert for development mode, but if you want to publish your skill, your server will need to be running a real recognized certificate (a cheap option is RapidSSL).</p>
</li>
<li>
<p>Enter the url for the privacy policy on your server. It can be any valid web page, a link will show during account linking in the alexa app</p>
</li>
<li>
<p>Hit Save</p>
</li>
<li>
<p>Click on SSL Certificate. If you have a self-signed cert (will only work for DEV mode) paste it here under 'I will upload a self-signed certificate in X.509 format.'</p>
</li>
<li>
<p>Hit Save and go to Test page and hit Save</p>
</li>
</ul>
<p><img src="2016-06-26-img09.png" alt="Test" /></p>
<ul>
<li>Go to Privacy and Compliance, and fill out the info there (It's required)</li>
</ul>
<p>Now note the application ID it gives you. You will need to add this to the application.groovy/yml file so the application will know the app ID and accept it.</p>
<p>Copy the application ID on the first tab 'SKILL INFORMATION', and paste that into application.groovy</p>
<pre><code>alexaSkills.supportedApplicationIds=&quot;amzn1.echo-api.request.8bd8f02f-5b71-4404-a121-1b0385e56123,amzn1.echo-sdk-ams.app.84d004e5-e084-4087-a8c3-a80b12fd2009,amzn1.echo-sdk-ams.app.dc1dea0e-ab91-446d-a1c7-460df5e83489&quot;
    alexaSkills.disableVerificationCheck = true // helpful for debugging or replay a command via curl
    alexaSkills.serializeRequests = true // this logs the requests to disk to help you debug
    alexaSkills.serializeRequestsOutputPath = &quot;/tmp/&quot;
</code></pre>
<p>Build and deploy your war file to your server (btw, it must be port 443 HTTPS, no exceptions).</p>
<h2>Test Your App</h2>
<p>Now try it on your Echo/Alexa device. Say either 'start' or 'open' and the invocation name you gave the app and follow the prompts! You can also use the test function on the portal itself.</p>
<h2>Debugging</h2>
<p>Debugging can be very frustrating. Make sure to turn your log level to debug. In the Grails config, there is an option called 'serializeRequests' and a output path for them. This allows you to capture the request that came from Amazon. If you are trying to test a fix for a bug, you can replay this via CURL. The files will look like this:</p>
<pre><code>    -rw-r--r-- 1 tomcat tomcat      598 Jun  6 22:45 speechlet-1465249551692.out
    -rw-r--r-- 1 tomcat tomcat      636 Jun  6 22:45 speechlet-1465249557538.out
    -rw-r--r-- 1 tomcat tomcat      598 Jun  6 22:46 speechlet-1465249601675.out
    -rw-r--r-- 1 tomcat tomcat      636 Jun  6 22:46 speechlet-1465249607216.out
</code></pre>
<p>The built-in security provided by the plugin and underlying library will now allow you to reuse a request because the hashed timestamps are too old (to prevent this type of attack called a 'replay attack'). You can disable this check for dev purposes with the 'disableVerificationCheck' Grails config value. Now you can replay a file via CURL back to your server to avoid the whole voice interaction to test that one case (and test it locally!):</p>
<pre><code>    curl -vX POST http://localhost:8080/test/index -d @speechlet-14641464378122470.out --header &quot;Content-Type: application/json&quot;
</code></pre>
<p>If you save enough requests of a normal interaction, you could write some functional tests that replay this as part of a test suite or just be able to dev against them locally a bit.</p>
<h2>Advanced Stuff: Full UI with Spring Security, OAuth</h2>
<p>If you want a UI for the user and use account linking, an easy path is to add Spring Security, Spring Security UI, Spring Security OAuth Grails plugins. You can see an example of how to do this <a href="https://github.com/rvanderwerf/twitterAuth">here</a>.</p>
<h2>Advanced Stuff: Say Sample Audio Clips in Your Skill</h2>
<p>There is a supported markup called SSML which allows up to 90 seconds of low quality mp3 sound clips to play. Their settings/requirements are quick picky to work:</p>
<ul>
<li>Must be hosted on a recognized CA HTTPS port 443 server (I use S3 static website for this)</li>
<li>Must be 16khz, 48 kb/s MP3 files</li>
<li>Use the open source tool 'ffmpeg' to encode them - these settings work: 'ffmpeg -y -i -ar 16000 -ab 48k -codec:a libmp3lame -ac 1 file.mp3'</li>
<li>See the <a href="https://github.com/rvanderwerf/heroQuiz">heroQuiz</a> app for an example of playback sounds being used.</li>
</ul>
<p>Example SSML</p>
<pre><code>        &lt;speak&gt;
          &lt;audio src=&quot;\&quot;https://s3.amazonaws.com/vanderfox-sounds/groovybaby1.mp3\&quot;/&quot;&gt; ${speechText}
          &lt;/audio&gt;
        &lt;/speak&gt;
</code></pre>
<h2>Useful links</h2>
<ul>
<li>Emulator: <a href="https://echosim.io/">https://echosim.io</a></li>
<li>Account Linking: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/linking-an-alexa-user-with-a-user-in-your-system</a></li>
<li>Getting Started Guide: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/getting-started-guide</a></li>
<li>Custom Skill Overview: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/overviews/understanding-custom-skills">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/overviews/understanding-custom-skills</a></li>
<li>Defining the Voice Interface: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/defining-the-voice-interface</a></li>
<li>Voice Design Handbook: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-voice-design-handbook">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-voice-design-handbook</a></li>
<li>Custom Skill JSON reference: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/alexa-skills-kit-interface-reference</a></li>
<li>SSML Reference: <a href="https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference">https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/speech-synthesis-markup-language-ssml-reference</a></li>
</ul>
<h2>Conclusion</h2>
<p>The Alexa service is a great invention that is catching on. Google and Apple are dipping their toes into the market. I see the Star Trek experience in the home being a reality for everyone in a few years. Already my wife uses it (who swore she never would), and my 4 year old asks it to tell her jokes all the time. I use it to control my lights very often. The sky is the limit, and these tools can be useful in the workplace too. Get out there and build some neat stuff for Alexa with the Grails framework!</p>]]></description><author>Ryan Vanderwerf</author><guid>2016-06-26</guid><pubDate>Sun, 26 Jun 2016 00:00:00 GMT</pubDate></item><item><title>GR8Conf EU 2016 Wrap-up!</title><link>https://grails.apache.org/blog/2016-06-07.html</link><description><![CDATA[</p>
<p><img src="2016-06-07-img01.jpg" alt="The OCI Team at GR8Conf EU 2016" /></p>
<p>Well I've just started to clear my jet-lagged head getting back from <a href="https://gr8conf.eu/">GR8Conf EU</a> in Copenhagen, where <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) was a platinum sponsor this year. Lots of good stuff came out of the show, things announced, good workshops. This also was the first year there were 3 concurrent tracks for the EU edition. This worked out quite well and gave a good variety for everyone. There was also a university day with 3 hour workshops packed in all day long.</p>
<p><img src="2016-06-07-img02.jpg" alt="CPH View" /></p>
<h2>Day 1: Workshops</h2>
<p>I started the day doing my Groovy Lego Mindstorms EV3 talk where we worked with putting Groovy apps on the robots, then used the Grails<sup>®</sup> framework to control the robots like mars rovers.</p>
<p><img src="2016-06-07-img03.jpg" alt="Lego" /></p>
<p>Jeff Brown then did 2(!) back to back workshops on 'Getting Started with Grails 3' and 'Rest with Grails 3'. Andres Almiray did a Gradle workshop, Jacob Mikkelsen (Of Grails Diary fame) did a Groovy and Spock for beginners. Wrapping up was our own Alvaro Sanchez-Mariscal with a workshop on <a href="https://alvarosanchez.github.io/grails-angularjs-springsecurity-workshop/" title="Building Apps with Grails">building apps with the Grails framework, AngularJS, and Spring Security</a>. I thought the workshops were very well attended this year, I could have used a couple more robots in mine, and I poked my head into full rooms on the other ones.</p>
<h3>Hackergarten on Tour</h3>
<p>Andres Almiray led the Hackergarten this year again. His energy is very good and high which helps get people motivated for some open source contributions. Lots was done, I think several Spock issues merged, progress on Elastic Search 2 plugin for Grails 3, fixes for lazybones templates on Android Wear. One thing that will be good for the Grails framework is that there was lots of progress on a converter for the old gdoc format to ascii doctor <a href="https://t.co/NA41R1DUjM">here</a>! Also a new Gradle Groovydoc plugin that forks the jvm <a href="https://t.co/EsFOyuVx7n">here</a>.</p>
<h2>Day 2: Talks</h2>
<p>Kenneth Kousen kicked off the conference with a great keynote that talked about all the value Groovy has and talked about the decisions by Gradle to make Kotlin first class and Groovy second going forward. Lots of good points about what everyone can do to make Groovy better and what makes the community great - and a big one is that maintainers are needed for the Grails framework and Groovy support for Eclipse. Will someone step up? It is hard to say because almost everyone at the show used IntelliJ IDEA, so it's tough to be motivated to work on another IDE for the folks in larger companies who only have access to Community edition of IJ or Eclipse. Some asked will IntelliJ Community add support for the Grails framework? We don't know but that'd be nice for a free option for Grails folks.</p>
<p>Here we start the 3 parallel tracks, with one being 'A Groovy journey in open source land' by Guillaume Laforge where we get a state of the union on Groovy. Following the Groovy track Jochen Theodorou talking about the new joint compiler which is very early. As an aside Jochen has started at Canoo (yay!), and unfortunately will have less time for Groovy now :( On a good note Cédric Champeau prepped a new release of Groovy 2.4.7 which is awaiting Apache approval for release.</p>
<p>After lunch we fire up again with our very own Jeff Scott Brown talking about monitoring and metrics in Grails 3 with a dropwizard plugin, Noam on clean Groovy, and a panel on the future of Groovy. I went to the panel which was led by Cedric, Jochen, and Jennifer. It was a frank upbeat discussion starting out with ribbing Gradle on Kotlin of course, then talking about what can be done to help drive Groovy adoption forward. Again the Eclipse support bubbled to the top again. Average Joe it seems misses the support in Eclipse and is lost without it.</p>
<p>I've heard following up that Marcin's talk on 'nooks and crannies of Spock' was quite good - lots to learn there. I didn't get a chance to attend the others but I peeked in the fame talk and looked interesting (does it archive?).</p>
<p>After that I sat in on the 'Ask the Grails Experts' panel with myself, Jeff, Alvaro, and Graeme. Lots of questions came up about Grails 4(????) including will the upgrade be hard like 2.5 to 3.0. We're try our best but I don't think anyone knows what Grails 4 will look like yet :) Always lots of good questions answered about direction and features to keep everyone in the know, and a question on upgrading grails 2 -&gt; 3 apps.</p>
<p>Next slot was some Android and Gradle (Ken), Groovy gateway drug(Jacob), and Migration to Grails 3 by Michael Ploed which I heard was quite good and helpful.</p>
<p><img src="2016-06-07-img04.jpg" alt="Gr8 Beer!" /></p>
<p>Wrapping up the talks was Mario David on Dockerizing your Grails app, Groovy Parallel, and Scraping the web with Geb.</p>
<p>Finishing the day, finally we get some of that Gr8 beer. They had 4 varieties this year, with the 4th one being a new Gradle IPA. Ironically a bitter beer for well um... (hrm did they know something that many months ago we didn't?) the world is weird like that.</p>
<p>Noam Tenne and Baruch Sadogursky did an really fantastic job with the Groovy Puzzlers. Lots of shirts were handed out for some good puzzlers. I think I knew more of them than I ever have before, so either I am getting better at this stuff or they are getting easier :)</p>
<h2>Day 3: Talks</h2>
<p>We roll into day 3 running with talks about Grails 3 Plugins by our own Alvaro Sanchez-Mariscal, Jennifer Strater's CodeNarc revisited, and Sacha Klein's UI intro. Grame Rocher goes deeper into the new GORM 5 features and inner workings. Iván López from Greach talks about full stack development, and Danny Hyun gives an excellent Ratpack talk (and as of today Dan Wood's book is in print!).</p>
<p>Graeme Rocher gives us a mid morning keynote before he has to jump on a plane, he showed us some new features of 3.2, RX-Gorm, and more.</p>
<p>At this point I have to give my Alexa talk <a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-dot-eu-2016">slides here</a> which went pretty well. I also (re)membered Alexa doesn't understand 'Grails' well since it's not a real word which the crowd got a good chuckle at some random tweets it started reading :) I missed but heard Cedric's and Puneet's talks were very good.</p>
<p>Next I attended Sergio del Amo's talk on building a conference app (for Greach) with Groovy, Android, and of all things Wordpress ;) very clever combination of things that seem to work well together. I missed Jennifer's talk on TDD for API Docs and Sacha Klein's talk on Groovy and Jenkins (which is something people either don't realize or forget about how much Jenkins uses Groovy!).</p>
<p>Wrapping up the conference is Jeff Scott Brown's 'Testing in Grails 3', Kenneth Kousen's &quot;Groovy Tips and Tricks&quot;, and Noam Tenne's talk about Dockerizing your Ratpack app.</p>
<p>Some of the speakers got together for dinner after that at a Mexican place (I'm from Texas and was a bit puzzled this existed in Denmark heh) which is quite good! The next day some of the speakers still left in town did a Segway tour around the city. It looks geeky as heck, but it was pretty fun.</p>
<p><img src="2016-06-07-img05.jpg" alt="Nerd Bike" /></p>
<p>Special thanks to all the sponsors and Gr8Crew (especially Søren, Jacob, Niels, Brian and crew) that make the conference possible! It is a lot of work they do for many many months before the conference each year. This is the 3rd one I have spoken at and attended and the best yet. I'm sure 2017 will be even better. If you haven't been I recommend it. If it's far, take a tech-cation (As Burt Beckwith likes to call it) and see the beautiful city and learn something too. Maybe you can find a way to write it off your taxes for business, who knows :)</p>
<p>Also here is a Groovy podcast recorded at Gr8Conf.eu: <a href="https://www.youtube.com/watch?v=Sj9P6_jT9R8">Groovy Podcast Episode 28</a></p>
<hr />
<h2>Slide Decks From the Conference</h2>
<p>(cobbled together and ripped from tweets, Grails Diary, and Groovy Calamari)</p>
<ul>
<li><a href="https://speakerdeck.com/rvanderwerf/alexa-tell-me-im-groovy-gr8conf-dot-eu-2016">Alexa, Tell Me I'm Groovy!</a> (Ryan Vanderwerf)</li>
<li><a href="https://speakerdeck.com/szpak/interesting-nooks-and-crannies-of-spock-you-may-have-never-seen-before">Interesting nooks and crannies of Spock you (may) have never seen before</a> (Marcin Zaj?czkowski)</li>
<li><a href="https://www.slideshare.net/alvarosanchezmariscal/creating-applications-with-grails-angular-js-and-spring-security-62646073">Creating applications with Grails, Angular JS and Spring Security</a> (Alvaro Sanchez-Mariscal)</li>
<li><a href="https://speakerdeck.com/glaforge/a-groovy-journey-in-open-source-land">A Groovy journey in Open Source land</a> (Guillaume Laforge)</li>
<li><a href="https://melix.github.io/gr8conf2016-intro-software-model/#/">Introduction to the Java software model</a> (Cédric Champeau)</li>
<li><a href="https://melix.github.io/gr8conf2016-variant-aware-dep-mgmt/#/">Variant aware dependency management with Gradle</a> (Cédric Champeau)</li>
<li><a href="https://speakerdeck.com/sdelamo/scraping-with-geb">Scraping with Geb</a> (Sergio del Amo)</li>
<li><a href="https://t.co/2GsyZuq2h8">How to create a conference android app with Groovy and Android?</a> (Sergio del Amo)</li>
<li><a href="https://speakerdeck.com/jlstrater/codenarc-revisited-gr8conf-eu-2016">Codenarc Revisited</a> (Jenn Strater)</li>
<li><a href="https://danhyun.github.io/2016-gr8confeu-rapid-ratpack-groovy/#implementing_individual_todo_chain">Rapid Ratpack Groovy Web App Development</a> (Danny Hyun)</li>
<li><a href="https://www.slideshare.net/alvarosanchezmariscal/mastering-grails-3-plugins-gr8conf-eu-2016">Mastering Grails 3 Plugins</a> (Alvaro Sanchez-Mariscal)</li>
<li><a href="https://www.slideshare.net/ilopmar/gr8conf-2016-mum-i-want-to-be-a-groovy-fullstack-developer">Mum, I want to be a Groovy full-stack developer</a> (Iván López)</li>
<li><a href="https://de.slideshare.net/sascha_klein/introduction-to-graphics-and-uidesign">Introduction to Graphics- and UI-Design</a> (Alexander (Sascha) Klein)</li>
<li><a href="https://melix.github.io/gr8conf2016-deepdive-groovy-compiler/#/">Deep dive into the Groovy compiler</a> (Cédric Champeau)</li>
<li><a href="https://speakerdeck.com/mariodavid/dockerize-your-grails-app-for-more-deployment-fun-gr8conf-eu-2016">Dockerize your Grails App for more deployment fun</a> (Mario David)</li>
<li><a href="https://speakerdeck.com/behl/giving-back-to-the-grails-community-migrating-plugins-from-grails-2-to-grails-3">Giving back to the Grails Community - Migrating plugins from Grails 2 to Grails 3</a> (Puneet Behl)</li>
<li><a href="https://speakerdeck.com/mariodavid/is-grails-the-right-approach-for-business-apps-gr8conf-eu-2016">Is Grails the right approach for business apps?</a> (Mario David)</li>
<li><a href="https://www.slideshare.net/gr8conf/groovy-powered-clean-code">Groovy Powered Clean Code</a> (Noam Tenne)</li>
<li><a href="https://de.slideshare.net/sascha_klein/using-groovy-with-jenkins">Using Groovy with Jenkins</a> (Alexander (Sascha) Klein)</li>
<li><a href="https://www.slideshare.net/gr8conf/ratpack-on-the-docks">Ratpack On the Docks</a> (Noam Tenne)</li>
<li><a href="https://speakerdeck.com/jlstrater/a-test-driven-approach-to-documenting-restful-apis-with-spring-rest-docs-gr8conf-eu-2016">Test Driven Approach to Documenting REST APIs w/ Spring REST Docs</a> (Jenn Strater)</li>
<li><a href="https://www.innoq.com/de/talks/2016/06/hands-on-migration-grails-2-to-3/">Hands On Migration from Grails 2 to 3</a> (Michael Plöd)</li>
<li><a href="https://www.innoq.com/de/talks/2016/06/reactive-applications-with-grails3/">Building reactive applications with the Grails 3 event system</a> (<a href="https://github.com/mploed/grails-event-example">code</a>) (Michael Plöd)</li>
<li><a href="https://www.slideshare.net/ilopmar/gr8conf-2016-metaprogramming-with-groovy">Metaprogramming with Groovy</a> (Iván López)</li>
<li><a href="https://www.slideshare.net/graemerocher/gr8conf-2016-whats-new-in-grails-3">Grails Keynote / What's New In Grails 3</a> (Graeme Rocher)</li>
<li><a href="https://www.slideshare.net/graemerocher/gr8conf-2016-gorm-inside-and-out">GORM Inside and Out</a> (Graeme Rocher)</li>
<li><a href="https://www.slideshare.net/aalmiray/gradle-glam-plugis-strike-back">Gradle Glam - Plugins Strike Back</a> (Andres Almiray)</li>
</ul>
<p>I look forward to the next edition!</p>
<p>— Ryan Vanderwerf and the rest of the OCI/Grails Team</p>]]></description><author>Ryan Vanderwerf</author><guid>2016-06-07</guid><pubDate>Tue, 07 Jun 2016 00:00:00 GMT</pubDate></item><item><title>Monitoring and Metrics with Grails® 3</title><link>https://grails.apache.org/blog/2016-06-02.html</link><description><![CDATA[</p>
<p>tags: <a href="https://grails.apache.org/blog/tag/monitoring.html"><span class="hashtag">#monitoring</span></a> <a href="https://grails.apache.org/blog/tag/video.html"><span class="hashtag">#video</span></a></p>
<p>Jeff Scott Brown, co-founder of the Grails<sup>®</sup> framework, discusses monitoring and metrics with Grails 3 at GR8Conf EU 2016.</p>
<p>In this presentation, Jeff demonstrates capabilities that are currently in development with the intention of soliciting feedback from the Grails community. He also introduces features of Grails 3 and Groovy.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/wVpEsbzMj90" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown</author><guid>2016-06-02</guid><pubDate>Thu, 02 Jun 2016 00:00:00 GMT</pubDate></item><item><title>Grails® 3.2 Milestone 1 Released</title><link>https://grails.apache.org/blog/2016-05-31.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/release.html"><span class="hashtag">#release</span></a></p>
<p>Today, and just in time for <a href="https://gr8conf.eu/">GR8Conf EU</a> in Copenhagen, we are pleased to announce the <a href="https://github.com/apache/grails-core/releases/tag/v3.2.0.M1">first milestone of Grails<sup>®</sup> 3.2</a>, which includes the following new features.</p>
<h2>RxGORM</h2>
<p>Grails 3.2 milestone 1 ships with GORM 6.0 milestone 1, which includes a new implementation of GORM based on RxJava called RxGORM. With RxGORM you can build non-blocking, reactive applications using a familiar GORM API including features such as Where Queries, Dynamic Finders and Criteria Queries.</p>
<p>With the initial release, support for MongoDB is included, but more implementations are planned for SQL, REST client, and other implementations. See the <a href="https://gorm.grails.org/latest/rx/manual/index.html">RxGORM Documentation</a> for more information.</p>
<h2>Angular Scaffolding</h2>
<p>Grails 3.2 features support for scaffolding of AngularJS 1.x applications (support for Angular 2 is also planned) when using the <code>angular</code> profile, allowing your team to quickly get up and running integrating Angular frontends with Grails 3 backends.</p>
<h2>Improvements to JSON Views</h2>
<p>JSON views, a feature introduced in Grails 3.1, have been drastically improved with support for template inheritance, global templates, extended HAL support and more.</p>
<p>See the <a href="https://views.grails.org/1.1.0.M2/#_version_history">documentation for the 1.1 milestone 2 version</a> of the JSON views plugin for more information.</p>
<h2>What's Still Coming?</h2>
<p>Grails 3.2 is at the milestone phase and is not feature complete, still in the pipeline are the following new features:</p>
<ul>
<li>Native GORM Multi Tenancy Support</li>
<li>RxGORM REST Client</li>
<li>GORM for Neo4j 3.0 / Bolt Driver Support</li>
<li>RxJava Controller Support</li>
<li>Further AngularJS and REST Refinements</li>
</ul>
<p>For more information on the Milestone 1 release, check out the release notes.</p>
<p>We look forward your feedback, and if you are coming to <a href="https://gr8conf.eu/">GR8Conf EU</a>, we look forward to talking to you more about the great new features coming in the Grails framework.</p>]]></description><author>Graeme Rocher</author><guid>2016-05-31</guid><pubDate>Tue, 31 May 2016 00:00:00 GMT</pubDate></item><item><title>Using React with the Grails® framework</title><link>https://grails.apache.org/blog/2016-05-28.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/react.html"><span class="hashtag">#react</span></a> <a href="https://grails.apache.org/blog/tag/javascript.html"><span class="hashtag">#javascript</span></a> <a href="https://grails.apache.org/blog/tag/gradle.html"><span class="hashtag">#gradle</span></a></p>
<p><strong>React</strong>, the JavaScript library from Facebook, has become a popular view technology for building dynamic, testable and performant user interfaces. While not a full-fledged framework like Angular or Ember, React’s focus on functional component-based views with no (or minimal) internal state makes it a great choice when building single page applications (SPA) or even dynamic subcomponents within a page-based application.</p>
<p>Because it doesn't make assumptions about data-flow or controller logic outside of rendering the view, React relies on the developer to either provide these features directly in JavaScript or use another framework as a backend to support the React-based UI.</p>
<p>It is this flexibility, in part, that makes React an appealing choice as a modern JavaScript view layer for <strong>Grails</strong><sup>®</sup> applications. Grails provides a robust backend built upon Spring Boot, GORM, and the Groovy programming language, as well as excellent support for generating restful endpoints that can be consumed by our React application. Since Grails 3 is also based upon Gradle, we can leverage <a href="https://github.com/srs/gradle-node-plugin">Gradle’s Node plugin</a> to unify our build and testing pipeline for both Grails and React, without needing to complicate our deployment processes.</p>
<p>Finally, <strong>JSX</strong> (React's XML-like syntax for defining components and page markup) is a powerful and flexible way to create dynamic views. In the author's opinion, creating components in JSX is quite analogous to defining custom GSP tags in a Grails taglib: a function which receives state via props (GSP <code>attrs</code>) and typically (but not always) renders markup based on that state. In React's case, these components are re-rendered upon every change to the app's state, rather than being limited to page-load. This stateless component model should be understandable to Grails developers who have written <a href="https://objectcomputing.com/resources/publications/sett/december-2015-custom-gsp-tags-grails-best-kept-secret/">custom GSP tags</a>, and JSX takes this to the next level.</p>
<p>In this article, we'll demonstrate how to integrate React into a Grails 3 application, using some of Grail’s restful features to get up and running quickly. We’ll spend a bit of time getting our project set up, and get to know some of the players in a React codebase.</p>
<p>There are plenty of resources available to teach you React and restful API design, so I’m going to focus primarily on the “missing pieces” of combining React with a Grails application[1]. At the completion of this article, we'll list some resources to further your understanding of React. You'll be able to take this foundation and follow along with the same documentation, tutorials and other resources available to React developers.</p>
<h2>Building Our Foundation</h2>
<p>Let’s start with a brand new Grails 3.1.6 application, using the default web profile:</p>
<pre><code>    grails create-app com.ociweb.TodoList
</code></pre>
<p>Having run the <code>create-app</code> command, we already have a fully functioning backend application and server ready to go, and we can start up our app using the run-app command. View your new Grails application at <a href="http://localhost:8080/">http://localhost:8080</a>.</p>
<p>Let’s create our data model.</p>
<pre><code>    grails create-domain-class com.ociweb.Todo
    grails create-domain-class com.ociweb.TodoList
</code></pre>
<pre><code class="language-groovy">//grails-app/domain/com/ociweb/Todo.groovy
    package com.ociweb

    class Todo {

        String name

        static belongsTo = [todoList: TodoList]
    }
</code></pre>
<pre><code class="language-groovy">//grails-app/domain/com/ociweb/TodoList.groovy
    package com.ociweb

    class TodoList {

        String name

        static hasMany = [ todos: Todo ]

        static constraints = {
            todos nullable: true
        }
    }
</code></pre>
<p>Now we have our domain model ready to go. By default Grails will provide us with an H2 database (in memory for development and test environments, as a file in production).</p>
<p>Of course Grails supports all the major databases, including MySQL, Postgres, Oracle, and even NoSQL data stores like <strong>Mongo</strong>. Thanks to the flexibility of GORM, changing datasources is as simple as adding a couple dependencies or lines of configuration.</p>
<p>Let’s switch to Mongo for this demonstration (this step is optional).</p>
<p>Specify the mongo plugin in your <code>build.gradle</code> file:</p>
<pre><code class="language-groovy">//build.gradle

    buildscript {
        //…
        dependencies {
            //…
            classpath &quot;org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT&quot;

    dependencies {
    		//…
        compile &quot;org.grails.plugins:mongodb:5.0.0.BUILD-SNAPSHOT&quot;
        compile &quot;org.grails.plugins:hibernate4:5.0.0.BUILD-SNAPSHOT&quot;
</code></pre>
<p>Now in our domain classes, add this static property to store the domain object in mongo:</p>
<pre><code class="language-groovy">    //grail-app/domain/com/ociweb/Todo.groovy &amp; TodoList.groovy

//...
    static mapWith=&quot;mongo&quot;
</code></pre>
<p>The plugin assumes you have mongodb installed and that mongod is running at port 27017; you can configure these to match your environment (<a href="https://gorm.grails.org/latest/mongodb/manual/index.html">see the plugin documentation for details</a>).</p>
<h2>Defining Our API</h2>
<p>Finally, we need to define a restful API for our React application.</p>
<p>API design is a broad subject and not in scope of this article. However, Grails gives us a jumpstart to getting our API off the ground, providing endpoints for standard CRUD operations with minimal configuration. This is done by declaring our domain classes as resources, either by marking with the <code>@Resource</code> annotation or specifying the resource class within our URLMappings.</p>
<p>Let's use the <code>@Resource</code> annotation for this example.</p>
<pre><code class="language-groovy">//grails-app/domain/com/ociweb/Todo.groovy
    import grails.rest.Resource

    @Resource(uri='/api/todos', formats=['json'])
    class Todo {
      //...
</code></pre>
<pre><code class="language-groovy">//grails-app/domain/com/ociweb/TodoList.groovy

    @Resource(uri='/api/todoList', formats=['json'])
    class TodoList {
      //...
</code></pre>
<p>Note that we specify the content-type we wish to expose - we’ll use JSON.</p>
<p>Finally, let’s add some initial data in <code>Bootstrap.groovy</code>:</p>
<pre><code class="language-groovy">//grails-app/init/BootStrap.groovy

    import com.ociweb.*

    class BootStrap {

        def init = { servletContext -&gt;

            if(!Todo.list()) {
                log.info &quot;Creating todos...&quot;
                def todoList = new TodoList(name: &quot;Bob's List&quot;).save()

                [[name: &quot;Task 1&quot;, todoList: todoList],
                 [name: &quot;Task 2&quot;, todoList: todoList],
                 [name: &quot;Task 3&quot;, todoList: todoList]].each { props -&gt;
                    def todo = new Todo()
                    todo.properties = props
                    todo.save(flush: true)
                }

            }
        }
        def destroy = {
        }
    }
</code></pre>
<p>Restart the application to load the new data.</p>
<p>Now using a rest client application or a command-line utility like cURL, we can test drive our new API.</p>
<pre><code>    ~ curl -i -H &quot;Accept: application/json&quot; localhost:8080/api/todos

    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    X-Application-Context: application:development
    Content-Type: application/json;charset=UTF-8
    Transfer-Encoding: chunked
    Date: Sun, 15 May 2016 06:03:56 GMT

    [{&quot;id&quot;:1,&quot;list&quot;:{&quot;id&quot;:1},&quot;name&quot;:&quot;Task 1&quot;},{&quot;id&quot;:2,&quot;list&quot;:{&quot;id&quot;:1},&quot;name&quot;:&quot;Task 2&quot;},
    {&quot;id&quot;:3,&quot;list&quot;:{&quot;id&quot;:1},&quot;name&quot;:&quot;Task 3&quot;}]
</code></pre>
<pre><code>    ~ curl -i -H &quot;Accept: application/json&quot; localhost:8080/api/todoList/1

    HTTP/1.1 200 OK
    Server: Apache-Coyote/1.1
    X-Application-Context: application:development
    Content-Type: application/json;charset=UTF-8
    Transfer-Encoding: chunked
    Date: Sun, 15 May 2016 06:06:00 GMT

    {&quot;id&quot;:1,&quot;name&quot;:&quot;Bob's List&quot;,&quot;todos&quot;:[{&quot;id&quot;:3},{&quot;id&quot;:1},{&quot;id&quot;:2}]
    }
</code></pre>
<p>There you go, we have a fully functioning restful API, backed by Mongo, and my coffee isn’t even cold yet.</p>
<p>Now that we have our backend largely ready to go, we’re ready to set up React.</p>
<blockquote>
<p>Question: Why Do This?</p>
<p>Why not use separate backend and front-end apps? In a microservice architecture, the work we’ve done might be sufficient - we could now build a separate React/node-based front-end application independent of our Grails backend. This is a great strategy, and <a href="https://grails.apache.org/docs/latest/guide/profiles.html#creatingProfiles">Grails 3.1 ships with a profile</a> tailored to this use case (web-api). Another option is to take advantage of Gradle multi-project builds, with separate projects for the backend and front-end. Both of these options require another server to run the React app.</p>
<p>In this article, however, we’re considering the use of React as the “view” (the V in MVC) in a standard Grails application. And although we’re sharing a project directory, the React code and Grails artifacts are independent, and will communicate at runtime via our restful API just as if they were separate apps. The only thing tying these two apps together is the same Gradle build, which gives us the benefits described earlier in the article (in fact, it would be quite easy to split out the React app in future by simply moving the <code>src/main/js</code> and <code>src/test/js</code> directories into their own project, and configuring up a new server).</p>
<p>There’s many situations where a team may want to bring React into a Grails application, and it can be done in a way that allows for full developer productivity for both Grails and Node/React developers. Read on to see how!</p>
</blockquote>
<h2>Upgrading Our Build</h2>
<p>React is most commonly used in combination with <a href="https://nodejs.org/">node.js</a>, and even if you aren’t intending to use node in particular, it still makes sense to have it installed if you intend to do any serious work with a Javascript library like React.</p>
<p>The reason? You will use <code>npm</code> (which most surely <a href="https://www.quora.com/I-keep-hearing-NPM-doesnt-stand-for-Node-Package-Manager-what-does-it-stand-for">does <em>not</em> stand for Node Package Manager</a>) to download and install React and any other libraries you choose to use alongside it. <code>npm</code> can also be used to run scripts to build and test your React code, and it is the “handle” that will allow us to integrate our React code with our Gradle-based deployment.</p>
<p>Once we have our React application set up, it will <em>not</em> be necessary for all developers to run node on their machines – we’ll take care of making that happen seamlessly as part of the Gradle build. However, any developer who is set up with node will be able to use <code>npm</code> and other node tools just as if they were working within a “plain” node application. This gives us the best of both worlds: Backend Grails developers can do their work without relying upon node and <code>npm</code>, while frontend developers can use node and their preferred development tools. The only requirement for all team members will be a Gradle installation to run the Grails project.</p>
<p>In addition to installing node in your development environment, we will need to install the <a href="https://github.com/srs/gradle-node-plugin">gradle-node plugin</a> in our Grails application. This plugin will be the key to managing our <code>npm</code> tasks without relying upon local installations of node. Install the plugin by adding the plugin in <code>build.gradle</code>:</p>
<pre><code class="language-groovy">    //build.gradle

    plugins {
        id &quot;com.moowork.node&quot; version &quot;0.12&quot;
    }

    node {
        version = '5.10.1'
        npmVersion = '3.8.3'
        distBaseUrl = 'https://nodejs.org/dist'
        download = true
    }
</code></pre>
<h2>Setting Up Our React Environment</h2>
<p>For the next few steps, we'll use a local installation of <code>npm</code>. If you don't have it installed yet, I <em>highly</em> recommend <a href="https://github.com/creationix/nvm">nvm</a> to simplify installation and managing of node versions (if you've used <code>gvm</code>/<code>sdkman</code> for managing Grails/Groovy/Gradle versions, you'll like <code>nvm</code>). We'll be using the latest version of node 5.x as of the time of writing, which is 5.10.1. Please refer to <a href="https://github.com/ZacharyKlein/sett-todolist/blob/master/README.md">the Readme in the Github repository</a> for the versions of all node packages that are used. For a simple example like this, newer versions of any of the packages shouldn't cause a problem.</p>
<p>Assuming you've installed <code>npm</code>, let's initialize our project. Run this command from your Grails project directory - you can accept the defaults for now; it's easy to fill in the details later):</p>
<pre><code>    npm init
</code></pre>
<p>Now we’re ready to install React and other dependencies.</p>
<pre><code>    npm install react react-dom --save

    npm install babel-core babel-preset-es2015 babel-preset-react babel-loader webpack --save-dev
</code></pre>
<p>There are plenty of options when setting up a React application, but these are the basics.</p>
<p>Of course we need React and ReactDOM to render our app in the browser (React can also be used natively on mobile platforms like iOS, using <a href="https://facebook.github.io/react-native/">ReactNative</a> instead of ReactDOM).</p>
<p>In addition, because we’ll be using JSX to write our components, we’ll need to use a <strong>transpiler</strong> to convert our React code into “plain vanilla” Javascript. Modern Javascript frameworks are moving much faster than web browsers, and many of the Javascript APIs commonly used in React projects are not yet standard in browsers.</p>
<p><a href="https://babeljs.io/">babel</a> is a popular transpiler with many “presets” supporting different versions of Javascript syntax.</p>
<p>To enable these presets, create a <code>.babelrc</code> file in the project root directory with this content:</p>
<pre><code class="language-javascript">    {
      &quot;presets&quot;: [
        &quot;react&quot;,
        &quot;es2015&quot;
      ]
    }
</code></pre>
<p>This will ensure that babel uses the presets we’ve installed when transpiling our code.</p>
<p>Of course, if we’re going to run our code through a transpiler, that means we need a build step to do the work. Typically in Grails applications, the asset pipeline plugin is the tool of choice for processing static assets like Javascript files. While there is a <a href="https://github.com/errbuddy/babel-asset-pipeline">Babel plugin</a> for the Grails asset pipeline, we are going to take a different approach and use **webpack **for this purpose; this will give us more flexibility in processing our React code and is in keeping with typical React projects.</p>
<h2>Webpack</h2>
<p><a href="https://webpack.github.io" title="Webpack on GitHub">Webpack</a> represents a family of tools called “bundlers” and is a very popular choice for building React applications. It’s also a powerful and complex tool, but we can get started with a fairly minimal configuration.</p>
<p>Here’s the big picture: Webpack will be responsible for running our React code through “loaders” for processing, and then output the finished product as a “bundle”. There are <a href="https://webpack.js.org/loaders/">loaders for nearly every conceivable asset type</a> you may want to access in your React application, including LESS, SASS, markdown, images, urls, generic files, and even Java properties files (such as <code>i18n/messages.properties</code> files). In our case, the babel-loader all we need to configure right now. We will configure webpack to drop this bundle into the <code>grails-app/assets/javascripts</code> directory in our Grails application, so it can be served just like another Javascript file.</p>
<p>Here's our <code>webpack.config.js</code> file:</p>
<pre><code class="language-javascript">    var path = require('path');

    module.exports = {
        entry: {
            index: './src/main/js/index.js'
        },
        output: {
            path: './grails-app/assets/javascripts',
            publicPath: '/assets/',
            filename: 'bundle.js'
        },
        module: {
            loaders: [
                {
                    test: /\.js$/,
                    include: path.join(__dirname, 'src/main/js'),
                    loader: 'babel',
                    query: {
                        presets: ['es2015', 'react']
                    }
                }
            ]
        }
    };
</code></pre>
<p>Don't be intimidated by this configuration; it’s actually fairly simple. The syntax is plain Javascript, which can be a bit confusing for a Grails developer accustomed to a DSL for config. The key points are that we’re defining where to find our React source files (<code>src/main/js/index.js</code>), where to output them (<code>grails-app/assets/javascripts</code>), and how to process them via the babel loader. You can learn more about configuring webpack <a href="https://webpack.js.org/concepts/">from the documentation</a>, but this should get you started.</p>
<blockquote>
<p>Where Is <code>/src/main/js</code>?</p>
<p>Typically in a Grails application, Javascript files, like other static assets, live in the <code>grails-app/assets/</code> directory, which is where the asset pipeline picks them up. However, it is far more typical in a React application to keep the source files separate from the distributed bundle within a <code>src</code> directory, which makes sense, given that they contain “source code” for an application and are not really “assets” in the sense that Twitter Bootstrap or jQuery might be.</p>
<p>In addition, we will want to write tests for our React code, and it really doesn't make sense for tests to live in an “assets” directory structure. This is simply a matter of preference; in this article, we will store our React source code under <code>src/main/js</code> (in keeping with Grails' conventional <code>src/main/java</code> and <code>src/main/groovy</code> source structure), and our tests under <code>src/test/js</code>. These directories won’t exist by default, so we’ll need to create them ourselves.</p>
</blockquote>
<p>We will also want to add a couple of “scripts” to our <code>package.json</code> file in order to run webpack via <code>npm</code> (and later automate these with Gradle). In the <code>scripts</code> section, add these two lines:</p>
<pre><code class="language-javascript">      &quot;scripts&quot;: {
        &quot;watch&quot;: &quot;webpack --watch --colors --progress&quot;,
        &quot;bundle&quot;: &quot;webpack&quot;,
</code></pre>
<p>Now we can call these scripts using <code>npm</code>. Why do we have two scripts that both run webpack? The “bundle” version runs webpack and generates the bundle once (analogous to <code>grails war</code>), while the “watch” version will run webpack in “watch” mode, where the tool will automatically regenerate the bundle every time it detects a change to the source files (similar to <code>grails run-app</code>, with reloading of changed classes). We also enable some pretty formatting to ensure developer happiness.</p>
<p>You can now run these scripts like so:</p>
<pre><code>    npm run bundle
</code></pre>
<p>However, you'll likely get an error saying &quot;Entry module could not be found.&quot;</p>
<p>Yep, we haven't added the &quot;entry&quot; file we specified earlier in our <code>src/main/js</code> directory yet. Let's do that.</p>
<p>Create <code>index.js</code> and add a simple <code>alert()</code> statement:</p>
<pre><code class="language-javascript">//src/main/js/index.js
    alert('Hello!');
</code></pre>
<p>Now if you run <code>npm run bundle</code>, you’ll get output like this:</p>
<pre><code class="language-javascript">    Hash: bc17d737c7738edc00a5
    Version: webpack 1.13.0
    Time: 727ms
        Asset     Size  Chunks             Chunk Names
    bundle.js  1.43 kB       0  [emitted]  index
        + 1 hidden modules
</code></pre>
<p>And if you check your <code>grails-app/assets/javascripts</code> directory, you should see your shiny new <code>bundle.js</code>!</p>
<p>Finally we need to load this bundle on our page. We’ll use a Grails controller and GSP view in this demonstration, but this could easily be a plain HTML page as well. Create a new controller <code>AppController</code>, and create an <code>index.gsp</code> page in the <code>grails-app/views/app</code> directory with this content:</p>
<pre><code>    grails create-controller com.ociweb.AppController
</code></pre>
<pre><code class="language-groovy">//grail-app/views/index.gsp
    &lt;!doctype html&gt;
    &lt;html&gt;
    &lt;head&gt;
        &lt;title&gt;Todo List&lt;/title&gt;
    &lt;/head&gt;
    &lt;body&gt;
        &lt;div id=&quot;app&quot;&gt;&lt;/div&gt;
        &lt;asset:javascript src=&quot;bundle.js&quot; &gt;&lt;/asset:javascript&gt;
    &lt;/body&gt;
    &lt;/html&gt;
</code></pre>
<p>(Note that if we had used a plain HTML page, we would not be able to use the tag)</p>
<p>Browse to <a href="http://localhost:8080/app"><code>http://localhost:8080/app</code></a>, and you should see your <code>alert()</code> statement.</p>
<blockquote>
<p>webpack-dev-server</p>
<p>Webpack also includes a simple server called <em>webpack-dev-server</em>, which will operate similarly to “watch” mode but is actually able to instantly reload the bundle/s on your page, so that you can see your app update when you save your source file <a href="https://gaearon.github.io/react-hot-loader/getstarted/">without refreshing the browser</a>. This is a powerful feature, but it can be tricky to set up and is outside the scope of this article. I’ve created <a href="https://github.com/ZacharyKlein/grails-react-starter">a starter application available on Github</a>[2] that demonstrates use of the webpack-dev-server within a Grails application.</p>
</blockquote>
<h2>Enter Gradle</h2>
<p>We’re almost done with our setup steps. With our current configuration, we can bundle our React code and output it to the asset pipeline, so the Grails app can serve it to our views. We also have a restful backend provided by our Grails app. Now we just need to make use of the Gradle node plugin [3] to automate the webpack bundling process when we 1. start the Grails app, and 2. package the Grails app as a WAR or JAR file.</p>
<p>Add these two lines to the end of your <code>build.gradle</code>:</p>
<pre><code class="language-groovy">//build.gradle

    processResources.dependsOn(['npmInstall', 'npm_run_bundle'])

    assetCompile.dependsOn(['npmInstall', 'npm_run_bundle'])
</code></pre>
<p>And that’s it! All we’ve done here is “hooked” a pair of <code>npm</code> tasks into our Gradle build process.</p>
<p>The first is <code>npmInstall</code>, which is the equivalent of <code>npm install</code>, and is typically the first command you’d run when setting up an existing node-based project. <code>npm install</code> will read the <code>package.json</code> file and install any missing dependencies in your development environment.</p>
<p>The second task should look familiar – it’s our <code>bundle</code> script we just used a moment ago. The Gradle node plugin supports this syntax for <em>any</em> script that you would normally run with <code>npm</code>. So any custom scripts you write in the future can be called via <code>npm_run_[your new script]</code>.</p>
<p>Of course, you can run these scripts yourself through Gradle, using the included Gradle wrapper:</p>
<pre><code>    ./gradlew npm_run_watch
</code></pre>
<p>Other than the delay from spinning up Gradle, this will have the same effect as running <code>npm run watch</code> directly. This also means that developers without node installed can run these tasks without adding anything to their build environment - Gradle will handle those details seamlessly and OS-independently.</p>
<p>When developing with React, typically you will run the Grails app <em>and</em> run webpack in “watch” mode, using <code>npm</code> or Gradle. As you make changes to your Javascript sources, webpack will automatically regenerate the <code>bundle.js</code>, and you can load the changes by refreshing your page.</p>
<p><img src="2016-05-28-img01.png" alt="" />
<em>Development Workflow with Grails &amp; Webpack (<code>grails run-app</code> in the left terminal; <code>./gradlew npm_run_watch</code> in the right)</em></p>
<p>Returning to our new <code>build.gradle</code> steps, you'll notice that we've attached these tasks to Grails' <code>processResources</code> (which runs every time the Grails app is started) and <code>assetCompile</code> (which runs when the app is packaged) tasks as dependencies. In this case, we just want to make sure the bundle is generated when the app is run, and when we build our WAR/JAR file, so that we’re always using our latest <code>bundle.js</code>. This also means you can exclude <code>bundle.js</code> from your version control if you’d prefer.</p>
<p>Now you can build your Grails application on a Continuous Integration server that knows nothing about node or React. Gradle will handle installing node (local to the project), downloading <code>npm</code> dependencies, and running scripts like our webpack bundle, all without any changes to your build and deployment process.</p>
<h2>Defining our Components</h2>
<p>As we mentioned in the introduction to this article, React provides an <a href="https://facebook.github.io/react/docs/jsx-in-depth.html">expressive XML-like syntax</a> for defining our components. Let’s take a look at a simple JSX component that will render a Todo instance.</p>
<pre><code class="language-javascript">    // /src/main/js/todo.js

    import React from 'react';

    function Todo(props) {

        const todo = props.todo;

        return(
            &lt;li&gt;
                &lt;input id={ todo.id } type=&quot;checkbox&quot;
                checked={ todo.complete ? 'checked' : '' }
                onChange={ props.toggleComplete } /&gt;
                &lt;span&gt;{ todo.name }&lt;/span&gt;
            &lt;/li&gt;
        );
    }
</code></pre>
<p>Again, this is not an in depth explanation of React and JSX, but you can learn a lot from a simple example like this one. As you can see, our component is a simple Javascript function, which takes an object (key/value pairs, similar to a Groovy map) that contains all attributes that are passed into this component.</p>
<p>To use our new component, we just need to render it to our page (note that we have implemented a <code>toggleComplete</code>function yet, so we’re skipping that property for now - our  component will still render but it won’t do anything yet):</p>
<pre><code class="language-javascript">    // /src/main/js/index.js

    import React from 'react';
    import ReactDOM from 'react-dom';
    import Todo from './todo';

    //Call to render our component into the DOM…
    ReactDOM.render(
    &lt;div&gt;

    &lt;h1&gt;Our first Todo!&lt;/h1&gt;
{% raw %}
    &lt;Todo todo={{name: 'Task 1', id: 1, complete: false}}&gt;&lt;/Todo&gt;
{% endraw %}
    &lt;/div&gt;, document.getElementById('app')); // ...into this element on the page
</code></pre>
<p>Compare this to a custom GSP tag that might render similar output server-side:</p>
<pre><code class="language-groovy">    //Hypothetical GSP taglib

    def todo = { attrs -&gt;

    	def todo = attrs.todo

    	out &lt;&lt; &quot;&quot;&quot;
      &lt;li&gt;
        &lt;input type=&quot;checkbox&quot;
    			checked=${todo.complete ? 'checked' : ''}
    			onchange=${ /* specify an Ajax function */} /&gt;
    			&lt;span&gt;${todo.name}&lt;/span&gt;
    	  &lt;/li&gt;
    		&quot;&quot;&quot;
    }

    &lt;g:todo todo=${todo} &gt;&lt;/g:todo&gt;
</code></pre>
<p>Of course this is not an entirely fair comparison. <a href="https://objectcomputing.com/resources/publications/sett/december-2015-custom-gsp-tags-grails-best-kept-secret/">GSP tags provide much more functionality</a> than simply rendering of attributes, but Grails developers should find the syntax of JSX to be quite friendly and understandable coming from GSPs.</p>
<p>JSX allows us to write Javascript expressions bound by curly braces, supports namespacing of components, and can make large, complex UIs easier to visualize while coding [4]. However, JSX is optional. You can write React components entirely in plain Javascript, but the resulting code is more verbose.</p>
<blockquote>
<p>Word of Warning</p>
<p>This article is not intended as a comprehensive introduction to React. For developers new to Javascript, there are plenty of pitfalls to be had when learning this library. Understanding function context, &quot;binding&quot; [5], and passing functional callbacks into child components are key skills when writing clean code in React. These concepts are not React-specific – they are in fact plain Javascript – but they can be confusing to Groovy and Java programmers. There are many resources for learning React, and we will list a few of them at the end of this article.</p>
</blockquote>
<h2>Calling the API</h2>
<p>Now that we have our React app integrated into our Grails project and served up via the asset pipeline, we can start to build out our application and write components that consume our restful API. Because React is a view library, it doesn’t offer specialized features for communicating with a restful API. Developers are encouraged to use native Javascript APIs or other libraries to supply this functionality. The example project from this article uses the <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">fetch API</a> [6]. The full code is available on Github, so we won’t go over it here.</p>
<p>The app allows a user to create new todo lists and add new todo items to them. All changes are saved to the mongo database. It also makes use of <a href="https://views.grails.org/latest/">JSON Views</a> to customize the JSON output from our endpoints.</p>
<p>No update or delete functions are provided at this time. Those features are left as an exercise to the reader.</p>
<p><a href="https://github.com/ZacharyKlein/sett-todolist">https://github.com/ZacharyKlein/sett-todolist</a></p>
<p><img src="2016-05-28-img02.png" alt="" /></p>
<p>Completed TodoList app</p>
<h2>Testing</h2>
<p>One of the benefits of creating a user interface in React is testability. Because React encourages the use of stateless components, testing their functionality is often as simple as providing props and making assertions against their output. Let’s look at a simple test for our  component, and then see how the Gradle node plugin can help us run our tests as part of our build.</p>
<p>There are many options for testing Javascript code. [7,8] In this example we'll use the <a href="https://mochajs.org/">mocha test framework</a>, React’s own <a href="https://facebook.github.io/react/docs/test-utils.html">testing utilities</a>, and <code>expect.js</code> to provide assertions.</p>
<p>Again, because React is focused on building our view layer, we’re mostly concerned with testing that our components output the correct content from their props. This is <em>not</em> an in-depth look at testing React components, but it will give you a place to start.</p>
<p>First, let’s install some dependencies:</p>
<pre><code>    npm install mocha expect react-addons-test-utils --save-dev
</code></pre>
<p>And add this &quot;test&quot; script to our <code>package.json</code> file:</p>
<pre><code>    ”test&quot;: &quot;mocha './src/test/js/*.spec.js' --compilers js:babel-core/register&quot;
</code></pre>
<p>Here's a simple test for our component:</p>
<pre><code class="language-javascript">    // /src/test/js/lot.spec.js

    import React from 'react';
    import TestUtils from 'react-addons-test-utils';
    import expect from 'expect';
    import Todo from '../../main/js/todo';

    describe('Todo', () =&gt; {
        it('should have expected content', () =&gt; {

            const todo = {name: 'Task 1', complete: false, id: 1, list: { id: 1 }};

            const renderer = TestUtils.createRenderer();

            renderer.render(
                &lt;Todo todo={todo} &gt;&lt;/Todo&gt;);

            const output = renderer.getRenderOutput();

    				//We expect the &lt;Todo&gt; to output an &lt;li&gt; element
            expect(output.type).toBe('li');

            const children = output.props.children;
            const [input, span] = children;

    				//We expect the first element in our &lt;li&gt; to be an input
            expect(input.type).toBe('input');

            const todoName = span.props.children;

    				//We expect the span to contain the name of the todo
            expect(todoName).toBe(todo.name);
        });
    });
</code></pre>
<p>There’s a lot to unpack here that is beyond the scope of this article, so I’ll refer you to the resources at the bottom of the page for more detail. But the big picture is fairly simple. We’ve created a “mock” todo object, and used it to populate our component, which is then “rendered” using <code>TestUtils.createRenderer()</code> (<code>TestUtils</code> also includes features for simulating clicks and other user interactions with your components). At that point, we’re simply traversing the “DOM” and making assertions about the expected content.</p>
<p>To run this test, use <code>npm</code> to run our new <code>test</code> script:</p>
<pre><code>    npm run test
</code></pre>
<pre><code class="language-javascript">    &gt; todo-list@1.0.0 test /Users/zak/Dev/TodoList
    &gt; mocha './src/test/js/*.spec.js' --compilers js:babel-core/register

      Todo
        ✓ should have expected content

      1 passing (15ms)
</code></pre>
<p>Finally, we can add this test script to our Gradle build using the same techniques we explored earlier.</p>
<pre><code class="language-groovy">    //build.gradle

    //Run React tests
    task mochaTest(dependsOn: ['npmInstall', 'npm_run_test'])

    check.dependsOn(mochaTest)
</code></pre>
<p>Now we can run our React tests via Gradle with <code>./gradlew mochaTest</code>, and they will also be run as part of the <code>check</code> task (which runs Grails unit and integration tests together).</p>
<h2>Conclusion</h2>
<p>React is a powerful and exciting library, and it’s a great choice for Grails applications. While there’s some bootstrapping necessary to get started, with a project structure like we’ve demonstrated you should be able to take advantage of the many resources available for learning React and associated libraries and tools, without having to “translate” into a Grails-specific flavor. In addition, front-end developers unfamiliar with Grails should find it much easier to work using their favorite node-based tools and development environments. The only requirement to firing up the backend is Java and the Gradle wrapper that is included in the Grails project. With React’s tooling standardized around <code>npm</code>, and Grails’ build process managed by <code>Gradle</code>, it’s quite straightforward to set up a combined development and deployment pipeline, one that allows both frameworks to be used as designed.</p>
<blockquote>
<p>Postscript</p>
<p>As mentioned earlier in the article, I've created a <a href="https://github.com/ZacharyKlein/grails-react-starter">starter project</a> with React integrated in a Grails application, using the same structure described above. It also provides a working configuration for the <code>webpack-dev-server</code>, including a custom taglib to switch between the “hot load” bundle and the static bundle from the Grails asset pipeline. React-Bootstrap and loading of images and CSS are also demonstrated. The project is available on Github. [2]</p>
</blockquote>
<h2>References</h2>
<ul>
<li>[1] Sample App: <a href="https://github.com/ZacharyKlein/sett-todolist">https://github.com/ZacharyKlein/sett-todolist</a></li>
<li>[2] Grails-React Starter: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://github.com/ZacharyKlein/grails-react-starter</a></li>
<li>[3] Gradle-node-plugin: <a href="https://github.com/srs/gradle-node-plugin">https://github.com/srs/gradle-node-plugin</a></li>
<li>[4] JSX and “Separation of concerns”: <a href="https://blog.andrewray.me/youre-missing-the-point-of-jsx/">https://blog.andrewray.me/youre-missing-the-point-of-jsx/</a></li>
<li>[5] Why and how to bind methods in your React component classes?: <a href="https://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/">https://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/</a></li>
<li>[6] Fetch API: <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch">https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch</a></li>
<li>[7] How we unit test React components using expect-jsx: <a href="https://blog.algolia.com/how-we-unit-test-react-components-using-expect-jsx/">https://blog.algolia.com/how-we-unit-test-react-components-using-expect-jsx</a></li>
<li>[8] How React Components Make UI Testing Easy <a href="https://www.toptal.com/react/how-react-components-make-ui-testing-easy">https://www.toptal.com/react/how-react-components-make-ui-testing-easy</a></li>
</ul>
<h2>Resources</h2>
<ul>
<li>OCI Training in React Web Development: <a href="https://ocitraining.com/react-web-development/">https://ocitraining.com/react-web-development</a></li>
<li>Egghead.io video courses on React and related technologies: <a href="https://egghead.io/q/react">https://egghead.io/q/react</a></li>
<li>Navigating the React.JS Ecosystem: <a href="https://www.toptal.com/react/navigating-the-react-ecosystem">https://www.toptal.com/react/navigating-the-react-ecosystem</a></li>
<li>An excellent set of sample React apps written and maintained by my OCI colleague, Mark Volkmann: <a href="https://github.com/mvolkmann/react-examples">https://github.com/mvolkmann/react-examples</a></li>
<li>RubyC presentation by <a href="https://alexbcoles.com/">Alex Coles</a>, “Beyond the Asset Pipeline” (Rails-specific talk, but much of the discussion is relevant to the Grails asset pipeline as well): <a href="https://youtu.be/CNv9ewmQys8">https://youtu.be/CNv9ewmQys8</a></li>
<li>How to Use Webpack with Rails (also Rails-specific, but many of the techniques described are relevant to Grails projects): <a href="https://clarkdave.net/2015/01/how-to-use-webpack-with-rails/">https://clarkdave.net/2015/01/how-to-use-webpack-with-rails/</a></li>
</ul>
<h2>Documentation</h2>
<ul>
<li>React Documentation: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://facebook.github.io/react/docs/getting-started.html</a></li>
<li>React Test-Utils: <a href="https://facebook.github.io/react/docs/test-utils.html">https://facebook.github.io/react/docs/test-utils.html</a></li>
<li>JSX Documentation: <a href="https://github.com/ZacharyKlein/grails-react-starter">https://facebook.github.io/react/docs/jsx-in-depth.html</a></li>
<li>Webpack Documentation: <a href="https://webpack.js.org/concepts/">https://webpack.js.org/concepts/</a></li>
</ul>]]></description><author>Zachary Klein</author><guid>2016-05-28</guid><pubDate>Sat, 28 May 2016 00:00:00 GMT</pubDate></item><item><title>Deploying Grails® 3.1 Applications to JBoss 6.4 EAP</title><link>https://grails.apache.org/blog/2016-05-26.html</link><description><![CDATA[</p>
<p>We had <a href="https://grails.io/post/142674392718/deploying-grails-3-to-wildfly-10">previously</a> described how to deploy Grails<sup>®</sup> 3.1 applications to WildFly 10, which is where all of the &quot;cutting edge&quot; work happens in the JBoss world.</p>
<p>The process to deploy Grails 3.1 applications to JBoss 6.4 EAP is largely similar, with some minor configuration differences.</p>
<p>Firstly, you have to configure your dependencies in <code>build.gradle</code> correctly by marking Tomcat as a provided dependency and including JAXB as a runtime dependency:</p>
<pre><code class="language-groovy">provided &quot;org.springframework.boot:spring-boot-starter-tomcat&quot;    
runtime 'javax.xml.bind:jaxb-api:2.2.12'
</code></pre>
<p>Next you need to create a <code>src/main/webapp/WEB-INF/jboss-deployment-structure.xml</code> file with the following contents:</p>
<pre><code class="language-xml">&lt;?xml version='1.0' encoding='UTF-8'?&gt;
&lt;jboss-deployment-structure xmlns=&quot;urn:jboss:deployment-structure:1.1&quot;&gt;
    &lt;deployment&gt;
        &lt;exclusions&gt;
          &lt;module name=&quot;javaee.api&quot;&gt;&lt;/module&gt;
          &lt;module name=&quot;javax.validation.api&quot;&gt;&lt;/module&gt;
          &lt;module name=&quot;javax.faces.api&quot;&gt;&lt;/module&gt;
          &lt;module name=&quot;org.hibernate.validator&quot;&gt;&lt;/module&gt;
        &lt;/exclusions&gt;
    &lt;/deployment&gt;
&lt;/jboss-deployment-structure&gt;
</code></pre>
<p>This will prevent JBoss from loading any APIs that conflict. For example Grails ships with <code>javax.validation</code> version 1.1 but JBoss 6.4 comes prepackages with version 1.0, so without this configuration you would end up with an exception such as:</p>
<pre><code class="language-plaintext">Caused by: java.lang.NoSuchMethodError: javax.validation.spi.ConfigurationState.getParameterNameProvider()Ljavax/validation/ParameterNameProvider;
    at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.&lt;init&gt;(ValidatorFactoryImpl.java:119)
    at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:45)
</code></pre>
<p>With these two changes in place you can run <code>gradle assemble</code> to produce a WAR file that can be deployed to JBoss 6.4 EAP!</p>]]></description><author>Graeme Rocher</author><guid>2016-05-26</guid><pubDate>Thu, 26 May 2016 00:00:00 GMT</pubDate></item><item><title>Grails® Slack Channel</title><link>https://grails.apache.org/blog/2016-04-28.html</link><description><![CDATA[</p>
<p>The folks at Slack describe their application as follows:</p>
<blockquote>
<p>A messaging app for teams who are changing the world.</p>
</blockquote>
<p>That sounds like us! :)</p>
<p>We set up the Grails<sup>®</sup> Slack channel less than a year ago, and the channel has been very well received by the community. Our Slack channel is a great place to connect with the core Grails development team, as well as thousands of other Grails users, to ask and answer questions and to discuss ideas.</p>
<p>The Grails Slack Channel can be found at <a href="https://grails.slack.com/">https://grails.slack.com</a>. Sign up at <a href="https://slack.grails.org">https://slack.grails.org</a>.</p>]]></description><author>Jeff Scott Brown</author><guid>2016-04-28</guid><pubDate>Thu, 28 Apr 2016 00:00:00 GMT</pubDate></item><item><title>How to Use a Specific Version of GORM in Grails® 3</title><link>https://grails.apache.org/blog/2016-04-27.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/gorm.html"><span class="hashtag">#gorm</span></a></p>
<p>In order to ensure compatibility Grails<sup>®</sup> 3 ships with a BOM that applies dependency management and enforces a particular version of GORM when using Grails.</p>
<p>Sometimes however, you want to use a different version or there is a more recent version of GORM out there that you would prefer to use.</p>
<p>Luckily Gradle makes this fairly easy to control. Using the following snippet you can enforce a particular GORM version within your <code>build.gradle</code>:</p>
<pre><code class="language-groovy">configurations.all {
    resolutionStrategy.eachDependency { DependencyResolveDetails details -&gt;
        if (details.requested.group == 'org.grails' 
        &amp;&amp; details.requested.name.startsWith('grails-datastore')) {
            details.useVersion(&quot;5.0.5.RELEASE&quot;)
        }
    }        
}
</code></pre>
<p>In this example I’m forcing Gradle to resolve the <code>5.0.5.RELEASE</code> version of GORM using the Gradle resolutionStrategy.</p>]]></description><author>Graeme Rocher</author><guid>2016-04-27</guid><pubDate>Wed, 27 Apr 2016 00:00:00 GMT</pubDate></item><item><title>JSON Views</title><link>https://grails.apache.org/blog/2016-04-13.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/json.html"><span class="hashtag">#json</span></a> <a href="https://grails.apache.org/blog/tag/rest.html"><span class="hashtag">#rest</span></a></p>
<p>We recently published another Grails<sup>®</sup> Quickcast, brought to you in collaboration with DZone. In case you missed the first episode on Grails 3 Interceptors, you can view it <a href="https://objectcomputing.com/products/grails/resources/quickcasts/grails-interceptors">here</a>.</p>
<p>The latest episode introduces JSON Views, a really simple yet powerful tool supported by Grails 3 for describing the JSON response formats for REST APIs. The video is available <a href="https://objectcomputing.com/products/grails/resources/quickcasts/json-views">here</a>.</p>
<p>Another powerful feature supported by the tool is convention-based content negotiation.</p>
<p>Consider a simple domain class.</p>
<pre><code class="language-groovy">package demo

import grails.rest.Resource

@Resource(uri='/books', formats=['json'])
class Book {
    String title
    String author
}
</code></pre>
<p>A simple JSON view for that domain class might look like this.</p>
<pre><code class="language-groovy">// grails-app/views/book/_book.gson
import demo.Book

model {
	Book book
}

json {
   bookTitle book.title
   bookAuthor book.author
}
</code></pre>
<p>When a request is made to render a Book, that view will be used by default.</p>
<pre><code>    $ curl http://localhost:8080/books/1.json
    {&quot;bookTitle&quot;:&quot;Wool&quot;,&quot;bookAuthor&quot;:&quot;Hugh Howey&quot;}
</code></pre>
<p>Grails takes into account a number of factors when attempting to resolve the view including the content type, version and locale.</p>
<p>The following paths are searched:</p>
<ul>
<li>view_name[_LOCALE][_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_de_hal_v1.0.gson)</li>
<li>view_name[_LOCALE][_ACCEPT_CONTENT_TYPE].gson (Example: show_de_hal.gson)</li>
<li>view_name[_LOCALE][_ACCEPT_VERSION].gson (Example: show_de_v1.0.gson)</li>
<li>view_name[_LOCALE].gson (Example: show_de.gson)</li>
<li>view_name[_ACCEPT_CONTENT_TYPE][_ACCEPT_VERSION].gson (Example: show_hal_v1.0.gson)</li>
<li>view_name[_ACCEPT_VERSION][_ACCEPT_CONTENT_TYPE].gson (Example: show_v1.0_hal.gson)</li>
<li>view_name[_ACCEPT_CONTENT_TYPE].gson (Example: show_hal.gson)</li>
<li>view_name[_ACCEPT_VERSION].gson (Example: show_v1.0.gson)</li>
<li>view_name.gson (Example: show.gson)</li>
</ul>
<p>The content type (defined by either the <code>ACCEPT</code> header or file extension in the URI) is taken into account to allow different formats for the same view.</p>
<p>For more detail, see <a href="https://grails.github.io/grails-views/latest/">the official documentation</a>.</p>]]></description><author>Jeff Scott Brown</author><guid>2016-04-13</guid><pubDate>Wed, 13 Apr 2016 00:00:00 GMT</pubDate></item><item><title>Quickcast #2: JSON Views</title><link>https://grails.apache.org/blog/2016-04-01-2.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a> <a href="https://grails.apache.org/blog/tag/json.html"><span class="hashtag">#json</span></a></p>
<p>In a delightful and informative 15 minutes, the Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, probes JSON views.</p>
<p>Beginning with a Grails 3.1.1 application created with a standard web profile, Jeff demonstrates how to add a few custom domain classes.</p>
<p>Jeff uses music examples, including <em>Space Oddity</em> by David Bowie (RIP) and <em>Close to the Edge</em> by Yes, to populate an artist class with associated albums annotated with grails.rest.Resource.</p>
<p>The goal is to publish a REST API under <code>/artists</code> to manage instances of the <code>artist</code> class and to support the JSON and XML formats. Sending a request to <code>/artists</code> delivers a list of artists, all of whom have albums associated with them.</p>
<p>While the app is running in development mode, the JSON files can be altered, and the effects of those changes can be seen real-time in the application.</p>
<p>This Quickcast assumes basic knowledge of Grails, JSON, and REST APIs.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XnRNfDGkBVg" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown</author><guid>2016-04-01-2</guid><pubDate>Fri, 01 Apr 2016 00:00:00 GMT</pubDate></item><item><title>Quickcast #1: Grails® Interceptors</title><link>https://grails.apache.org/blog/2016-04-01-1.html</link><description><![CDATA[</p>
<p>Tags: <a href="https://grails.apache.org/blog/tag/quickcast.html"><span class="hashtag">#quickcast</span></a></p>
<p>In this 17-minute video, the Grails<sup>®</sup> framework co-founder, <a href="https://objectcomputing.com/products/2gm-team#brown">Jeff Scott Brown</a>, talks Grails <a href="https://en.wikipedia.org/wiki/Interceptor_pattern">interceptors</a>.</p>
<p>(Yes, <code>create-interceptor</code> actually creates an interceptor. Mind. Blown.)</p>
<p>This tutorial assumes only basic familiarity with Groovy (which is pretty darned expressive anyway) and the MVC concept (which you already know). It also serves as an excellent introduction to the interceptor pattern in any language, because Grails' behind-the-scenes legwork lets you focus on the logic of the pattern.</p>
<p>Grails Quickcasts, brought to you through a partnership between <a href="https://objectcomputing.com/">Object Computing, Inc.</a> (OCI) and <a href="https://dzone.com/">DZone</a>, provide bite-sized tutorials to help you maximize your productivity with the Framework.</p>
<iframe width="100%" height="560" src="https://www.youtube-nocookie.com/embed/XnRNfDGkBVg" frameborder="0"></iframe>]]></description><author>Jeff Scott Brown</author><guid>2016-04-01-1</guid><pubDate>Fri, 01 Apr 2016 00:00:00 GMT</pubDate></item><item><title>Grails® 3 Interceptors</title><link>https://grails.apache.org/blog/2015-03-01.html</link><description><![CDATA[</p>
<h2>Introduction</h2>
<p>Grails<sup>®</sup> 3 is a major step forward in the evolution of the framework and re-evaluates many aspects of the framework that have evolved over the years. One area of the framework that was re-evaluated is that related to Grails filters.</p>
<p>Grails filters are a lot like servlet filters but are more simple and are better integrated into the Grails runtime and its conventions. Grails filters were a way to implement logic that might relate to any number of controllers and were a powerful and flexible way to address many of those concerns. Grails 3 introduces the notion of interceptors as a better way to address many of the types of concerns that previously would have been addressed with filters.</p>
<p>Like filters, interceptors contain code which may be applied to requests before and/or after invoking controller actions without having to embed that logic into all of the controllers that the logic may relate to. Interceptors offer a number of benefits over filters including support for static compilation and more flexible configurability.</p>
<h2>Defining An Interceptor</h2>
<p>Like most Grails artifacts, interceptors are normal Groovy classes that follow certain conventions which allow the framework to identify them and augment them with a rich set of behavior that is relevant to tasks that interceptors frequently address.</p>
<p>Because interceptors are often associated with controllers the convention is to define them under the <code>grails-app/controllers/</code> directory. Interceptor class names should end with the word <code>Interceptor</code>.</p>
<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
package demo

class FirstInterceptor {
    // ...
}
</code></pre>
<p>The interceptor class does noes not need to extend any special base class and does not need to be marked with any special annotations in order for the framework to recognize the class as an interceptor. The location of the source file and the name of the class are sufficient to register the class as an interceptor.</p>
<p>The <code>create-interceptor</code> command may be used to define an interceptor.</p>
<pre><code>    $ grails create-interceptor demo.First
    | Created grails-app/controllers/demo/FirstInterceptor.groovy
    | Created src/test/groovy/demo/FirstInterceptorSpec.groovy
</code></pre>
<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
package demo

class FirstInterceptor {

    boolean before() { true }

    boolean after() { true }

    void afterView() {
        // no-op
    }

}
</code></pre>
<pre><code class="language-groovy">// src/test/groovy/demo/FirstInterceptorSpec.groovy
package demo


import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(FirstInterceptor)
class FirstInterceptorSpec extends Specification {

    void &quot;Test first interceptor matching&quot;() {
        when:&quot;A request matches the interceptor&quot;
            withRequest(controller:&quot;first&quot;)

        then:&quot;The interceptor does match&quot;
            interceptor.doesMatch()
    }
}
</code></pre>
<h2>The Interceptor Trait</h2>
<p>Grails 3 takes advantage of Groovy's powerful and flexible support for traits in many places. All interceptors are automatically made to implement the <a href="https://grails.github.io/legacy-grails-doc/3.0.x/api/grails/artefact/Interceptor.html">grails.artefact.Interceptor</a> trait so all of the methods and properties defined by that trait and all of the methods and properties defined by traits which that trait extends are all available inside of an interceptor. This provides easy access to attributes like <code>grailsApplication</code>, <code>params</code>, <code>request</code>, <code>session</code> and others. The trait also provides access to methods like <code>redirect</code> and <code>render</code>.</p>
<h2>Matching Requests</h2>
<p>A convention is imposed which will automatically configure interceptors to match all requests to their corresponding controller. The implicit mapping from an interceptor to a controller is based on the artifact names. For example, by default the <code>PersonInterceptor</code> will match all requests to the <code>PersonController</code>.</p>
<p>Interceptors often need to deviate from the convention and define which requests they should participate in using the <code>match</code>or <code>matchAll</code> method.</p>
<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
package demo

class FirstInterceptor {

    public FirstInterceptor() {
        // match all requests to the
        // reporting controller...
        match controller: 'reporting'

        // match a request to the create action
        // in the person controller
        match controller: 'person', action: 'create'

        // match all requests to the accounting
        // or payroll controller
        match controller: ~/(accounting|payroll)/
    }

    // ...
}
</code></pre>
<p>The named arguments supported are <code>namespace</code>, <code>controller</code>, <code>action</code>, <code>method</code>, and <code>uri</code>. All of them except for <code>uri</code> accept either a <code>String</code> or a regex expression. The <code>uri</code> argument supports a <code>String</code> path that is compatible with Spring's <a href="https://docs.spring.io/spring/docs/4.1.7.RELEASE/javadoc-api/org/springframework/util/AntPathMatcher.html">org.springframework.util.AntPathMatcher</a>.</p>
<p>An interecptor may match all requests except requests that satisfy some condition.</p>
<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
package demo

class FirstInterceptor {

    public FirstInterceptor() {
        // match all requests except requests
        // to the auth controller
        matchAll().excludes(controller: 'auth')
    }

    // ...
}
</code></pre>
<p>The <code>match</code> and <code>matchAll</code> methods in an intereceptor each return an instance of <a href="https://grails.github.io/grails-doc/3.0.x/api/grails/interceptors/Matcher.html">grails.interceptors.Matcher</a>. Most of the methods in <code>Matcher</code> also return the <code>Matcher</code> which allows for method chaining as shown above with <code>matchAll().excludes(controller: 'auth')</code>.</p>
<p>Care should be taken to narrow the group of requests that an interceptor is applied to. Keep in mind that whatever logic is contained in an interceptor is being engaged for all of the requests that the interceptor matches.</p>
<h2>Interceptor Methods</h2>
<p>There are 3 separate methods that an interceptor may define to participate in different parts of the request processing lifecycle. The <code>before</code> method is executed before the controller action is invoked. The <code>after</code> method is invoked after the controller action returns and before the view is rendered. The <code>afterView</code> method is invoked after the view is rendered. An interceptor may provide any combination of these 3 call back methods and does not need to provide all 3.</p>
<p>The <code>before</code> and <code>after</code> methods have a <code>boolean</code> return type. The methods should return <code>true</code> to indicate that control should continue as usual without interruption. The methods should return <code>false</code> to indicate that the interceptor has decided that the request has been handled by the intereceptor and processing should not continue on as per usual. For example, a <code>before</code> interceptor may recognize that a request to a controller action is invalid for some reason, issued a <code>redirect</code> to handle the situation and then return <code>false</code> so that the originally requested action will not be engaged.</p>
<pre><code class="language-groovy">package demo

class SimpleAuthInterceptor {

    public SimpleAuthInterceptor() {
        match controller: 'person'
    }

    boolean before() {
        // if the user has not been authenticated,
        // redirect to authenticate the user...
        if(!session.userHasBeenAuthenticated) {
            redirect controller: 'auth', action: 'login'
            return false
        }
        true
    }
}
</code></pre>
<h2>Interceptor Ordering</h2>
<p>Any number of interceptors may match a request and in some circumstances it may be useful to affect the order in which the interceptors are invoked. To support this, the framework will recognize an <code>int</code> property named <code>order</code> defined in any interceptor. The value of the <code>order</code> property may be any number. Intereceptors are sorted based on their order from lowest to highest value and executed in that order so an interceptor with an <code>order</code> of 100 will execute before an interceptor with an <code>order</code> of 200. This determines the order in which the <code>before</code> interceptor methods are invoked. The interceptors are configured kind of like a stack and are popped off of the stack while processing the <code>after</code> and <code>afterView</code> methods so those are executed in the opposite order that the <code>before</code> methods are executed.</p>
<p>For convenience there are properties named <code>HIGHEST_PRECEDENCE</code> and <code>LOWEST_PRECEDENCE</code> which may be referenced when initializing the <code>order</code> property.</p>
<pre><code class="language-groovy">package demo

class FirstInterceptor {

    int order = HIGHEST_PRECEDENCE + 100

    // ...

}
</code></pre>
<pre><code class="language-groovy">package demo

class SecondInterceptor {

    int order = HIGHEST_PRECEDENCE + 200

    // ...

}
</code></pre>
<h2>Static Compilation</h2>
<p>Unlike Grails 2 filters, Grails 3 intercetors are compatible with Groovy's static compilation and as such may be marked with the <code>@CompileStatic</code> annotation. Static compilation may be of particular importance in an interceptor because code in an interceptor potentially could be executed as part of handling every request into the application so performance may be particularly important there. Referencing methods introduced by the <code>Interceptor</code> trait like <code>redirect</code> and <code>render</code> and accessing propeties like <code>grailsApplication</code> are all compatible with <code>@CompileStatic</code>.</p>
<h2>Logging</h2>
<p>Like most Grails artifacts interceptors have a <code>log</code> property.</p>
<pre><code class="language-groovy">package demo

class SimpleAuthInterceptor {

    public SimpleAuthInterceptor() {
        match controller: 'person'
    }

    boolean before() {
        // if the user has not been authenticated,
        // redirect to authenticate the user...
        if(!session.userHasBeenAuthenticated) {
            // log a message
            log.debug 'Redirecting to login page'
            redirect controller: 'auth', action: 'login'
            return false
        }
        true
    }
}
</code></pre>
<p>The default logger name for an interceptor is <code>grails.app.controllers</code>. For the interceptor shown above that would be <code>grails.app.controllers.demo.SimpleAuthInterceptor</code> so the logging could be configured in <code>grails-app/conf/logback.groovy</code> as shown below.</p>
<pre><code class="language-groovy">// ...
logger 'grails.app.controllers.demo.SimpleAuthInterceptor',
       DEBUG, ['STDOUT'], false
</code></pre>
<p>Note that the logger name prefix is <code>grails.app.controllers</code>, not <code>grails.app.interceptors</code>. This is because by default interceptors are defined under the <code>grails-app/controllers/</code> directory.</p>
<p>The framework offers flexibility around this such that if you would like to separate your interceptors from your controllers you can do that by moving the interceptors to a directory like <code>grails-app/interceptors/</code>. If the interceptor defined above were moved from <code>grails-app/controllers/demo/SimpleAuthInterceptor.groovy</code> to <code>grails-app/interceptors/demo/SimpleAuthInterceptor.groovy</code>, the logger name would be <code>grails.app.interceptors.demo.SimpleAuthInterceptor</code>.</p>
<h2>Interceptors Are Spring Beans</h2>
<p>All interceptors are configured as beans in the Spring application context and are configured to be autowired by name. This means that just like other Grails artifacts, an interceptor may define a property with a name that matches a bean name and that property will be initialized using standard Spring dependency injection.</p>
<p>In addition to participating in dependency injection, because interceptors are Spring beans they participate in all of the standard Spring bean management handling. For example, if an interceptor wanted access to the application's configuration, the intereceptor class could implement the <a href="https://grails.github.io/grails-doc/3.0.x/api/grails/core/support/GrailsConfigurationAware.html">grails.core.support.GrailsConfigurationAware</a> interface.</p>
<pre><code class="language-groovy">package demo

import grails.config.Config
import grails.core.support.GrailsConfigurationAware

class FirstInterceptor implements GrailsConfigurationAware {

    boolean before() {
        // ...
    }

    @Override
    void setConfiguration(Config co) {
        // configure the interceptor matching dynamically
        // based on what is in application.yml
        match co.'demo.interceptor.first'
    }
}
</code></pre>
<p>With that in place, the request matching could be dynamically configured in <code>grails-app/conf/application.yml</code>.</p>
<pre><code class="language-yml">demo:
    interceptor:
        first:
            action: save
            controller: person
</code></pre>
<h2>Testing Interceptors</h2>
<p>Interceptors may be tested on their own as first class artifacts.</p>
<pre><code class="language-groovy">// grails-app/controllers/demo/FirstInterceptor.groovy
package demo

class FirstInterceptor {

    public FirstInterceptor() {
        match controller: 'demo', action: 'index'
    }

    boolean before() {
        params.firstInterceptorRan = 'yes'
        true
    }
}
</code></pre>
<pre><code class="language-groovy">// grails-app/controllers/demo/DemoController.groovy
package demo

class DemoController {

    def index() {
        render &quot;firstInterceptorRan is ${params.firstInterceptorRan}&quot;
    }

    def create() {
        render &quot;firstInterceptorRan is ${params.firstInterceptorRan}&quot;
    }
}
</code></pre>
<pre><code class="language-groovy">// src/test/groovy/demo/DemoInterceptorSpec.groovy
package demo


import grails.test.mixin.TestFor
import spock.lang.Specification

@TestFor(DemoInterceptor)
class DemoInterceptorSpec extends Specification {

    void &quot;Test first interceptor matching&quot;() {
        when:&quot;A request is made to the index action&quot;
        withRequest(controller:&quot;demo&quot;, action: 'index')

        then:&quot;The interceptor does match&quot;
        interceptor.doesMatch()
    }

    void &quot;Test first interceptor not matching&quot;() {
        when:&quot;A request is made to the create action&quot;
        withRequest(controller:&quot;demo&quot;, action: 'create')

        then:&quot;The interceptor does not match&quot;
        !interceptor.doesMatch()
    }
}
</code></pre>
<p>The effects introduced by an interceptor may be tested in a functional test.</p>
<pre><code class="language-groovy//">package demo

import geb.spock.GebSpec
import grails.test.mixin.integration.Integration

@Integration
class DemoControllerFunctionalSpec extends GebSpec {

    void &quot;test the index action&quot;() {
        when:
        go '/demo/index'

        then:
        $().text() == 'firstInterceptorRan is yes'
    }

    void &quot;test the create action&quot;() {
        when:
        go '/demo/create'

        then:
        $().text() == 'firstInterceptorRan is null'
    }
}
</code></pre>
<h2>Conclusion</h2>
<p>Grails 3 interceptors are a great way to insert logic into the request handling process. Like all Grails artifacts, interceptors take advantage of convention over configuration and sensible defaults to maximize flexibility and minimize configuration burden required to take advantage of really powerful functionality provided by the framework. Support for marking interceptors with <code>@CompileStatic</code> means that the performance cost associated with interceptor logic can be minimized. The fact that interceptors are Spring beans provides a lot of flexibility for keeping interceptors simple yet powerful.</p>]]></description><author>Jeff Scott Brown</author><guid>2015-03-01</guid><pubDate>Sun, 01 Mar 2015 00:00:00 GMT</pubDate></item></channel></rss>