We tried Groovy EE — and what we have learned from it

Artur Skowroński
Smart Up
Published in
5 min readOct 10, 2016

Let me tell you a story. One from the category people like the most — with a lot of cries and pain, but also catharsis at the end.

Does anybody still remember Groovy? It was popular JVM language in the late 2000s. In my personal career, I have seen it’s usage mainly for scripting and creating clever one-liners at developer’s conferences (those ones you definitely don’t want to see in inherited code of the other team). But did anybody think about using it for full-fledge development? I know Grails exists and there are some people who write in it to make a living — but let’s be serious — It’s hard to consider Groovy a language of choice for writing a production-ready web application in 2016s.

But we still tried to check how it would work out. And we paid a price for our bravery.

Forgive me for this ironic beginning ,the truth is, we like Groovy, we like it a lot. It is a perfect tool for quick scripting, and an ideal weapon to defeat database migrations. We also started to use it in some specific parts of our Java web application , and it integrated with Java quite well. We thought we are prepared for another great leap , we gained a lot of experience in that language, we started with small steps and tried something bigger each time (JUnit tests, some mappers). In the end, we decided to dare and write a whole new (micro)service in Groovy. We liked the language and decided it’s time to make it our weapon of choice in this kinda clumsy Java world.

We are not writing software in a vacuum. Our main stack is based on Java EE, although this platform has it’s problems.

“Java EE is best tool to write Microservices” said nobody ever

Still, we harnessed it to suit our daily needs and we are happy with our choice. Decision to use them together was natural one — we know Java EE well and we know Groovy at the level that makes us quite productive. Yet, we weren’t prepared for what happened after we had mixed them together. I will share with you just a few most interesting problems we encountered:

  1. The first one — Groovy’s Syntax looks sleek as long as it was used in a project that used it as Groovy. Just packing it to a .jar file and using it as a dependency in another project showed us its true face. Everything is meta in it. Just take a look what we received as “bonus” to every plain old Groovy object. Pollution of interface was enormous.

    It was unacceptable for people who needed to use the code we wrote,we needed to write every shared piece of code in Java class. Our team learned — the hard way — that Groovy is interoperable, but on it’s own rules. I won’t mention that it added about 4 Mb to every archive where we put it in…
  2. Groovy is dynamic — that is good — but for a lot of places it was too dynamic. After a few situations when we received kick in the knee from bugs that could be easily spotted in statically compiled languages, we started to use @CompileStatic annotation. We quickly traded off a lot of dynamic freedom for stable application and well earned sleep.
  3. Did I write that Groovy is dynamic? It is — and it rendered our IDE useless. Not completely, but unfortunately more advanced tools (for which we are paying a lot of money to Jetbrains) didn’t work with it. We couldn’t find Injection Points of Beans in Groovy classes, postfixes don’t work, we couldn’t easily optimise imports. Groovy is definitely a slick tool, but unfortunately it made our other tools dumber,we lost everything we took for granted while using Java.
  4. Groovy Proxy is really clever language feature, an engineering masterpiece, and it works fine… as long as you don’t make it interoperable with Java EE Weld, which also can be considered such a proxy. When you do that… a lot of “fun” stuff happens. We received new category of Heisenberg Bugs , they couldn’t be observed on our developers’ machines, but were starting to popup semi-randomly on application servers. Sometimes our Groovy Beans were simply… not injected by Weld. They worked fine on one configuration, they just broke on another. The scale of our irritation was so enormous that after fighting with another broken deployment (different solutions helped in different cases, we didn’t have one that worked in every case), we hoisted the white flag — whenever Bean started to be problematic, we just rewrote it to Java — ending up with Frankenstein monster.
  5. Surprisingly — the same category of problems showed up in a place we were sure that won’t bite us — Unit Tests. We used Groovy in them a lot, and considered ourselves battle tested in this use-case. It couldn’t be that easy — we started to see strange behaviour in tests, specifically in Mockito (which was our library-of-choice for stubbing) — all mocks started to be null in some cases. When we distilled a minimal piece of code, we realised that everything was fine whenever we used Groovy in class-under-test OR in test. If we used Groovy in both, our mocks were throwing NullPointers. After some digging, we found out that this is a common case — Mockito’s Proxy doesn’t like Groovy’s one — which has a solution in specific versions of Mockito but it is not viable anymore. It became clear that, while we wouldn’t like to loose expressiveness of Groovy in tests, we couldn’t use it the way we did in past…

Are you still there? If yes, I will reward your patience. Our problems with Groovy and Mockito made us look for an alternative. And we found one quite easily… in Spock Framework — Groovy-first testing toolchain, with tiny bit of BDD flavour . We heard a lot of good things about it, but we were comfortable with well-known devil, without the motivation to change it. We were forced to improvise and we decided to give Spock a chance. We quickly understood that it’s a fabulous library, which we use in every new project. We dropped Mockito and never turned back. We love to use it, so we write more tests, and we write better tests using more advanced features.

“Parameterized Test in JUnit are easy to write”, said anybody who consider Java EE best tool for Microservices.

That renders quality of our daily work at least slightly better.

I promised you a moral, and I see two of them there:

First — if you know well both tool A and tool B, making them work together is a completely different kettle of fish and you need to be prepared for it. We definitely thought everything will be far easier.

Second — remember to experiment. Probably you will fail a lot, but without it you cannot learn any new tricks, living in the world of “good enough”. We are lucky to work in an environment that promote experiments like that (Microservices FTW!), but if you are not, try to combine some strange stuff and check the result in some side projects.

Life begins at the end of your comfort zone.

--

--