Nowadays with the variety of programming languages available to you, it’s tough to stick to the coding rules of your favorite choice without looking at what else is available.
I have been a professional Java developer for many years now, but I’m keen to always look at what is being done in the industry by all kinds of actors and I have to admit to something: there is cool stuff out there, in other programming languages. The cool stuff isn’t just the features or syntactic sugar constructs, but it’s also the coding standards that get my attention. In this post I want to talk about fluent APIs.
For the first 19 years of its life, Java hasn’t been a particularly fluent language and a lot of developers we’re quite vocal about that. I don’t know how many times I’ve heard the words “verbose” and “Java” in the same sentence, but believe me, it’s more than I care to count. I tend to agree with that sentiment, by the way, but rather than just complain about it, I decided to share my thoughts on how you can write a fluent API in Java. Warning, some of these thoughts do not follow the normal Java coding styles, rules, standards. So if you’re a Java purist, you may want to hide under your desk at this point.
In this post I would like to discuss the concepts and patterns that are often used in Java, and discuss whether or not it would be a good idea to avoid them to achieve a fluent API.
Java is verbose, what about other languages?
As I previously mentioned, Java is a verbose language. But I thought I’d repeat it to increase the verbosity of this blog post! Maybe Java’s verbosity is one of the reasons why so many new JVM languages were created, but during this post, I will also venture off of the JVM platform as well. For now though, we’ll start with a familiar JVM language for most.
Having used Gradle in my projects for a while now, I’m familiar with Groovy as the it’s the DSL which the Gradle build tool is built on. Groovy is a very expressive language without needing to write an awful lot of code. Let’s start with the simplest case:
If we go a little deeper, one of the features I particularly like is String interpolation (or variable expansion).
There’s just no need for a heavyweight StringBuilder! Is that enough evidence to call Groovy fluent? Well, not with just these examples, but how about if we use closures?
This code is taken from a gradle build script of SlideshowFX. Basically, it takes a configuration, named markdown, collects the name of every artifact (e.g. dependencies) and creates a comma separated string with that data, with a period to finish. The result is the following:
The syntax will undoubtedly look very familiar to everyone and it’s very concise. When you use libraries like jQuery, you won’t be surprised to see examples to chaining methods in the code.
Even when writing an article in which I ask you to review and look at other languages, I simply cannot ignore Java 8 which has many new features that have been widely praised by the Java community. Straight away, of course, you’ll think about the addition of Lambdas in the Java language. I have to admit: I like them. Groovy has Closures, Java has Lambdas. It completely changes the way we code and read code and it brings some much needed simplification to the language. See what you think:
As you can see from the snippet above, I have combined Lambdas with the Steam API, allowing you to traverse a collection in a very fast and efficient manner by turning complex computations into operations. Let’s look at a more complex example:
This snippet converts all items of the array into a Map using an Integer as a key and the number raised to the power of 2 as a value. Lambdas aren’t the only fluent API in Java 8. Don’t forget about the new, powerful and very fluent date and time API.
In comparison with the previous API, the new version is much more fluent and is largely inspired by Joda-Time.
Being fluent: where and why?
As seen previously, being fluent makes it easier for developers to adopt your API. But where should you be fluent and more to the point, why? Let’s try to answer these questions.
The JavaBean concept is well known in the Java world and a lot of APIs rely on it. The rules for making a JavaBean are pretty simple:
- Have a default constructor
- Make every field private (or protected)
- Use getters / setters to access each field
A simple example of a JavaBean is as follows:
Much in Java builds upon these elementary blocks. The EntityBean in JavaEE, for example, relies on this concept. For those who don’t know the concept, here’s a long story cut short: it’s an object (a Java class) representing an SQL table, or for those playing with Hibernate ORM, an entity stored within a data store. In a document oriented NoSQL data store, like MongoDB, it would be a JSON structure. But the exact implementation is not important. The point is that in order to persist and retrieve an EntityBean to and from a storing engine, JPA performs some operations:
- Every non transient value of an EntityBean is persisted using the getXXX method.
- Every value retrieved from the storing engine is set on an EntityBean using the setXXX method.
Moreover, the JDK itself relies on this concept in order to find getters and setters methods of a bean. When you are doing some reflection in Java, it is pretty easy to get a getter and setter method from a field’s name, and then, invoke it. Let’s play a bit:
And if you want all getters and setters:
At this point, there’s no problem but you can see what’s coming: what if I refactor the Foo class a little bit:
This improvement allows me to write the following code:
We call this method chaining. We now have a problem, because if we try to get the setter method using the previous technique, you will get a java.beans.IntrospectionException: Method not found: setBar. So don’t even think about refactoring the Foo class that way. Instead consider the following code:
And invoke as follows:
So what should we do with the JavaBean concept? Should we break free of it to make our APIs and code more fluent or just live with it? Considering a lot of APIs rely on it I don’t think breaking it is the right path, particularly because the next concept provides a better solution.
The factory/builder pattern
Basically, a factory is class that has a static method for building an object of a given type. The type of the factory is not of the same as the object it is building. For example, in Java you have (among others) the ProcessBuilder class that builds Process objects. This is particularly useful when the object you are trying to build is complex and you want to avoid your API’s users to know about and handle the boilerplate code needed for your API. This is paramount if it requires:
- a lot of skill
- a lot of configuration
- a lot of parameters
- to specify JNI libraries
Be warned, a factory will not resolve everything because your API is complex. A good refactoring would actually be much better, maybe mandatory, but I digress. So, the factory pattern is well suited in providing a fluent mechanism to build objects. Typically, we could use a minimal example:
In the JDK you can find the Calendar#getInstance() method that is similar to the previous example, among others.
The Context JavaBean
This is a concept of mine which consists of creating a JavaBean, which does not respect the fundamentals of a JavaBean. The Foo class described previously is a typical example.
These objects are particularly useful when used as context when calling a method. In some cases I like to provide a contextual object to a method instead of having a long list of parameters for that method. This allows me to add parameters to a method by avoiding method chaining in its declaration. Let’s see an example:
If I need more parameters I just need to update the contextual bean. In the case of a contextual object, I like to write a fluent API because I know those beans will never be serialized and only ever be used as helper objects.
How Do the Professionals Do It?
If you take a look at the jOOQ library, you will discover a very good example of a fluent API. For writing an SQL query using jOOQ, you can write something like this:
In this particular case, a fluent API shows one of its great potential by abstracting the Object language to be as fluent as the SQL grammar by:
- facilitating the query writing;
- avoiding typos.
Just let me explain the first bullet point. On the one hand, skilled SQL developers will use the API as fluent as if they were writing plain SQL text in their editor, and very quickly thanks to modern autocompletion provided by IDEs. On the other hand, newcomers to SQL (are there any?) will be helped to avoid mixing instructions, like putting a WHERE clause before the FROM one. Indeed, when they perform a select(…) operation, the API returns an object that doesn’t contain a where(…) method for example.
Vert.x is also a library that is very fluent. In order to get an instance of Vert.x, you do the following:
Additionally, the library takes care of creating the instance correctly. Also in Vert.x, you have the possibility to specify routes that are allowed using a Router. The router can be configured as follows:
In the fun world of lightweight Java frameworks for creating web applications, Spark is very fluent when it comes to creating a server and configuring it. It is inspired by Sinatra. Let’s see an example:
As you can see, using Spark completely hides the server instantiation by simply making you configure the server and the resources it serves. This lets you focus on the business you want to provide rather than the configuration. It is a paradigm I would call “Implementation over Configuration”.
To summarize there are cases of being fluent and cases of not being fluent. The worst time to create a fluent API is a JavaBean that need to be serialized, to a database for instance, because of the high risk of breaking compatibility between libraries relying on the fundamentals of Java. A better solution would be to create a contextual JavaBean.
Another great alternative is to use factories and builders using a fluent API to hide the more complex boilerplate of the class instantiation.
Fluent APIs are very beneficial when creating integrations between different languages such as Java and SQL, like jOOQ provides. But it also helps you to avoid errors, like typos, when writing code. Additionally, it provides you with a subtle mechanism to direct a user in how to use your API, by returning specific objects when a particular method is used. Think of the jOOQ API and its use of select, from, where clauses.
Do you have an example of a good Java project with an impeccably fluent API? Let me know below in the comments or tweet me: @twasyl.