0

Intro

I am using Apache Storm (Local mode, not Remote mode) in my Java project and when creating the topology I need to pass an object to one of the bolts

TopologyBuilder builder = new TopologyBuilder();
.....
builder.setBolt("last-bolt", new MyBolt(Classifier.SECONDS)).someGrouping(...);
.....
LocalCluster cluster = new LocalCluster();
cluster.submitTopology("test", conf, builder.createTopology());

The object itself has some non-serializable fields. Instead of subclassing the classes to which those fields belong and making them Serializable I have taken another approach. Since the actual object isn't gonna be changing a lot and it can be enumerated I've decided to make it an enum and pass it like that to bolt's tasks. The good thing about enum is that it is serializable under all costs. This approach works in local mode because (if I understood Storm correctly) there is only one JVM running on my computer and things can't get complicated actually.

Question

If the enum consists of a static final non-serializable field will that field be constructed properly when the enum is deserialized by another process on a different machine or a cluster running multiple JVMs?

The actual enum (static final field is at the end)

public enum Classifier {
    SECONDS {            
        public String classify(String timestamp) {
            DateTime dateTime = formatter.parseDateTime(timestamp);
            int second = dateTime.getSecondOfMinute();
            if (second <= 30) {
                return "00 - 30";
            } else {
                return "30 - 60";
            }
        }


        public int getNumberOfCategories() {
            return 2;
        }
    },

    WEEK {            
        public String classify(String timestamp) {
            DateTime dateTime = formatter.parseDateTime(timestamp);
            int dayOfWeek = dateTime.getDayOfWeek();
            String typeOfDay = (dayOfWeek >= 1 && dayOfWeek <= 5) ? "workday" : "weekend";
            int hour = dateTime.getHourOfDay();
            String hourInterval = hour + " - " + (hour == 23 ? 0 : hour + 1);
            return typeOfDay + " " + hourInterval;
        }


        public int getNumberOfCategories() {
            return 48;
        }
    };

    private static final DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");

    public abstract String classify(String timestamp);

    public abstract int getNumberOfCategories();
}

More details

DateTimeFormatter and DateTime are from org.joda.time package.

filip
  • 414
  • 3
  • 14

1 Answers1

0

All static final fields are initialized when class is loaded. Whatever serialization mechanism is used it will first initialize the static fields and execute static initialization blocks. Note that static fields are not deserialised because we are not deserialising classes but objects (please also refer to this answer https://stackoverflow.com/a/6429497/1937263).

So the answer is yes, the field should be constructed properly.

Community
  • 1
  • 1
makasprzak
  • 5,082
  • 3
  • 30
  • 49
  • 1
    For `enum`s it doesn’t even matter whether the fields are `static`. In the special case of `enum` (De-)Serialization *nothing* is (de)serialized at all, besides the `enum`’s type and the constants’s name. – Holger Jun 19 '14 at 15:30
  • If the enum instances have a constructor with some arguments is it called again during the deserialization? – filip Jun 20 '14 at 09:35
  • Enums are all static so the constructor is invoked just once at class loading phase. Again, it's not actually deserialized - it's initialized. http://stackoverflow.com/a/19433954/1937263 - here I was telling about what is behind the enum more or less. – makasprzak Jun 20 '14 at 14:02