Java Ecosystem, Kotlin, Distributed Systems, Sociology of Software Development

Why I Moved Back from Gradle to Maven

Posted on Apr 2, 2018

“Maven is old school” they said. “Use Gradle instead. It’s the future of building Java applications” they said. Sounds like something you don’t want to miss. So I tried Gradle in two real-world projects. In this post, I like to tell you about my experiences with Gradle and why I finally migrated back to Maven. It’s a story about enthusiasm and disillusionment.

Why I Moved Back from Gradle to Maven

Disclaimer and Target Group of this Post

This post aims at developers who are currently using Maven and are wondering if they should use Gradle instead. If you and your team are already familiar with Gradle and you are using it happily in practice for a while, you can definitely go on with Gradle. I won’t talk you into moving back to Maven. ;-)

And at the end, it’s also a matter of taste. You can read many blogs about this “Maven or Gradle?” topic and everybody tells you another story. Finally, you have to try out Gradle on your own and make up your own opinion.

TL;DR

  • For me, there is no best build tool. Both Maven and Gradle can be great or painful - depending on the project and team. There is only the right tool for the right job. And there is the personal taste.
  • Gradle is really powerful and flexible, but also complex, hard to learn and to cope if applied to real-world projects.
  • Advantages:
    • Great Flexibility. You can do everything within the build script as you write them with the full-fledged programming language Groovy.
    • Great Performance. Gradle does an awesome job in speeding up your builds with features like incremental builds, daemons and clustered builds.
  • Drawbacks:
    • Steep learning curve. Moreover, the whole team has to learn Gradle or you will be depending on the single Gradle ninja in your team.
    • The dynamic Groovy DSL and the heterogeneous plugin APIs will make you google everything.
    • Unexpected side-effects, behavior, and interdependencies between plugins. It often feels like magic.
    • Breaking changes in Gradle itself and plugins becoming incompatible.
    • As Groovy is dynamically typed, it’s really hard for IDEs to provide good and fast (!) tooling. Contrarily, parsing and interpreting Maven’s XML is dead simple.
    • New Gradle versions are often breaking existing plugins and the poor maintainer of this one-man-open-source-projects can’t keep up with this speed.
  • Make sure that you really need Gradle’s flexibility and performance.
    • Especially in a (micro)service architecture, many builds are straight-forward and small. So you don’t benefit much from Gradle’s advantages but you’ll have the drawbacks anyway.
    • Also, consider your development workflow. If you are compiling and running the tests and application inside the IDE most of the time and, therefore, rarely execute the build on your local machines, you don’t benefit that much from Gradle’s performance features. However, on the CI server, you are always running a clean and full build. Not much time to save here for most projects.
    • Be honest: Is Maven really a big pain point in your daily work?

Takeaway: Consider

  • the complexity and speed of your build,
  • the existing Gradle knowledge in your team and
  • your development workflow

to decide if the non-trivial investment into moving to Gradle is justified.

My Gradle Story at Spreadshirt

We have June 2017.

Gradle is definitely a popular technology in the Java community. More and more open-source projects are using it and it’s the defacto standard build tool for Android. It promises a shorter and compact DSL, flexibility and high performance. Sounds great! So I started to get familiar with Gradle, did some getting started tutorials and finally started to convert an existing project from Maven to Gradle. The build included the following aspects:

  • Retrieve artifacts from our own Nexus (Maven repository).
  • Compile a Vaadin theme (mainly SASS). Integrate this seamlessly with the Spring Boot project layout.
  • Compile Kotlin
  • Read from the local Git repository and write the information to a version.properties which in turn is read by the application to create a /version endpoint.
  • Start a MySQL Docker container, run the tests and stop the container afterward.
  • Create a Spring Boot fat jar.
  • Upload the jar to our Nexus. Distinguish between different repository URLs for releases and snapshots.
  • Make the build fly on our CI server (GitLab-CI). We need the Gradle binary and the Nexus credentials here as well.

That’s not a trivial build, but nothing really special. We are doing this with Maven for many years.

Enthusiasm

First, Gradle impressed me.

  • Great Flexibility. Highly customizable build.
    • You can easily create your own task and do whatever you want.
    • You can take advantage of the fully-fledged programming language Groovy. You can use conditions, loops, subroutines and any Java libraries. For a build script, this is very useful.
  • Performance
    • Gradle offers many performance optimizations. They claim to be way faster than Maven and I truly believe them.
    • They achieve this by an intensive use of incremental builds and the Gradle daemon. So there is no JVM restart and the daemon can keep the project configuration in memory.
    • Especially in case of the slow Kotlin compiler, incremental builds are really crucial for a fast build on the developer’s machine.
  • Compact DSL
    • I reduced the 408 lines pom.xml to a 180 lines build.gradle.

First Concerns

