Over a million developers have joined DZone.

Lambda, Will it Serialize?

· DevOps Zone

The DevOps zone is brought to you in partnership with Sonatype Nexus. The Nexus suite helps scale your DevOps delivery with continuous component intelligence integrated into development tools, including Eclipse, IntelliJ, Jenkins, Bamboo, SonarQube and more. Schedule a demo today

So I have been pondering an enhancement required on the Tyrus project that would allow a user to broadcast to a subset of client connected to a URL across a cluster of machines. There are various way of doing this; but since I was playing with JDK 8 this problem definitely looked like a nail.

To this end I created a simple unit test class that would take my filter, serialise it to disk, read it back and in then execute it. It had a instance field "VALUE" that we could use to reference directly or indirectly to find out what would cause the serialisation to fail.

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.NotSerializableException;
import java.io.ObjectInput;
import java.io.ObjectInputStream;
import java.io.ObjectOutput;
import java.io.ObjectOutputStream;
import java.io.Serializable;

import java.util.function.Predicate;

import org.junit.Test;

public class SerializablePredicateFilterTest {

  public String VALUE = "Bob";

  public interface SerializablePredicate<T> extends Predicate<T>, Serializable {


  public <T> void filter(SerializablePredicate<T> sp, T value) throws IOException, ClassNotFoundException {


    File tempFile = File.createTempFile("labmda", "set");

    try (ObjectOutput oo = new ObjectOutputStream(new FileOutputStream(tempFile))) {

    try (ObjectInput oi = new ObjectInputStream(new FileInputStream(tempFile))) {
      SerializablePredicate<T> p = (SerializablePredicate<T>) oi.readObject();




So just to calibrate lets make sure that an anonymous inner class will fail, because it will always contain a reference to enclosing object....

01.@Test(expected = NotSerializableException.class)
02.publicvoidtestAnonymousDirect() throwsIOException, ClassNotFoundException {
04.  String value = VALUE;
07.  filter(newSerializablePredicate<String>() {
09.    @Override
10.    publicbooleantest(String t) {
11.      returnvalue.length() > t.length();
12.    }
13.  }, "Bob");

The same is true for local classes, what you don't use local classes?

  @Test(expected = NotSerializableException.class)
  public void testLocalClass() throws IOException, ClassNotFoundException {

    class LocalPredicate implements SerializablePredicate<String> {
      public boolean test(String t) {
        // TODO Implement this method
        return false;

    filter(new LocalPredicate(), "Bobby");


So a standalone class will of course work, in this case a nested class for convenience.

  public static class LengthPredicate implements SerializablePredicate<String> {

    private String value;

    public LengthPredicate(String value) {
      this.value = value;

    public void setValue(String value) {
      this.value = value;

    public String getValue() {
      return value;

    public boolean test(String t) {
      // TODO Implement this method
      return false;

  public void testStaticInnerClass() throws IOException, ClassNotFoundException {

    filter(new LengthPredicate(VALUE), "Bobby");


So lets get down with JDK 8, it turns out that my first try also fails but it does confirm that the serialisation is quite happy to take a Lambda in general.

  @Test(expected = NotSerializableException.class)
  public void testLambdaDirect() throws IOException, ClassNotFoundException {

    filter((String s) -> VALUE.length() > s.length(), "Bobby");


A slight modification to copy the value into a effectively final attributes, and voila the lambda is now serialised and retrieved properly.

  public void testLambdaInDirect() throws IOException, ClassNotFoundException {

    String value = VALUE;

    filter((String s) -> value.length() > s.length(), "Bobby");


And of course if the value is a simple method parameter it also works fine.

  public void testLambdaParameter() throws IOException, ClassNotFoundException {



  private void invokeWithParameter(String value) throws java.lang.ClassNotFoundException, java.io.IOException {
    filter((String s) -> value.length() > s.length(), "Bobby");

So the answer is yes, you can get it to serialise if you are a bit careful.

The DevOps zone is brought to you in partnership with Sonatype Nexus. Use the Nexus Suite to automate your software supply chain and ensure you're using the highest quality open source components at every step of the development lifecycle. Get Nexus today


Published at DZone with permission of Gerard Davison, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}