You do know how to handle Json objects in Java, right? If you don’t, just pretend you do and check out the javax.json API introduced in JavaEE 7.

Since JavaEE 7, this is the official, standardized way of dealing with Json in Java. Even if you develop a desktop application or a library, you can use the API by pulling in the implementation with “runtime” dependency scope.

In this post I’m going to illustrate the importance of interfaces, by showing you how I solved an annoying problem with this specitifaction.

Mouse Trouble
Tom & Jerry - Mouse Trouble, by William Hanna and Joseph Barbera (from here)

You’ve probably used this API too, most likely for parsing responses from a REST endpoint. There, you simply built a JsonObject from the response’s InputStream and used it later only to read data from it, since JsonObject is immutable. Something like this:

InputStream content = response.getContent();
JsonObject result = Json.createReader(content).readObject();

or, you simply built a JsonObject, to send to a server with a POST request:

JsonObject car = Json.createObjectBuilder()
                     .add("mark", "BMW")
                     .add("price","$30.000")
                     .build();

In neither of these occasions, the flaw I’m talking about is not visible: JsonObjectBuilder.build() flushes the builder. So, in the car example above, if you would call build() multiple times, only the first would output the desired JsonObject; the following calls would result in an empty object. See this SO question about this “strange behaviour”.

Why is it a flaw? Because otherwise, you could elegantly use JsonObjectBuilder as the skeleton of any “mutable” implementation. It is a prefect in-memory storage. For instance, I’m using a JsonObjectBuilder to back a mock HTTP server. This basically means I have a bunch of classes which mimic the real HTTP API without actually making calls to any server. Instead, all the data is read/written from/into a JsonObjectBuilder. The build() method is called at every read operation and thus it is very inconvenient to have the builder flushed afterwards.

So how do you solve this issue? The first thing you do is start looking into different implementations. You try both Glassfish and Redhat to see that they behave the same. Bummer. Since there is no other way, the obvious solution is to write a global static method which takes the JsonObjectBuilder, builds the JsonObject and then, iterating over the JsonObject, adds the attributes back in the builder; something like this:

public static JsonObject buildObject(JsonObjectBuilder builder) {
    JsonObject built = builder.build();
    for(Entry<String, JsonValue> entry : built.entrySet()) {
      builder.add(entry.getKey(), entry.getValue());
    };
    return built;
}

This should work fine, except you will soon realize that all your code is poluted with calls to this static function. Wherever the build() method is called, you have to also call this function. Good luck debugging if you forget to use it somewhere. And you (or one of your new colleagues) will, for sure. Besides, static methods are always an ugly solution because they make our code more procedural.

Then, maybe you realize that javax.json.JsonObjectBuilder is an interface and that you can implement it to have any behaviour you need. So what? You are now going to reimplement everything those smart guys from Oracle or Redhat already implemented? No, of course not. Check this out:

public final class NfJsonObjectBuilder implements JsonObjectBuilder {

    private Map<String, Object> values = new LinkedHashMap<>();

    @Override
    public JsonObjectBuilder add(String name, JsonValue value) {
        this.values.put(name, value);
        return this;
    }

    @Override
    public JsonObjectBuilder add(String name, String value) {
        this.values.put(name, value);
        return this;
    }

    @Override
    public JsonObjectBuilder add(String name, BigInteger value) {
        this.values.put(name, value);
        return this;
    }
    //other add(...) methods with the same implementation

    @Override
    public JsonObject build() {
        //HERE: reuse their building logic.
        final JsonObjectBuilder builder = Json.createObjectBuilder();
        for(final Entry<String, Object> pair : this.values.entrySet()) {
            this.addToBuilder(pair, builder);
        }
        return builder.build();
    }

    private void addToBuilder(Entry<String, Object> pair, JsonObjectBuilder builder) {
        if(pair.getValue() instanceof JsonValue) {
            builder.add(pair.getKey(), (JsonValue) pair.getValue());
        }
        if(pair.getValue() instanceof String) {
            builder.add(pair.getKey(), (String) pair.getValue());
        }
        if(pair.getValue() instanceof Boolean) {
            builder.add(pair.getKey(), (Boolean) pair.getValue());
        }
        //A couuple more ifs to cover all the add(...) methods.
    }
}

Do you see the advantages of having a standardized API with clear interfaces? Now, the only difference in your code will be that, instead of instantiating your builder like this:

JsonObjectBuilder builder = Json.createObjectBuilder();

you will do it like this:

JsonObjectBuilder builder = new NfJsonObjectBuider();

And it will work like a charm.

Finally, I am aware (and you should be, too) that this is really basic OOP. But at the same time, I am ready to bet quite a fair amount that most developers would come up with the second solution or maybe even think of switching to some library from Google or what not. A lot of developers simply do not take advantage of such simple concepts as interfaces.