Switching from Groovy to Java

Originally posted at http://labs.adaptavist.com/code/2017/07/17/switching-from-groovy-to-java/

For those of you who are aware that ScriptRunner allows JIRA users to execute Groovy code in response to events and workflow transitions, it may come as a surprise that the ScriptRunner for JIRA Cloud team has been converting the majority of our Cloud service codebase from Groovy to Java.

In this blog post I’ll talk a little bit about the reasons for that change and the things we miss from Groovy.

1. Static compilation finds bugs before runtime

Very early on in the development of ScriptRunner for JIRA Cloud we enabled static compilation of our Groovy code because we shipped some type-related bugs into production. The CompileStatic annotation tells the Groovy compiler to type-check our code at compile time, so as to avoid silly mistakes!

2. The Groovy compiler isn’t as good at static compilation as the Java compiler

Having enable static compilation we started running into scenarios where the Groovy compiler didn’t know what type a def was even though it was extremely clear to us and our IDE. Our codebase was becoming littered with as Map or as String and using def was becoming pointless. Given the amount of type-hinting we were doing, we felt like switching to Java wouldn’t add any additional type indication overhead.

3. We like our types, even if they’re verbose

One of the appeals of Groovy is that you don’t have to specify the type of a variable when the compiler can figure it out for you. Having said that, both Groovy and Java are strongly typed languages, and code is for humans, not for computers, so hiding the type of any given variable seems to be deliberately making things hard for ourselves. For this same reason we’re considering a move to TypeScript from ES6.

4. IntelliJ IDEA didn’t handle some of the generics in our Groovy code

Finally, our IDE just couldn’t handle the generics in some of our Ratpack code and subsequently highlighted huge chunks of our source incorrectly as having the wrong return type. This obscured actual errors in those sections of code which made working in any promise based Groovy code a real PITA.

So, what do we miss from Groovy?

  1. @Slf4j which injected a logger into each class for us, although we might introduce @Log4j from Project Lombok
  2. Succinct map and list literals although this might change a little with Java 9
  3. Some of the collection based default methods required less code than Java 8s streams, but the map/reduce terminology
    in Java is much more accessible than Groovys collect/inject
  4. String interpolation, although we do prefer only having one String type

We’re still using Groovy for our tests though, in part because we like Spock and in part because static compilation isn’t as necessary there 🙂