Serialize Optional

In a recent post I explained why we can’t serialize Optional. But what if, after all that, we still really, really want to? Let’s see how to come as close as possible.

Update

This is part of a series of posts about Optional:

Overview

This post first takes a look at possible scenarios in which we want to serialize Optional and then presents a serializable wrapper for it. Finally, bringing both together, it shows solutions for the different scenarios. The post relies on the concepts of serialization and especially the serialization proxy pattern, which I described recently.

I created a demo project at GitHub which contains the complete code of the involved classes and a demonstration on how to use them. Check it out for more details. The next release of LibFX will also contain the serializable wrapper from that project.

When To Serialize Optional

Do restate the facts: Optional does not implement Serializable. And it is final, which prevents us from creating a serializable subclass.

Why And How to Serialize Optional?

Published by Ethan Lofton under CC-BY 2.0.

There are at least two scenarios which require to serialize an Optional:

  • It could be an argument or return type of a method which is send over the wire with a serialization-based RPC framework, like RMI.
  • It could be a field in a serializable class.

Let’s have a closer look at both cases.

Serializing an Optional Argument or Return Value

In this case the argument or return type has to be serializable. This can only be achieved by changing the method’s signature and use a class which implements that interface. Several approaches exist.

It would be possible to simply create a class which duplicates all the functionality of Optional but is serializable. It can then be used as a full replacement. This will likely lead to this class permeating the code base instead of the official one. In the face of future changes to the language, which might optimize performance if Optional follows a defined and rigid structure, and for various other reasons I don’t think this is a good idea.

Instead a simple class could be created which just allows to wrap and unwrap an Optional. It would be serializable by writing/reading the object contained in that Optional. I implemented such a class in my demo project. It is called SerializableOptional and explained further below.

But let’s first look at the other reason to serialize Optional.

Disclaimer

I do not have much architectural experience with remote calls. On the OpenJDK mailing list Remi Forax describes downsides of having the client act upon an empty Optional. For the exchange regarding that see Remi’s initial statement, this request for clarification and Remi’s explanation.

Serializing an Optional Field

If a class wants to serialize a field of type Optional, it has to customize its serialization mechanism. This is actually a good idea for any serializable – see chapter 11 in Java Bloch’s excellent Effective Java (2nd Edition). It can either define a custom serialized form or implement the serialization proxy pattern.

As it is the recommended approach in most cases, I will only cover the proxy pattern.

Disclaimer

In most cases there is no need to have a nullable/optional field in a class. A better design can often be created and should be actively looked for! (Apparently Optional isn’t serializable in order to convey that fact.)

If the class must have an optional field, it should be carefully decided whether it is part of the class’s logical representation. The fact that it is nullable/optional makes it likely that it is transient and can be recreated after deserialization. Only if that is not the case, does it make sense to serialize the field.

Serializable Optional

The SerializableOptional<T> (link) only exists to wrap and unwrap an Optional and offers little of its features. In the case of arguments or return values, it can (and in most cases should) be used without even declaring a variable of type SerializableOptional.

Wrapping

The class has two methods to wrap and unwrap an Optional (where T always extends Serializable – left out for brevity):

To make construction a little less verbose if no Optional exists, it has these equivalents of Optional’s methods with the same name:

Serialization

SerializableOptional uses the serialization proxy pattern. Its logical representation only consists of the value contained in the wrapped Optional (or null if it is empty).

Serialization then works as usual. See the demo for different use cases.

Serialize Optional

Let’s see how to approach the situations in which we would like to serialize an argument, return value or field of type Optional.

Methods With Optional Arguments Or Return Value

A method which likes to have an argument or return value of type Optional but needs it to be serializable, can use SerializableOptional instead. Using it of course adds another layer of indirection, which leads to additional calls:

Fields Of Type Optional

The recommended approach to serialization is to use the serialization proxy pattern. In that case, there are two possibilities to serialize Optional.

Serializing The Extracted Value

The proxy can simply have a field of the type which is wrapped by the Optional. In its constructor it then assigns the value contained in the Optional (or null if it is empty) to that field.

This is done by the ClassUsingOptionalCorrectly (link):

Using SerializableOptional

Alternatively, the serialization proxy can have an instance of SerializableOptional. This is done by the class TransformForSerializationProxy (link):

The main difference to extracting the value is readability. It makes it clearer that the logical representation contains an optional field. The costs are an increased size of byte representation and more time to write it. I didn’t benchmark this so I can’t tell whether this can be important. I guess that, as usual, it depends.

Reflection

We have seen the two main (and only?) reasons to serialize an Optional and what to do about it: If a method’s arguments or return value needs to be serialized, use the SerializableOptional and immediately wrap/unwrap it when the method is called. If a class has an optional field which it wants to serialize, its serialization proxy could either extract the Optional’s value or use write the SerializableOptional to the byte stream.

The helper class SerializableOptional from my demo project is public domain and can be used without any legal limitations.

Share & Follow

You liked this post? Then share it with your friends and followers!
twittergoogle_plusredditlinkedin
And if you like what I'm writing about, why don't you follow me?
twittergoogle_plusrss

Other Posts