blob: 3e4acc30b936a52b022c6782fb96bcc6a5e157b2 [file] [log] [blame]
<!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='groovy, asf, apachecon, communityovercode'/><meta name='description' content='This post looks at the ASF Community Over Code conference in Halifax, Nova Scotia, October 7-10 2023, with a particular focus on the Groovy Track.'/><title>The Apache Groovy programming language - Blogs - Community Over Code (North America) 2023</title><link href='../img/favicon.ico' type='image/x-ico' rel='icon'/><link rel='stylesheet' type='text/css' href='../css/bootstrap.css'/><link rel='stylesheet' type='text/css' href='../css/font-awesome.min.css'/><link rel='stylesheet' type='text/css' href='../css/style.css'/><link rel='stylesheet' type='text/css' href='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.css'/>
</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-envelope'></span> Discuss on the mailing-list</a>
</li><li>
<a href='https://twitter.com/ApacheGroovy' class='icon'><span class='fa fa-twitter'></span> Groovy on Twitter</a>
</li><li>
<a href='https://groovy-lang.org/events.html' class='icon'><span class='fa fa-calendar'></span> Events and conferences</a>
</li><li>
<a href='https://github.com/apache/groovy' class='icon'><span class='fa 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-bug'></span> Report issues in Jira</a>
</li><li>
<a href='http://stackoverflow.com/questions/tagged/groovy' class='icon'><span class='fa fa-stack-overflow'></span> Stack Overflow questions</a>
</li><li>
<a href='http://groovycommunity.com/' class='icon'><span class='fa 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 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 posts</a></li><li class=''><a href='https://groovy.apache.org/events.html'></a></li><li>
<a data-effect='st-effect-9' class='st-trigger' href='#'>Socialize</a>
</li><li class=''>
<a href='../search.html'>
<i class='fa fa-search'></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'>Community Over Code (North America) 2023</a></li><li><a href='#_upon_arrival' class='anchor-link'>Upon arrival</a></li><li><a href='#_the_groovy_track' class='anchor-link'>The Groovy Track</a></li><li><a href='#_other_tracks' class='anchor-link'>Other tracks</a></li><li><a href='#_an_evening_at_the_citadel' class='anchor-link'>An evening at the Citadel</a></li><li><a href='#_but_wait_theres_more' class='anchor-link'>But wait, there&#8217;s more&#8230;&#8203;</a></li><li><a href='#_back_home' class='anchor-link'>Back home</a></li><li><a href='#_other_information' class='anchor-link'>Other information</a></li></ul><br/><ul class='nav-sidebar'><li style='padding: 0.35em 0.625em; background-color: #eee'><span>Related posts</span></li><li><a href='./apache-groovy-2022-year-in'>Apache Groovy 2022 Year In Review</a></li></ul></div><div class='col-lg-8 col-lg-pull-0'><a name='doc'></a><h1>Community Over Code (North America) 2023</h1><p><span>Author: <i>Paul King</i></span><br/><span>Published: 2023-10-26 05:00PM</span></p><hr/><div id="preamble">
<div class="sectionbody">
<div class="paragraph">
<p>This year&#8217;s North American edition of the ASF conference, <a href="https://communityovercode.org/">Community Over Code</a>,
featured four in-person days of sessions (October 7-10) at the Halifax Convention Centre.</p>
</div>
<div class="admonitionblock note">
<table>
<tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">
The presentation slides and audio/video (where available) are still being added onto the conference site.
If additional material becomes available, this post will be updated with links to the additional content.
</td>
</tr>
</table>
</div>
<div class="paragraph">
<p>This post gives an update on the conference. It is mostly a focus on the Groovy track,
but there is also material about other tracks and the many other aspects of the conference.
In particular, hopefully, this post gives you some insight into why going to conferences,
and the ASF conferences in particular, can be a rewarding experience. I hope to see you at
a future conference.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_upon_arrival">Upon arrival</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Before getting into the conference report proper, just a pro-tip for anyone travelling
to conferences from more than a few time-zones away. If you base your knowledge just on viewing
social media, regular speaking at conferences may look like a glamorous life, but without a little
bit of planning, you may see little more than the inside of planes, hotels, and conference rooms.
It pays to allocate some time to seeing the host city/country. If you also get some sun on the
first day you arrive (or first full day after you arrive if arriving at night), it seems to help
with getting over jet lag.
In my case, I took the opportunity to do a bicycle ride East of Halifax mostly along some
cyclist-friendly bike trails.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/HalifaxRideMap.png" alt="HalifaxRideMap"></span></p>
</div>
<div class="paragraph">
<p>The route was 90% on trails built upon now disused railroad tracks
which form part of the <a href="https://tctrail.ca/">Trans Canada Trail</a>.
It is further broken down into smaller sections including
the <a href="https://www.alltrails.com/trail/canada/nova-scotia/shearwater-flyer-trail">Shearwater Flyer Trail</a>,
the <a href="https://www.alltrails.com/trail/canada/nova-scotia/salt-marsh-trail">Salt Marsh Trail</a>,
the <a href="https://www.alltrails.com/trail/canada/nova-scotia/atlantic-view-trail">Atlantic View Trail</a>,
and the <a href="https://www.alltrails.com/trail/canada/nova-scotia/dartmouth-waterfront-trail">Dartmouth Waterfront Trail</a>.
The place I hired the bike from recommended riding to <a href="https://parks.novascotia.ca/park/lawrencetown-beach">Lawrencetown Beach</a>, but I went just a little further for good measure.
The views were spectacular. I particularly like some of the autumn color scenery which is seldom seen
where I live.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/HalifaxRideCollage.jpg" alt="HalifaxRideCollage"></span></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_the_groovy_track">The Groovy Track</h2>
<div class="sectionbody">
<div class="paragraph">
<p><span class="image right"><img src="https://photos.apachecon.com/_data/i/upload/2023/10/20/20231020033313-d56c0136-me.jpg" alt="stickers" width="200"></span></p>
</div>
<div class="paragraph">
<p>The Groovy track was spread over the first two days of the conference and had ten sessions
as well as a <em>birds-of-a-feather</em> session after the first day.
The sessions typically had mini-themes: Groovy update, for Java developers, Kubernetes and Groovy,
Groovy and Data Science (this year featuring Apache Ignite) and so on.
Here we&#8217;ll just look at a few highlights of each talk. You are encouraged to peruse
the slides and other content if you want more details.</p>
</div>
<div class="sect2">
<h3 id="_groovy_update">Groovy update</h3>
<div class="paragraph">
<p>The first two talks covered the state of the Groovy project with also some updates
from the broader Groovy ecosystem.</p>
</div>
<div class="paragraph">
<p><span class="image right"><img src="https://photos.apachecon.com/_data/i/upload/2023/10/12/20231012195704-e8e8482f-me.jpg" alt="Paul King" width="150"></span>
The first talk was <a href="https://speakerdeck.com/paulk/groovy-roadmap">Groovy and Groovy Ecosystem Update</a>.
This talked about the status of the Groovy project itself as well as some important projects
within the broader Groovy ecosystem.</p>
</div>
<div class="paragraph">
<p>Some highlights:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Groovy downloads recently surpassed the 3 billion mark in total and is currently tracking just over
3 million downloads per day on average.</p>
</li>
<li>
<p>Groovy already supports classes and scripts but with JEP 445 scripting on the way in Java (preview in JDK21),
Groovy 5 supports additional forms so that JEP 445 code examples will run straight in Groovy (for JDK11+).</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">def main() {
println 'Hello world!'
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>There are variations that remain strictly JEP 445 compatible (to gain the same bytecode simplifications)
and variations which retain Groovy&#8217;s extra features like access to the script binding and context.
The <code>run</code> method is used instead of the <code>main</code> method to gain the traditional Groovy script features.
An added bonus is that Groovy&#8217;s <code>@Field</code> annotation isn&#8217;t needed to designate fields within JEP 445-like scripts.
Here is another example, this one using Jackson data binding to serialize itself as a JSON file:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">@JsonIgnoreProperties(["binding"])
def run() {
var mapper = new ObjectMapper()
assert mapper.writeValueAsString(this) == '{"pets":["cat","dog"]}'
}
public pets = ['cat', 'dog']</code></pre>
</div>
</div>
</li>
<li>
<p>Groovy added support for "underscore as a placeholder" functionality. This is similar to JEP 443 (preview in JDK21) but Groovy also adds the feature for Closures and multi-assignment expressions.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">var (_, y, m, _, _, d) = Calendar.instance
println "Today is $y-${m+1}-$d" // Today is 2023-8-23</code></pre>
</div>
</div>
</li>
<li>
<p>An additional <code>@OperatorRename</code> AST transform is now available which makes it easier to use
a multitude of libraries with Groovy&#8217;s operator overloading. This is handy when working with
libraries that might manipulate complex numbers, matrices, or fractions (as per the example below
which uses the Apache Commons Numbers Fraction library).
Previously, you may have forgone using the operator overloading shortcuts,
or you (or someone else) would have possibly written some Groovy specific
extension methods to provide the nicer operator overloading syntactic sugar for a particular library
of interest. Now, such libraries can now easily be used straight out-of-the-box
with the operator overloading feature.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">@OperatorRename(plus='add')
def testAddOfTwoFractions() {
var half = Fraction.of(1, 2)
var third = Fraction.of(1, 3)
assert half.add(third) == Fraction.of(5, 6) // old style still works
assert half + third == Fraction.of(5, 6) // fraction '+' operator!
}</code></pre>
</div>
</div>
</li>
<li>
<p>Grails 6 was recently released with support for recent versions of Groovy 3.</p>
</li>
<li>
<p>Micronaut 4 was recently released with support for recent versions of Groovy 4.</p>
</li>
<li>
<p>Geb 7 and several versions of the Spock testing framework also support Groovy 4.</p>
</li>
<li>
<p>The latest version of the Deep Netts deep learning library works well when using
Groovy 5 with GraalVM.</p>
</li>
<li>
<p>The latest version of Apache Ignite works well with Groovy 5 when scaling up
your distributed data, distributed compute, and distributed data science applications.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The second talk was <a href="https://speakerdeck.com/paulk/groovy-today">Why use Groovy in 2023</a>?
This discussed the features that make Groovy a compelling language choice even given the
wonderful progress being made in other languages within the JDK ecosystem.</p>
</div>
<div class="paragraph">
<p>Some highlights:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Groovy is compelling if you need its dynamic features like runtime metaprogramming,
lifecycle hooks, and dynamic builders.</p>
</li>
<li>
<p>Groovy also offers features like ranges, default parameters, named arguments,
command chains, operator overloading, extensible tooling including an
extensible type checker.</p>
</li>
<li>
<p>As well as its own native features, Groovy 5 provides about 2000 extension
methods for around 150 Java classes.</p>
</li>
<li>
<p>Traits provide similar functionality to default methods in interfaces but rather
than just tackling the problem of API evolution, traits are a more ambitious and
powerful OO feature. Groovy offers stateful traits, more powerful method selection
options, offers trait application at runtime (dynamic traits) and supports the
stackable traits pattern like Scala.</p>
</li>
<li>
<p>Groovy&#8217;s Closure abstraction offers several powerful mechanisms over and above
what lambdas offer including memoization and tail call recursion handling.
You can write factorial in a more natural recursive form (avoiding an explicitly
imperative algorithm) and not suffer from stack overflow issues.
You can write recursive fibonacci algorithms that take milliseconds
to execute rather than the trillions of years a naïve recursive algorithm would take.</p>
</li>
<li>
<p>AST transforms (based around annotations) and
macro methods (which are similar but look like methods calls)
allow a declarative style of programming where a few lines of code
can be replaced with hundreds or thousands of lines of equivalent code.
The generated code follows best practice and is much less error-prone.
Groovy 5 has 80+ AST transforms.</p>
</li>
<li>
<p>Language integrated queries allow a SQL-like style for querying data.</p>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">GQ {
from fruit in ['Apple', 'Apricot', 'Banana', 'Cantaloupe']
groupby fruit[0] as firstChar
select firstChar, list(fruit.toUpperCase()) as fruit_list
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>which yields:</p>
</div>
<div class="listingblock">
<div class="content">
<pre>+-----------+------------------+
| firstChar | fruit_list |
+-----------+------------------+
| A | [APPLE, APRICOT] |
| B | [BANANA] |
| C | [CANTALOUPE] |
+-----------+------------------+</pre>
</div>
</div>
</li>
<li>
<p>While we like, many of the exciting changes for switch expressions coming along with
recent Java versions, Groovy still provides numerous additional options (for JDK8+):
<span class="image"><img src="img/Groovy2023Switch.png" alt="Groovy switch expressions"></span></p>
</li>
<li>
<p>Groovy gives you the choice of emulated records for JDK8+
or native records for JDK16+ with many record enhancements:
<span class="image"><img src="img/Groovy2023Records.png" alt="Groovy records"></span>
Over and above the built-in enhancements, record development is made
easier by Groovy&#8217;s AST transforms. The slides have examples of combining
records with the following AST transforms:
<code>@PropertyOptions</code>, <code>@ToString</code>, <code>@Memoized</code>, <code>@Builder</code>,
<code>@Requires</code>, <code>@Sortable</code>, <code>@Newify</code>, and <code>@OperatorRename</code>.
But of course, you aren&#8217;t limited to just that list.</p>
</li>
</ul>
</div>
</div>
<div class="sect2">
<h3 id="_groovy_for_java_developers">Groovy for Java developers</h3>
<div class="paragraph">
<p>The next two talks were aimed at Java developers who wanted to understand how
they could use Groovy for their development or testing needs.</p>
</div>
<div class="paragraph">
<p><span class="image right"><img src="https://photos.apachecon.com/_data/i/upload/2023/10/12/20231012200013-649bb746-me.jpg" alt="Jeff Scott Brown" width="200"></span></p>
</div>
<div class="paragraph">
<p>The next talk was by <a href="https://www.linkedin.com/in/jeffscottbrown/">Jeff Scott Brown</a> on
<em>Groovy for Java Developers</em>. Jeff covered a range of topics including:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>Groovy optional typing</p>
</li>
<li>
<p>Groovy properties</p>
</li>
<li>
<p>Groovy script syntax</p>
</li>
<li>
<p>Evolving Java source to Groovy</p>
</li>
<li>
<p>Special features of Groovy</p>
</li>
<li>
<p>Groovy extension methods for Groovy and Java classes</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>The next talk was
<a href="https://speakerdeck.com/paulk/property-based-testing">Testing your Java with Groovy, Spock, JUnit5, Jacoco, Jqwik and Pitest</a>.
This talk covered a common scenario of using Groovy tests with Java production code, though most of the content
is applicable for production code in other JVM languages (including Groovy!) too.
It also showed examples of a few advanced tools you might want to consider as part of your testing toolkit.</p>
</div>
<div class="paragraph">
<p>The central example for the talk was based around what initially appears to be a very
simple mathematical calculation originally implemented using the following Java code:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava1.png" alt="Buggy code" width="80%"></span></p>
</div>
<div class="paragraph">
<p>We write a Groovy test using the <a href="https://spockframework.org/">Spock</a> testing framework which
at first glance seems to indicate our initial implementation is correct since all the tests
pass and we have 100% test coverage.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava2.png" alt="Code coverage" width="90%"></span></p>
</div>
<div class="paragraph">
<p>But this is 100% line and branch coverage but doesn&#8217;t reflect 100% state coverage.
We can illustrate this by adding one more test case, which now fails:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava3.png" alt="Add fault revealing test case" width="90%"></span></p>
</div>
<div class="paragraph">
<p>It turns out there was one edge case the initial implementation didn&#8217;t cater
for but it is simple enough to fix:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava4.png" alt="Corrected algorithm" width="90%"></span></p>
</div>
<div class="paragraph">
<p>We now have all test cases passing and still 100% coverage.</p>
</div>
<div class="paragraph">
<p>The moral of the story is that 100% line and branch coverage isn&#8217;t sufficient
to ensure a correct implementation. You should try to add test cases until
you think the problem domain is fully tested. The rest of the talk looked
at two advanced tools which could assist you in finding test case deficiencies.</p>
</div>
<div class="paragraph">
<p>The <a href="https://pitest.org/">Pitest tool</a> is a mutation testing tool.
Understanding how it works and how it can help is a little mind-bending at first.
Pitest mutates your production code and then re-runs your test suite.
If the test suite still passes, i.e. the mutant survives, it represents a possible code smell.</p>
</div>
<div class="paragraph">
<p>Often it means that your test suite isn&#8217;t complete enough to kill the mutant,
and you should add some more test cases.
But mutation testing is not an exact science, if a mutant survives,
it could mean there is a missing test case,
it could mean there is a flaw in the existing test cases,
it could mean there is a bug in the implementation code,
or it could be a false positive.</p>
</div>
<div class="paragraph">
<p>Running the tool on the faulty implementation when we had 3 test cases,
indeed reveals some surviving mutations and analysis indicates that indeed the mutations
correspond to the faulty edge case:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava5.png" alt="Pitest result" width="90%"></span></p>
</div>
<div class="paragraph">
<p>This should direct us to add the additional test case like we did manually earlier
and this would hopefully have forced us to discover the bug.</p>
</div>
<div class="paragraph">
<p>Running the tool on the fixed implementation showed an improvement
but still indicated a possible code smell. That finding reflects that
for our fixed implementation, that <code>c &gt; Math.min(a, b)</code> and <code>c &gt;= Math.min(a, b)</code>
are equivalent, even though in the general case it might mean
an edge case wasn&#8217;t being tested. So mutation testing can certainly be
useful but often requires human analysis to rule out any false positives.</p>
</div>
<div class="paragraph">
<p>The other tool examined was <a href="https://jqwik.net/">Jqwik</a>, a property-based testing tool.
Such tools check that certain properties hold when exercising the implementation
under test with random data. Indeed, such testing also reveals the flaw in the
original code, with no flaw found in the fixed code.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/TestingJava6.png" alt="Jqwik result" width="90%"></span></p>
</div>
</div>
<div class="sect2">
<h3 id="_kubernetes_and_groovy">Kubernetes and Groovy</h3>
<div class="paragraph">
<p>The next mini-theme in the Groovy track was Kubernetes and Groovy.
<span class="image right"><img src="https://photos.apachecon.com/_data/i/upload/2023/10/12/20231012200925-e882ed51-me.jpg" alt="Jorge Aguilera" width="200"></span></p>
</div>
<div class="paragraph">
<p>The first talk was by <a href="https://jvm.social/@jorge">Jorge Aguilera</a>: <em>It works on my cluster. Deploying a groovy kubernetes application to Okteto.</em>
<a href="https://communityovercode.files.wordpress.com/2023/10/sat_groovy_it_works_on_my_cluster-jorge.pdf">Slides</a></p>
</div>
<div class="paragraph">
<p>In this talk, Jorge showed a
<a href="https://groovy-lang.org/">Groovy</a>
<a href="https://micronaut.io/">Micronaut</a>
<a href="https://kubernetes.io/">Kubernetes</a> (k8s) application deployed in the cloud.
It was deployed to the Okteto platform, so that in fact most of the k8s details were taken
care of by the platform.</p>
</div>
<div class="paragraph">
<p>The sample application was a simple solution to the
<a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Collatz conjecture</a>.
I remember studying this back in my Uni days but had forgotten the details.
Basically, given a starting number, one of two calculations is performed,
depending on whether the current number is even.
Odd numbers are multiplied by 3 and then 1 is added, even numbers are divided by 2.
This is stopped if the result becomes the number 1, but otherwise continues.
The conjecture is that eventually, the calculation terminates, i.e. it always eventually equals 1.</p>
</div>
<div class="paragraph">
<p>Of interest is the number of cycles needed to get to 1.
Here is an algorithm that returns the number of cycles:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">class Collatz {
static long getAt(BigInteger n) {
var result = n
var count = 0L
while (result != 1G) {
if (result % 2G == 0G) {
result /= 2G
} else {
result *= 3G
result++
}
count++
}
count
}
}</code></pre>
</div>
</div>
<div class="paragraph">
<p>We used a static <code>getAt</code> method to give us a neat shorthand for getting the result.
We can test out some of the example sequences mentioned in the <a href="https://en.wikipedia.org/wiki/Collatz_conjecture">Wikipedia page</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">assert Collatz[12] == 9
assert Collatz[19] == 20
assert Collatz[27] == 111</code></pre>
</div>
</div>
<div class="paragraph">
<p>Now, to create our microservice based around this algorithm.
We can create a fully working (but skeleton) project for Micronaut in a number
of ways. Here, is what is needed from the command-line:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code>mn create-app \
--features kubernetes \
--features postgres \
--features jdbc-data \
--lang groovy collatz</code></pre>
</div>
</div>
<div class="paragraph">
<p>We&#8217;ve shown some example features you might want to use.
You could add further features depending on your application&#8217;s needs.</p>
</div>
<div class="paragraph">
<p>We can change the skeleton controller to have our desired functionality:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">@Controller
...
@Get('{n}')
Map index(BigInteger n) {
[n: n, count: Collatz[n]]
}
...</code></pre>
</div>
</div>
<div class="paragraph">
<p>Jorge then went on to explain the k8s configuration details and gave a demonstration
deploying the application.</p>
</div>
<div class="paragraph">
<p>Jorge also presented the next talk: <a href="https://communityovercode.files.wordpress.com/2023/10/sat_groovy_let_groovy_operate_your_cluster-jorge.pdf">Let Groovy operate your k8s cluster</a>.
This dived into more k8s details. He showed how to write a swagger-operator in Groovy
which removed the need for tedious manual steps when deploying k8s applications.
The operator monitors our services, rewrites the configmap if needed and restarts the pod.</p>
</div>
<div class="paragraph">
<p>The operator itself was written in <a href="https://micronaut.io/">Micronaut</a>:</p>
</div>
<div class="listingblock">
<div class="content">
<pre class="prettyprint highlight"><code data-lang="groovy">@Operator(
informer = @Informer(
apiType = V1Swagger,
apiListType = V1SwaggerList,
apiGroup = V1SwaggerWrapper.GROUP,
resourcePlural = V1SwaggerWrapper.PLURAL,
resyncCheckPeriod = 10000L)
)
class SwaggerOperator implements ResourceReconciler&lt;V1Swagger&gt;{
}</code></pre>
</div>
</div>
</div>
<div class="sect2">
<h3 id="_apache_groovy_and_apache_ignite">Apache Groovy and Apache Ignite</h3>
<div class="paragraph">
<p>The next mini-theme was Groovy and Data Science. Groovy has been described
as the Python equivalent for the JVM and Groovy works well with many of the ASF
frameworks and technologies related to data science and big data in general.</p>
</div>
<div class="paragraph">
<p>This year the Groovy track&#8217;s data science content had a particular focus on
scaling up your data science applications,
and your data and compute applications in general,
using <a href="https://ignite.apache.org/">Apache Ignite</a>.</p>
</div>
<div class="paragraph">
<p>The first talk was <a href="https://speakerdeck.com/paulk/whisky-clustering-groovy-ignite">Whisky Clustering with Apache Groovy and Apache Ignite</a>. This was a case study looking at how to cluster
86 single malt scotch whiskies.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/Clustering0.png" alt="Whiskey flavour profiles"></span></p>
</div>
<div class="paragraph">
<p>There are different algorithms that can be used to do the clustering.
Here K-Means clustering was used.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/Clustering1.png" alt="The k-means algorithm"></span></p>
</div>
<div class="paragraph">
<p>For this particular dataset, the number of datapoints is relatively small
and scaling up isn&#8217;t crucial. But larger datasets would be split up in the same way
so we&#8217;ll look at how we&#8217;d scale this up. First we read in the data:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/Clustering2.png" alt="Whiskey flavour profiles"></span></p>
</div>
<div class="paragraph">
<p>Apache Ignite has special features for reading in data within a cluster environment,
but we can get by using Apache Commons CSV for our example.</p>
</div>
<div class="paragraph">
<p>If you know the K-Means algorithm, at first glance it doesn&#8217;t appear amenable to
distribution. To cluster points you need to calculate distances of <em>all</em> the points
to your centroids. Luckily, various distributed versions of the algorithm have been
devised and this is what is included in the <code>ignite-ml</code> library. We just use the library
in the same way we&#8217;d use a non-distributed version and Ignite does the hard work for you.
Here is the result:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/Clustering3.png" alt="Whiskey flavour profiles"></span></p>
</div>
<div class="paragraph">
<p>There are various options we have to tweak the algorithm and various
ways to visualize the results.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/Clustering4.png" alt="Whiskey flavour profiles"></span></p>
</div>
<div class="paragraph">
<p>As a side note, it is rumoured that additional extensive research on this topic may (or may not)
have been held in conjunction with the conference. Only because the conference was in (Nova) Scotia no doubt!
<span class="image"><img src="img/HalifaxWhisky.png" alt="Citadel"></span></p>
</div>
<div class="paragraph">
<p><span class="image right"><img src="https://photos.apachecon.com/_data/i/upload/2023/10/13/20231013192401-65a58458-cu_s9999x410.jpg" alt="Jeremy Meyer" width="200"></span>
The second talk was by <a href="https://www.linkedin.com/in/jeremy-s-meyer/">Jeremy Meyer</a> discussing
<a href="https://drive.google.com/file/d/1vjDkFmG9zz9y7yDY10ru9tya7KidJsqG/view?usp=sharing">Scalable Distributed Computing with Groovy Using Apache Ignite</a>.</p>
</div>
<div class="paragraph">
<p>In this talk, Jeremy posed the question:</p>
</div>
<div class="quoteblock">
<blockquote>
What if we used the dynamic, easy to code and prototype aspects of Groovy&#8230;&#8203;<br>
&#8230;&#8203;with the fantastically scalable compute power of Apache Ignite&#8217;s
compute grid, and clever peer class loading?
</blockquote>
</div>
<div class="paragraph">
<p>For those that know Ignite, it can be used in numerous ways:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks1.png" alt="Ignite" width="90%"></span></p>
</div>
<div class="paragraph">
<p>In this scenario, it was going to be used for distributed computing
and the task at hand was to solve Rubik&#8217;s cubes. In this case,
particular non-destructive corner moves of a 3x3x2 cube.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks2.png" alt="Numbers" width="90%"></span></p>
</div>
<div class="paragraph">
<p>First up was to create a little domain model to represent the cube:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks3.png" alt="Model" width="90%"></span></p>
</div>
<div class="paragraph">
<p>Then piece together a cluster of computers of varying skills for the compute grid:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks4.png" alt="Team" width="90%"></span></p>
</div>
<div class="paragraph">
<p>Or a different visualization of the machines if you&#8217;re not
a Guardians of the Galaxy fan:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks5.png" alt="Machines" width="90%"></span></p>
</div>
<div class="paragraph">
<p>Then code up the corner swapping algorithm:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks6.png" alt="Algorithm" width="90%"></span></p>
</div>
<div class="paragraph">
<p>And finally get the results:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/IgniteRubiks7.png" alt="Results" width="90%"></span></p>
</div>
<div class="paragraph">
<p>I won&#8217;t steal Jeremy&#8217;s thunder. Check out the link for details.
But a lesson learned is that naively allocating work to machines of
differing capabilities can sometimes yield surprising results.
Luckily, there are various ways that compute grids job allocation
can account for such variations.</p>
</div>
</div>
<div class="sect2">
<h3 id="_miscellaneous">Miscellaneous</h3>
<div class="paragraph">
<p>Jeff gave another talk, this time on <em>GORM Data Services</em>.
First covered was the traditional GORM functionality including dynamic finders,
the Criteria API, Where queries, and HQL:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/GORM1.png" alt="1"></span></p>
</div>
<div class="paragraph">
<p>Then he covered GORM Data Services:</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/GORM2.png" alt="2"></span></p>
</div>
<div class="paragraph">
<p><span class="image right"><img src="img/JeffOpenSourceSoftwareAndYou.jpg" alt="Jeff Scott Brown" width="300"></span>
Jeff also gave the final talk for the track: <em>Open Source Software and You</em>.
In this talk, Jeff gave an insight into his own open source journey.
He covered some of his insights from his 30+ years working in open source.
Discussing why you might want to contribute to open source, and how you could contribute.
His journey gives us all some inspiration for anyone starting
or continuing on their own open source journeys.</p>
</div>
<div class="paragraph">
<p>Jeff covered some of his early projects. He went on to discuss Grails
which was a key driver during Groovy&#8217;s early evolution.
He also reiterated the continuing investment Unity Foundation
is making towards the Grails foundation and Micronaut foundation - two technologies
which are very well known to many Groovy users.
He also discussed some of Unity Foundation&#8217;s recent projects
which target applying open source to help underserved communities.</p>
</div>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_other_tracks">Other tracks</h2>
<div class="sectionbody">
<div class="paragraph">
<p>In addition to the Groovy track, the conference was full of other fascinating content too,
grouped into the following tracks:</p>
</div>
<div class="ulist">
<ul>
<li>
<p>API/Microservices Track</p>
</li>
<li>
<p>Big Data: Compute Track</p>
</li>
<li>
<p>Big Data: Storage Track</p>
</li>
<li>
<p>Cloud and Runtime Track</p>
</li>
<li>
<p>Community Track</p>
</li>
<li>
<p>Content Wrangling Track</p>
</li>
<li>
<p>Data Engineering Track</p>
</li>
<li>
<p>Fintech Track</p>
</li>
<li>
<p>Frameworks Track</p>
</li>
<li>
<p>Geospatial Track</p>
</li>
<li>
<p>Highlights Track</p>
</li>
<li>
<p>Incubator Track</p>
</li>
<li>
<p>Internet of Things Track</p>
</li>
<li>
<p>Performance Engineering Track</p>
</li>
<li>
<p>Search Track</p>
</li>
<li>
<p>Serverside Chat with ASF Infra</p>
</li>
<li>
<p>Streaming Track</p>
</li>
<li>
<p>Sustainability Track</p>
</li>
<li>
<p>Tomcat and httpd Track</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>I did manage to see quite a few talks from some of the
other tracks but instead of trying to summarise everything I saw,
I&#8217;ll point you to the online content which is being linked to the conference
<a href="https://communityovercode.org/schedule/">schedule</a>.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_an_evening_at_the_citadel">An evening at the Citadel</h2>
<div class="sectionbody">
<div class="paragraph">
<p>The conference attendee event was an evening at the Halifax Citadel National Historic Site.
The Citadel is a fortification that was built (and rebuilt several times) to
protect the city. It stands high on a hill overlooking the harbour and also has
been a crucial communication hub at times.</p>
</div>
<div class="paragraph">
<p>It is worthwhile visiting the Citadel if you are ever in Halifax.
They have historical tours, ghost tours, daily cannon firing,
and occasional marching and band drills. I&#8217;ll just point out one feature
that was mentioned in the tour. The flag poles served the dual purpose of
military and commercial signalling before the advent of electronic telecommunications.
Even after the invention of the telegraph, the flags have still been used
as a tradition to earlier times.</p>
</div>
<div class="paragraph">
<p>The commercial signal mast was used by the British army to communicate marine
traffic in the harbour to the public. Different flags would indicate the
number and nationality of approaching ships (among other things).
The military signal mast used a code based on flags and disks.
Messages could be relayed to other signal posts and allowed a message
to be sent great distances quickly. A message that might take half a day
to deliver on horseback could be done in 30 minutes using the signal masts and codes.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/HalifaxCitadel.png" alt="Citadel"></span></p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_but_wait_theres_more">But wait, there&#8217;s more&#8230;&#8203;</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Of course, there is much more to ASF conferences than I can hope to do justice to hear.
There&#8217;s great people, great food, hallway conversations, a chance to chat to the wonderful
Infra folks. And did I say great people and great food?</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/HalifaxConferenceOverall.png" alt="conference"></span></p>
</div>
<div class="paragraph">
<p>I hope to see you at a future ASF conference.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_back_home">Back home</h2>
<div class="sectionbody">
<div class="paragraph">
<p>When you return from a trip, make sure to catch up with family and friends.
In my case, this involved a weekend away at the beach.</p>
</div>
<div class="paragraph">
<p><span class="image"><img src="img/MermaidBeach.jpg" alt="Mermaid Beach"></span></p>
</div>
<div class="paragraph">
<p>If you visit Australia, make sure to pop in.</p>
</div>
</div>
</div>
<div class="sect1">
<h2 id="_other_information">Other information</h2>
<div class="sectionbody">
<div class="paragraph">
<p>Other trip reports for the Halifax Community over Code conference 2023:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://www.linkedin.com/pulse/code-connections-collaboration-unpacking-community-over-atita-arora-b0gfe/">A review by Atita Arora</a>.</p>
</li>
</ul>
</div>
<div class="paragraph">
<p>See also:</p>
</div>
<div class="ulist">
<ul>
<li>
<p><a href="https://photos.apachecon.com/index.php?/category/37">Additional photos</a> grouped roughly into days and sessions within each day.</p>
</li>
<li>
<p><a href="https://communityovercode.org/schedule/">The official schedule</a> includes all tracks and will include
links to the slides of the talks if/when available.</p>
</li>
<li>
<p>Details for <a href="https://eu.communityovercode.org/">Community over Code EU</a> next year.</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.html'></a></li>
</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.org/search.html'>Search</a></li>
</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://twitter.com/ApacheGroovy'>Groovy on Twitter</a></li><li><a href='https://groovy-lang.org/events.html'>Events and conferences</a></li><li><a href='https://github.com/apache/groovy'>Source code on GitHub</a></li><li><a href='https://groovy-lang.org/reporting-issues.html'>Report issues in Jira</a></li><li><a href='http://stackoverflow.com/questions/tagged/groovy'>Stack Overflow questions</a></li><li><a href='http://groovycommunity.com/'>Slack Community</a></li>
</ul>
</div><div class='col-right'>
<p>
The Groovy programming language is supported by the <a href='http://www.apache.org'>Apache Software Foundation</a> and the Groovy community.
</p><div text-align='right'>
<img src='../img/asf_logo.png' title='The Apache Software Foundation' alt='The Apache Software Foundation' style='width:60%'/>
</div><p>Apache&reg; and the Apache feather logo are either registered trademarks or trademarks of The Apache Software Foundation.</p>
</div>
</div><div class='clearfix'>&copy; 2003-2024 the Apache Groovy project &mdash; Groovy is Open Source: <a href='http://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='https://cdnjs.cloudflare.com/ajax/libs/prettify/r298/prettify.min.js'></script><script>document.addEventListener('DOMContentLoaded',prettyPrint)</script><script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-257558-10', 'auto');
ga('send', 'pageview');
</script>
</body></html>