Serialize your lambdas for a rainy day - save to file

Introduction

A short post describing how a Java lambda can be persisted to a file for re-use in a different process. I then discuss how we use this technique in Fluxtion.

Serialising Lambdas

Lambdas, introduced in Java 8 make functions first class citizens(nearly) in the Java language. They remove the need for a dedicated class to hold a function. But how does this work under the covers?

In reality javac hijacks the class containing the function adding a static method that contains the implementation of the lambda. The lambda call site is replaced with an invocation to the newly added static method. For a full description of the lambda implementation magic see this article.

Oracle helpfully provides the SerializableLambda class that implements the serializable form of a lambda, providing enough meta information to reconstruct the call. All we have to do is cast the lambda to a Serializable and then use the standard java machinery to marshal the lambda. Below are a couple of utility functions to serialise and deserialise a lambda.

In the serialise function I use intersecting types to cast the function to Serializable.

I have written a small project with a test main here to demonstrate the serialisation of lambdas. The main method to execute the functions:

The project has a serialised lambda file "func-1" stored in the root of the project. Running the project will see func-1 overwritten so the second execution will give a different result from the first:

First execution:

hello - Greg
goodbye - Greg

Second execution:

goodbye - Greg
goodbye - Greg

To reset to original state set the boolean value to true and re-run.

Why is this useful

What are the use cases for serialising a lambda to execute in another process? An obvious use is sending processing logic to execute remotely. With Fluxtion we have a particular problem sharing  lambdas across independent execution phases. Fluxtion creates stream processing engines as a two step process:
  1. Design time: describe the processing requirements and generate a processing engine during the build.
  2. Runtime: use the generated engine in a deployed application.
Lambdas are defined in the build phase but execute at runtime in the generated code. Serialising the lambda solves the problem of accessing design time behaviour, the deserialised lambda can be invoked by the generated processing engine. The example below demonstrates the solution. 

First we define the processing at build time in a builder class:


The lambda is serialised to resources directory of the project during the build process, for use by the generated processing engine. The generated code deserialises the lambda and binds it to the event processing, see here. The relevant sections of the Fluxtion generated processing engine code:


The lambda is deserailsed on line 4 and is referenced as the filter function in line 17.

Hope you enjoyed this small article and found it interesting.

Comments

Popular Posts