Due to the attraction of the new, I first didn’t notice how much effort and time it took me to implement the above build in Gradle. Ok, it’s a new language and technology, so I just have to get more familiar with Gradle and things will become easier. But I already figured out some cons:

  • Complexity. Steep Learning Curve. Demanding.
    • Sometimes, it’s hard to make certain things work and to understand the workflow of Gradle and the impact of certain plugins.
    • When starting to learn Gradle, some parts of the Groovy DSL are hard to grasp. It’s not always clear, where you can use =, a space or {}. Sometimes you can leave out the (). There are many different notations for the same thing. Again, flexibility comes with complexity.
  • Stability of Gradle and Plugins
    • Many of the plugin that I used were maintained by a single person who can’t manage to keep up with Gradle’s frequent breaking changes and “new” approaches like Spring Boot.
    • Here is my short story of pain and waiting with the Vaadin Spring Boot integration: I need to compile my Vaadin theme (SASS) during the build. However, there are only community Gradle plugins like com.devsoap.plugin.vaadin for this task available (Vaadin focuses on Maven). This plugin didn’t support the Spring Boot layout (it produced a war and didn’t support theme assets located under src/main/resources). After waiting a while, I could finally use version 1.2.0.beta1 fixing this issue. But it now requires Gradle 4.0, which was released just 2 weeks ago. This again crashes the plugin gradle-dcompose-plugin (used for starting a MySQL container before the tests). There was an issue filed on GitHub, less than 2 days ago where the author promised to fix this soon. Bottom line: It can be really tricky to make all plugins work together. But the community is active and is trying to fix issues asap. That’s great.

I drew the following intermediate conclusion:

  • Migrating the project to Gradle was more time-consuming and complex than expected.
  • Gradle is a good choice if your project…
    • … is big (you can benefit from Gradle’s great performance)
    • … or requires bells and whistles (Gradle’s flexibility comes in handy here - you can do anything you want in the Groovy DSL)
  • For small and simple projects Gradle doesn’t provide many benefits compared to Maven.
  • As Maven is not a real pain point in our daily work, I would definitely not migrate further services to Gradle. But for new services, I would try Gradle.

Disillusionment

So I carried on. Some months later, we started a new small internal tool and I used Gradle right from the beginning. After much fiddling around I was still not as productive in Gradle as I had expected. I got more and more frustrated because I had to invest so much time into my build just to get the functionality I already had with Maven.

I finally aborted my Gradle investment and moved both projects back to Maven within one hour. Here are my reasons and final findings:

  • Challenging Groovy DSL. You have to google a lot. Same notations can mean different things. There is no central place for global values (version numbers, repo URLs and credentials etc). Even after using the DSL for a while, I can’t say that I understand everything and why I’m using this notation and not the other one. You really have to learn Groovy for a full understanding. And I don’t want to learn a new programming language to fully understand my build scripts.
  • Although IDEA tries its best, the tooling support for Gradle build script (auto-completion etc.) was still poor. That’s in the nature of dynamic languages. Moreover, IDEA feels much slower.
  • We had to extend our existing CI infrastructure, puppet integrations and release mechanisms (e.g. for the Nexus credentials). Yes, that’s no big deal.
  • Steep Learning Curve. Every developer has to learn Gradle in order to understand the build, which is non-trivial. And learning Gradle is time-consuming and can be frustrating at the beginning. This is crucial, especially for small or new teams when there are other more important things to learn.
  • I was the only one in my team that learned Gradle (a little bit). So I knew that it’s tough. I didn’t want to encumber my team by forcing them to learn Gradle for building a single project. Especially when we don’t have a real benefit by using Gradle. That wouldn’t be responsible.
  • It’s hard to grasp what really happens internally in Gradle. Besides, there are side effects between plugins. e.g. the vaadin-plugin only creates a jar if you apply the spring-plugin (otherwise, you get a war).
  • The performance benefits are not that noticeable in practice for our small projects. Usually, I develop in my IDE. It compile my project and I execute my test out of IDEA. I only execute the build a few times. So it’s ok for me if some tasks (compilation, tests) are executed although they don’t have to be. Same goes for incremental builds. And on the CI server, you always execute a clean build. So you don’t benefit from incremental builds and the daemon.
  • Same goes for the flexibility that Gradle offers. Most of our builds are simple: execute some tests and create a fat jar (e.g. with the spring plugin). That’s it. No bells and whistles. Most of our projects are even simpler as they don’t even require the above Vaadin theme compilation or Docker control.
  • The point is that in a microservices architecture, you often have straight-forward builds. Complex and long-running builds are often occurring in monolithic applications. So the architecture might be the real problem; not the build tool.

Bottom Line: Maven is not perfect at all. But it’s not our biggest pain point. It does its job. Everyone knows it and our infrastructure supports it. And most important: our builds are not so big or special, that the challenging complexity of Gradle is justified.

What about the Kotlin Gradle DSL?

(Note, that the following paragraph refers to the state of the Gradle Kotlin DSL back in June 2017. Nowadays, things have become much better. Also mind, that the first GA version is not released for a reason.)

First and foremost, I highly appreciate the idea of a statically typed Gradle DSL and believe that this is the future of Gradle since it solves a huge drawback of Gradle. I also tried the Kotlin DSL, which fixes some of the missing tooling features (auto-completion, documentation, jump to sources). But the Kotlin DSL made IDEA incredibly slow. It was barely useable. Moreover, some notations (like configure<FooExtension>) are not very intuitive and it’s hard to find the correct name to use. For me, as a Gradle newbie, things haven’t become much more easy with the Kotlin DSL.

Conclusion

I suppose that all of my problems could be solved if I’d just invest more time into Gradle or buy consulting from Gradle Inc. That’s not the point. The point is, whether or not the effort is worth it. For our non-complex builds, development workflow and team, I conclude that Gradle doesn’t provide enough benefits to justify the investment. Maven is doing fine for us.

What are your experiences with Gradle? Do you agree or disagree? Just drop a comment.