This is an automated email from the ASF dual-hosted git repository.
git-site-role pushed a commit to branch asf-site
in repository https://gitbox.apache.org/repos/asf/groovy-dev-site.git
The following commit(s) were added to refs/heads/asf-site by this push:
new f99a5df 2026/03/24 10:22:52: Generated dev website from
groovy-website@34cbdb8
f99a5df is described below
commit f99a5dfc9a8077ab6677e7d3173c78e0c3320785
Author: jenkins <[email protected]>
AuthorDate: Tue Mar 24 10:22:52 2026 +0000
2026/03/24 10:22:52: Generated dev website from groovy-website@34cbdb8
---
blog/groovy-async-await.html | 505 +++++++++++++++++++++++++++++++++++++++++++
blog/index.html | 2 +-
blog/loop-invariants.html | 8 +-
search/search-index.json | 11 +-
4 files changed, 522 insertions(+), 4 deletions(-)
diff --git a/blog/groovy-async-await.html b/blog/groovy-async-await.html
new file mode 100644
index 0000000..6858f26
--- /dev/null
+++ b/blog/groovy-async-await.html
@@ -0,0 +1,505 @@
+<!DOCTYPE html>
+<!--[if lt IE 7]> <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
+<!--[if IE 7]> <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
+<!--[if IE 8]> <html class="no-js lt-ie9"> <![endif]-->
+<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]--><head>
+ <meta charset='utf-8'/><meta http-equiv='X-UA-Compatible'
content='IE=edge'/><meta name='viewport' content='width=device-width,
initial-scale=1'/><meta name='keywords' content='async, await, concurrency,
virtual-threads'/><meta name='description' content='This post looks at a
proposed extension to Groovy which provides comprehensive async/await
support.'/><title>The Apache Groovy programming language - Blogs - Async/await
for Groovy</title><link href='../img/favicon.ico' type='image/ [...]
+</head><body>
+ <div id='fork-me'>
+ <a href='https://github.com/apache/groovy'>
+ <img style='position: fixed; top: 20px; right: -58px; border: 0;
z-index: 100; transform: rotate(45deg);'
src='../img/horizontal-github-ribbon.png'/>
+ </a>
+ </div><div id='st-container' class='st-container st-effect-9'>
+ <nav class='st-menu st-effect-9' id='menu-12'>
+ <h2 class='icon icon-lab'>Socialize</h2><ul>
+ <li>
+ <a href='https://groovy-lang.org/mailing-lists.html'
class='icon'><span class='fa fa-classic fa-regular fa-envelope'></span> Discuss
on the mailing list</a>
+ </li><li>
+ <a href='https://x.com/ApacheGroovy' class='icon'><span
class='fa fa-brands fa-x-twitter'></span> Groovy on X</a>
+ </li><li>
+ <a href='https://bsky.app/profile/groovy.apache.org'
class='icon'><span class='fa fa-brands fa-bluesky'></span> Groovy on Bluesky</a>
+ </li><li>
+ <a href='https://fosstodon.org/@ApacheGroovy'
class='icon'><span class='fa fa-brands fa-mastodon'></span> Groovy on
Mastodon</a>
+ </li><li>
+ <a
href='https://www.linkedin.com/company/106402668/admin/dashboard/'
class='icon'><span class='fa fa-brands fa-linkedin'></span> Groovy on
LinkedIn</a>
+ </li><li>
+ <a href='https://groovy-lang.org/events.html'
class='icon'><span class='fa fa-classic fa-solid fa-calendar-days'></span>
Events and conferences</a>
+ </li><li>
+ <a href='https://github.com/apache/groovy'
class='icon'><span class='fa fa-brands fa-github'></span> Source code on
GitHub</a>
+ </li><li>
+ <a href='https://groovy-lang.org/reporting-issues.html'
class='icon'><span class='fa fa-classic fa-solid fa-bug'></span> Report issues
in Jira</a>
+ </li><li>
+ <a href='http://stackoverflow.com/questions/tagged/groovy'
class='icon'><span class='fa fa-brands fa-stack-overflow'></span> Stack
Overflow questions</a>
+ </li><li>
+ <a href='http://www.groovycommunity.com/'
class='icon'><span class='fa fa-brands fa-slack'></span> Slack Community</a>
+ </li>
+ </ul>
+ </nav><div class='st-pusher'>
+ <div class='st-content'>
+ <div class='st-content-inner'>
+ <!--[if lt IE 7]>
+ <p class="browsehappy">You are using an
<strong>outdated</strong> browser. Please <a
href="http://browsehappy.com/">upgrade your browser</a> to improve your
experience.</p>
+ <![endif]--><div><div class='navbar navbar-default
navbar-static-top' role='navigation'>
+ <div class='container'>
+ <div class='navbar-header'>
+ <button type='button'
class='navbar-toggle' data-toggle='collapse' data-target='.navbar-collapse'>
+ <span class='sr-only'></span><span
class='icon-bar'></span><span class='icon-bar'></span><span
class='icon-bar'></span>
+ </button><a class='navbar-brand'
href='../index.html'>
+ <i class='fa-classic fa-solid
fa-star'></i> Apache Groovy™
+ </a>
+ </div><div class='navbar-collapse collapse'>
+ <ul class='nav navbar-nav navbar-right'>
+ <li class=''><a
href='https://groovy-lang.org/learn.html'>Learn</a></li><li class=''><a
href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li
class=''><a href='/download.html'>Download</a></li><li class=''><a
href='https://groovy-lang.org/support.html'>Support</a></li><li class=''><a
href='/'>Contribute</a></li><li class=''><a
href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li class=''><a
href='/blog'>Blog pos [...]
+ <a data-effect='st-effect-9'
class='st-trigger' href='#'>Socialize</a>
+ </li><li class=''>
+ <a href='../search.html'>
+ <i class='fa-classic fa-solid
fa-magnifying-glass'></i>
+ </a>
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div><div id='content' class='page-1'><div
class='row'><div class='row-fluid'><div class='col-lg-3'><ul
class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a
href='#doc'>Async/await for Groovy</a></li><li><a href='#_introduction'
class='anchor-link'>Introduction</a></li><li><a
href='#_the_problem_callback_complexity' class='anchor-link'>The problem:
callback complexity</a></li><li><a
href='#_example_1_sequential_async_reads_like_synchronou [...]
+<a href="https://github.com/paulk-asert/" target="_blank" rel="noopener
noreferrer"><img style="border-radius:50%;height:48px;width:auto"
src="img/paulk-asert.png" alt="Paul King"></a>
+<div style="display:grid;align-items:center;margin:0.1ex;padding:0ex">
+ <div><a href="https://github.com/paulk-asert/" target="_blank" rel="noopener
noreferrer"><span>Paul King</span></a></div>
+ <div><small><i>PMC Member</i></small></div>
+</div>
+ </div><br/><span>Published: 2026-03-24 04:30PM</span></p><hr/><div
class="sect1">
+<h2 id="_introduction">Introduction</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>A proposed enhancement for Groovy adds native
<code>async</code>/<code>await</code> as a
+language-level feature
+(<a href="https://issues.apache.org/jira/browse/GROOVY-9381">GROOVY-9381</a>,
+<a href="https://github.com/apache/groovy/pull/2387">PR <mark>2387</a>).
+Inspired by similar constructs in JavaScript, C</mark>, Kotlin, and Swift,
+the proposal lets you write asynchronous code in a sequential, readable
+style — with first-class support for async streams, deferred cleanup,
+structured concurrency, Go-style channels, and framework adapters
+for Reactor and RxJava.</p>
+</div>
+<div class="paragraph">
+<p>On JDK 21+, async methods automatically leverage
+<a
href="https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Thread.html#ofVirtual()">virtual
threads</a>
+for optimal scalability.</p>
+</div>
+<div class="paragraph">
+<p>This is a comprehensive feature. Rather than cover every detail,
+this post walks through a handful of bite-sized examples that show
+what the day-to-day experience would feel like — and how it compares
+to what you’d write in plain Java today.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_the_problem_callback_complexity">The problem: callback complexity</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Consider a three-step workflow — fetch a user ID, look up a name,
+load a profile. With <code>CompletableFuture</code> the logic gets buried
+under plumbing:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="java">// Java with
CompletableFuture
+CompletableFuture<String> profile =
+ fetchUserId()
+ .thenCompose(id -> lookupName(id))
+ .thenCompose(name -> loadProfile(name))
+ .exceptionally(e -> "fallback");</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Each <code>.thenCompose()</code> adds a nesting level, exception recovery is
+separated from the code that causes the exception, and the control
+flow reads inside-out.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_1_sequential_async_reads_like_synchronous_code">Example 1:
sequential async — reads like synchronous code</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>With the proposed <code>async</code>/<code>await</code>, the same logic
becomes:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async String
getProfile() {
+ var id = await fetchUserId()
+ var name = await lookupName(id)
+ var profile = await loadProfile(name)
+ return profile
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Variables are declared at the point of use. The return value is
+obvious. No callbacks, no lambdas, no chained combinators. Standard
+<code>try</code>/<code>catch</code> works — and <code>await</code>
automatically unwraps
+<code>CompletionException</code>, so you catch the <em>original</em> exception
type,
+not a wrapper.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_2_parallel_tasks_fetch_once_await_together">Example 2:
parallel tasks — fetch once, await together</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Launching concurrent work and collecting the results is a common
+pattern. Here’s how it looks with <code>Awaitable.all</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async def
fetchDashboard() {
+ var user = async { fetchUser() }
+ var orders = async { fetchOrders() }
+ var prefs = async { fetchPrefs() }
+
+ var (u, o, p) = await Awaitable.all(user(), orders(), prefs())
+ return buildDashboard(u, o, p)
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>All three I/O calls run concurrently. The <code>all</code> combinator waits
+for every result, failing fast if any task throws.</p>
+</div>
+<div class="sect2">
+<h3 id="_how_this_compares_to_javas_structuredtaskscope">How this compares to
Java’s <code>StructuredTaskScope</code></h3>
+<div class="paragraph">
+<p>Java’s structured concurrency preview
+(<a href="https://openjdk.org/jeps/525">JEP 525</a>, previewing since JDK 21)
+provides a similar capability through <code>StructuredTaskScope</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="java">// Java with
StructuredTaskScope (JDK 25 preview API)
+try (var scope = StructuredTaskScope.open()) {
+ var userTask = scope.fork(() -> fetchUser());
+ var ordersTask = scope.fork(() -> fetchOrders());
+ var prefsTask = scope.fork(() -> fetchPrefs());
+ scope.join();
+ return buildDashboard(
+ userTask.get(), ordersTask.get(), prefsTask.get());
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The goals are aligned — both approaches bind task lifetimes to a
+scope and cancel siblings on failure. The Groovy version adds
+syntactic sugar (<code>await</code>, <code>all</code>) and integrates with the
same
+<code>async</code>/<code>await</code> model used everywhere else, whereas
Java’s API
+is deliberately lower-level and imperative.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_3_async_streams_with_yield_return_and_for_await">Example 3:
async streams with <code>yield return</code> and <code>for await</code></h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Many real-world scenarios involve <em>streams</em> of values that arrive
+over time — paginated API results, sensor readings, log events.
+The proposal introduces <code>yield return</code> (to produce values lazily)
+and <code>for await</code> (to consume them):</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async
fetchPages(String url) {
+ var next = url
+ while (next != null) {
+ var page = await httpGet(next)
+ yield return page.items
+ next = page.nextLink
+ }
+}
+
+async def processAll() {
+ for await (items in fetchPages('/api/data')) {
+ items.each { process(it) }
+ }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>The producer yields values on demand. The consumer pulls them with
+<code>for await</code>. The runtime provides natural
<strong>back-pressure</strong> — the
+producer blocks on each <code>yield return</code> until the consumer is ready,
+preventing unbounded memory growth. No explicit queues, signals, or
+synchronization required.</p>
+</div>
+<div class="paragraph">
+<p>There’s nothing comparable in plain Java today. You’d typically
+reach for Reactor’s <code>Flux</code> or RxJava’s
<code>Flowable</code>, each of which
+brings its own operator vocabulary and mental model. With <code>for
await</code>,
+async iteration feels as natural as a regular <code>for</code> loop.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_4_defer_go_style_cleanup">Example 4: <code>defer</code> —
Go-style cleanup</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The <code>defer</code> keyword schedules cleanup to run when the enclosing
+async method completes, regardless of success or failure.
+Multiple deferred blocks execute in LIFO order — exactly like
+<a href="https://go.dev/blog/defer-panic-and-recover">Go’s
<code>defer</code></a>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async def
withTempFile() {
+ var f = createTempFile()
+ defer { f.delete() }
+
+ var conn = openConnection()
+ defer { conn.close() }
+
+ await uploadTo(conn, f)
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>This is cleaner than nested <code>try</code>/<code>finally</code> blocks,
especially when
+multiple resources are acquired at different points in the method.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_5_go_style_channels">Example 5: Go-style channels</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>For task-to-task coordination, the proposal includes CSP-style
+channels inspired by Go:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async def
pipeline() {
+ var ch = Awaitable.channel(5) // buffered channel, capacity 5
+
+ // Producer
+ Awaitable.go {
+ for (i in 1..10) {
+ await ch.send(i)
+ }
+ ch.close()
+ }
+
+ // Consumer
+ var sum = 0
+ for await (val in ch) {
+ sum += val
+ }
+ assert sum == 55
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Channels support both unbuffered (rendezvous) and buffered modes.
+<code>for await</code> iterates received values until the channel is closed —
+the Groovy equivalent of Go’s <code>for range ch</code>. You can also
race
+channel operations with <code>Awaitable.any(…​)</code>, serving a
similar
+role to Go’s <code>select</code> statement.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_6_structured_concurrency_with_asyncscope">Example 6:
structured concurrency with <code>AsyncScope</code></h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p><code>AsyncScope</code> binds child task lifetimes to a scope — inspired by
+Kotlin’s <code>coroutineScope</code>, Swift’s
<code>TaskGroup</code>, and Java’s
+<code>StructuredTaskScope</code>. When the scope exits, all child tasks have
+completed or been cancelled:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">async def
fetchAll(List<String> urls) {
+ AsyncScope.withScope { scope ->
+ var tasks = urls.collect { url ->
+ scope.async { await httpGet(url) }
+ }
+ tasks.collect { await it }
+ }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>By default, <code>AsyncScope</code> uses fail-fast semantics: if any child
+task throws, siblings are cancelled immediately.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_example_7_framework_integration">Example 7: framework integration</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The <code>await</code> keyword natively understands
<code>CompletableFuture</code>,
+<code>CompletionStage</code>, <code>Future</code>, and
<code>Flow.Publisher</code>. For third-party
+frameworks, drop-in adapter modules are auto-discovered via
+<code>ServiceLoader</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="prettyprint highlight"><code data-lang="groovy">// With
groovy-reactor on the classpath:
+async def reactorExample() {
+ var value = await Mono.just("hello")
+ for await (item in Flux.range(1, 5)) {
+ println item
+ }
+}
+
+// With groovy-rxjava on the classpath:
+async def rxExample() {
+ var value = await Single.just("hello")
+ for await (item in Observable.range(1, 5)) {
+ println item
+ }
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>No manual adapter registration is needed — add the dependency and
+<code>await</code> works transparently with Reactor and RxJava types.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_how_it_relates_to_gpars_and_virtual_threads">How it relates to GPars
and virtual threads</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>Readers of the
+<a href="https://groovy-lang.org/blog/gpars-meets-virtual-threads.html">GPars
meets virtual threads</a>
+blog post will recall that GPars provides parallel collections,
+actors, agents, and dataflow concurrency — and that it works well
+with virtual threads via custom executor services.</p>
+</div>
+<div class="paragraph">
+<p>The async/await proposal complements GPars rather than replacing
+it. GPars excels at data-parallel operations (<code>collectParallel</code>,
+<code>findAllParallel</code>) and actor-based designs. Async/await targets a
+different sweet spot: sequential-looking code that is actually
+asynchronous, with language-level support for streams, cleanup,
+structured concurrency, and framework bridging. If you’re calling
+microservices, paginating through APIs, or coordinating I/O-bound
+tasks, async/await gives you a concise way to express that without
+dropping into callback chains.</p>
+</div>
+<div class="paragraph">
+<p>Both approaches benefit from virtual threads on JDK 21+, and
+both can coexist in the same codebase.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_the_full_picture">The full picture</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The examples above are only a taste. The complete proposal also includes
+async closures and lambdas, the <code>@Async</code> annotation (for Java-style
+declarations), <code>Awaitable</code> combinators (<code>any</code>,
<code>allSettled</code>, <code>delay</code>,
+<code>orTimeoutMillis</code>), <code>AsyncContext</code> for propagating trace
and tenant
+metadata across thread hops, cancellation support, and a pluggable
+adapter registry for custom async types. The full spec is available in
+the
+<a
href="https://github.com/apache/groovy/blob/GROOVY-9381_3/src/spec/doc/core-async-await.adoc">draft
documentation</a>.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_wed_love_your_feedback">We’d love your feedback</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>The async/await feature is currently a proposal in
+<a href="https://github.com/apache/groovy/pull/2387">PR #2387</a>
+(tracking issue
+<a href="https://issues.apache.org/jira/browse/GROOVY-9381">GROOVY-9381</a>).
+This is a substantial addition to the language and we want to get
+it right.</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p><strong>Comment</strong> on the <a
href="https://github.com/apache/groovy/pull/2387">PR</a> or
+the <a href="https://issues.apache.org/jira/browse/GROOVY-9381">JIRA issue</a>
+with your thoughts, use cases, or design suggestions.</p>
+</li>
+<li>
+<p><strong>Vote</strong> on the JIRA issue if you’d like to see this
feature land.</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Your feedback helps us gauge interest and shape the final design.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_conclusion">Conclusion</h2>
+<div class="sectionbody">
+<div class="paragraph">
+<p>We’ve seen how the proposed async/await feature lets you write
+async Groovy code that reads almost like synchronous code — from
+simple sequential awaits, to parallel fan-out, async streams,
+Go-style channels, structured concurrency, and framework
+integration. The syntax is concise, the mental model is
+straightforward, and virtual threads make it scale.</p>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_references">References</h2>
+<div class="sectionbody">
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://github.com/apache/groovy/pull/2387">PR #2387 — Async/await
support</a></p>
+</li>
+<li>
+<p><a href="https://issues.apache.org/jira/browse/GROOVY-9381">GROOVY-9381 —
Tracking issue</a></p>
+</li>
+<li>
+<p><a
href="https://github.com/apache/groovy/blob/GROOVY-9381_3/src/spec/doc/core-async-await.adoc">Draft
spec documentation</a></p>
+</li>
+<li>
+<p><a href="https://openjdk.org/jeps/525">JEP 525 — Structured Concurrency
(Sixth Preview)</a></p>
+</li>
+<li>
+<p><a
href="https://groovy-lang.org/blog/gpars-meets-virtual-threads.html">GPars
meets Virtual Threads</a></p>
+</li>
+<li>
+<p><a href="http://gpars.org/">GPars</a></p>
+</li>
+</ul>
+</div>
+</div>
+</div></div></div></div></div><footer id='footer'>
+ <div class='row'>
+ <div class='colset-3-footer'>
+ <div class='col-1'>
+ <h1>Groovy</h1><ul>
+ <li><a
href='https://groovy-lang.org/learn.html'>Learn</a></li><li><a
href='https://groovy-lang.org/documentation.html'>Documentation</a></li><li><a
href='/download.html'>Download</a></li><li><a
href='https://groovy-lang.org/support.html'>Support</a></li><li><a
href='/'>Contribute</a></li><li><a
href='https://groovy-lang.org/ecosystem.html'>Ecosystem</a></li><li><a
href='/blog'>Blog posts</a></li><li><a
href='https://groovy.apache.org/events.ht [...]
+ </ul>
+ </div><div class='col-2'>
+ <h1>About</h1><ul>
+ <li><a
href='https://github.com/apache/groovy'>Source code</a></li><li><a
href='https://groovy-lang.org/security.html'>Security</a></li><li><a
href='https://groovy-lang.org/learn.html#books'>Books</a></li><li><a
href='https://groovy-lang.org/thanks.html'>Thanks</a></li><li><a
href='http://www.apache.org/foundation/sponsorship.html'>Sponsorship</a></li><li><a
href='https://groovy-lang.org/faq.html'>FAQ</a></li><li><a
href='https://groovy-lang.or [...]
+ </ul>
+ </div><div class='col-3'>
+ <h1>Socialize</h1><ul>
+ <li><a
href='https://groovy-lang.org/mailing-lists.html'>Discuss on the mailing
list</a></li><li><a href='https://x.com/ApacheGroovy'>Groovy on
X</a></li><li><a href='https://bsky.app/profile/groovy.apache.org'>Groovy on
Bluesky</a></li><li><a href='https://fosstodon.org/@ApacheGroovy'>Groovy on
Mastodon</a></li><li><a
href='https://www.linkedin.com/company/106402668/admin/dashboard/'>Groovy on
LinkedIn</a></li><li><a href='https://groovy-lang. [...]
+ </ul>
+ </div><div class='col-right'>
+ <p>
+ The Groovy programming language is
supported by the <a href='https://www.apache.org'>Apache Software
Foundation</a> and the Groovy community.
+ </p><div text-align='right'>
+ <img
src='https://www.apache.org/img/asf_logo.png' title='The Apache Software
Foundation' alt='The Apache Software Foundation' style='width:60%'/>
+ </div><p>Apache, Apache Groovy,
Groovy, and the ASF logo are either registered trademarks or trademarks of The
Apache Software Foundation.</p>
+ </div>
+ </div><div class='clearfix'>© 2003-2026
the Apache Groovy project — Groovy is Open Source: <a
href='https://www.apache.org/licenses/LICENSE-2.0.html' alt='Apache 2
License'>license</a>, <a
href='https://privacy.apache.org/policies/privacy-policy-public.html'>privacy
policy</a>.</div>
+ </div>
+ </footer></div>
+ </div>
+ </div>
+ </div>
+ </div><script src='../js/vendor/jquery-1.10.2.min.js'
defer></script><script src='../js/vendor/classie.js' defer></script><script
src='../js/vendor/bootstrap.js' defer></script><script
src='../js/vendor/sidebarEffects.js' defer></script><script
src='../js/vendor/modernizr-2.6.2.min.js' defer></script><script
src='../js/plugins.js' defer></script><script
src='../js/vendor/prettify.min.js'></script><script>document.addEventListener('DOMContentLoaded',prettyPrint)</script>
+</body></html>
\ No newline at end of file
diff --git a/blog/index.html b/blog/index.html
index 56fd109..a434a88 100644
--- a/blog/index.html
+++ b/blog/index.html
@@ -59,7 +59,7 @@
</ul>
</div>
</div>
- </div><div id='content' class='page-1'><div
class='row'><div class='row-fluid'><div class='col-lg-3' id='blog-index'><ul
class='nav-sidebar list'><li class='active'><a
href='/blog/'>Blogs</a></li><li><a href='loop-invariants'>Design by contract
with Groovy™: loop invariants</a></li><li><a
href='groovy-graph-databases'>Using Graph Databases with
Groovy™</a></li><li><a href='fruity-eclipse-grouping'>Grouping Fruity
Collections</a></li><li><a href='groovy [...]
+ </div><div id='content' class='page-1'><div
class='row'><div class='row-fluid'><div class='col-lg-3' id='blog-index'><ul
class='nav-sidebar list'><li class='active'><a
href='/blog/'>Blogs</a></li><li><a href='loop-invariants'>Design by contract
with Groovy™: loop invariants</a></li><li><a
href='groovy-graph-databases'>Using Graph Databases with
Groovy™</a></li><li><a href='fruity-eclipse-grouping'>Grouping Fruity
Collections</a></li><li><a href='groovy [...]
<div class='row'>
<div class='colset-3-footer'>
<div class='col-1'>
diff --git a/blog/loop-invariants.html b/blog/loop-invariants.html
index 14f1cc8..8881d4e 100644
--- a/blog/loop-invariants.html
+++ b/blog/loop-invariants.html
@@ -59,7 +59,13 @@
</ul>
</div>
</div>
- </div><div id='content' class='page-1'><div
class='row'><div class='row-fluid'><div class='col-lg-3'><ul
class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a
href='#doc'>Design by contract with Groovy™: loop
invariants</a></li><li><a href='#_introduction'
class='anchor-link'>Introduction</a></li><li><a
href='#_the_dafny_example_multiply_by_repeated_addition'
class='anchor-link'>The Dafny example: multiply by repeated addition</a></li
[...]
+ </div><div id='content' class='page-1'><div
class='row'><div class='row-fluid'><div class='col-lg-3'><ul
class='nav-sidebar'><li><a href='./'>Blog index</a></li><li class='active'><a
href='#doc'>Design by contract with Groovy™: loop
invariants</a></li><li><a href='#_introduction'
class='anchor-link'>Introduction</a></li><li><a
href='#_the_dafny_example_multiply_by_repeated_addition'
class='anchor-link'>The Dafny example: multiply by repeated addition</a></li
[...]
+<a href="https://github.com/paulk-asert/" target="_blank" rel="noopener
noreferrer"><img style="border-radius:50%;height:48px;width:auto"
src="img/paulk-asert.png" alt="Paul King"></a>
+<div style="display:grid;align-items:center;margin:0.1ex;padding:0ex">
+ <div><a href="https://github.com/paulk-asert/" target="_blank" rel="noopener
noreferrer"><span>Paul King</span></a></div>
+ <div><small><i>PMC Member</i></small></div>
+</div>
+ </div><br/><span>Published: 2026-03-24 04:30PM</span></p><hr/><div
class="sect1">
<h2 id="_introduction">Introduction</h2>
<div class="sectionbody">
<div class="paragraph">
diff --git a/search/search-index.json b/search/search-index.json
index 1a3f3ef..80b06b9 100644
--- a/search/search-index.json
+++ b/search/search-index.json
@@ -149,7 +149,7 @@
{
"id": "blog/loop-invariants.html",
"title": "The Apache Groovy programming language - Blogs - Design by
contract with Groovy™: loop invariants",
- "content": "The Apache Groovy programming language - Blogs - Design by
contract with Groovy™: loop invariants Socialize Discuss on the mailing
list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events
and conferences Source code on GitHub Report issues in Jira Stack Overflow
questions Slack Community You are using an outdated browser. Please upgrade
your browser to improve your experience. Apache Groovy™ Learn
Documentation Download Support Contr [...]
+ "content": "The Apache Groovy programming language - Blogs - Design by
contract with Groovy™: loop invariants Socialize Discuss on the mailing
list Groovy on X Groovy on Bluesky Groovy on Mastodon Groovy on LinkedIn Events
and conferences Source code on GitHub Report issues in Jira Stack Overflow
questions Slack Community You are using an outdated browser. Please upgrade
your browser to improve your experience. Apache Groovy™ Learn
Documentation Download Support Contr [...]
"url": "blog/loop-invariants.html",
"site": "dev"
},
@@ -251,6 +251,13 @@
"url": "blog/groovy-2-5-7-released.html",
"site": "dev"
},
+ {
+ "id": "blog/groovy-async-await.html",
+ "title": "The Apache Groovy programming language - Blogs - Async/await
for Groovy",
+ "content": "The Apache Groovy programming language - Blogs -
Async/await for Groovy Socialize Discuss on the mailing list Groovy on X Groovy
on Bluesky Groovy on Mastodon Groovy on LinkedIn Events and conferences Source
code on GitHub Report issues in Jira Stack Overflow questions Slack Community
You are using an outdated browser. Please upgrade your browser to improve your
experience. Apache Groovy™ Learn Documentation Download Support
Contribute Ecosystem Blog posts Socia [...]
+ "url": "blog/groovy-async-await.html",
+ "site": "dev"
+ },
{
"id": "blog/netbeans.html",
"title": "The Apache Groovy programming language - Blogs - Using
Apache NetBeans with Apache Groovy™",
@@ -681,7 +688,7 @@
{
"id": "blog/index.html",
"title": "The Apache Groovy programming language - Blogs",
- "content": "The Apache Groovy programming language - Blogs Socialize
Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon
Groovy on LinkedIn Events and conferences Source code on GitHub Report issues
in Jira Stack Overflow questions Slack Community You are using an outdated
browser. Please upgrade your browser to improve your experience. Apache
Groovy™ Learn Documentation Download Support Contribute Ecosystem Blog
posts Socialize Blogs Design by cont [...]
+ "content": "The Apache Groovy programming language - Blogs Socialize
Discuss on the mailing list Groovy on X Groovy on Bluesky Groovy on Mastodon
Groovy on LinkedIn Events and conferences Source code on GitHub Report issues
in Jira Stack Overflow questions Slack Community You are using an outdated
browser. Please upgrade your browser to improve your experience. Apache
Groovy™ Learn Documentation Download Support Contribute Ecosystem Blog
posts Socialize Blogs Design by cont [...]
"url": "blog/index.html",
"site": "dev"
},