protostuff/protostuff

Issue while deserializing an enum class

Vishv19 opened this issue · 4 comments

Hi,

I am working on a codebase that uses an Enum class (AttrKey)

public class LCDetails {
	List<DiscardReason> evaluate(Map<AttrKey, List<String>> actualValues);
	// more data elements and methods
}

Since this is a legacy codebase, it serializes and compresses the LCDetails object using protostuff and stores the blob in a relational database.

Now we want the behavior of AttrKey to be dynamic and read some of the new values from the config. Since this enum is heavily used, we have gone with an approach to change the AttrKey enum to a class type and minimize the number of changes.

Can the existing entries of LCDetails in the database be deserialized correctly once AttrKey enum is converted to a class type? I am observing the following issues while spinning up a local server after this change.

java.lang.RuntimeException: Reading from a byte array threw an IOException (should never happen).
	at com.dyuproject.protostuff.IOUtil.mergeFrom(IOUtil.java:53)
	at com.dyuproject.protostuff.ProtostuffIOUtil.mergeFrom(ProtostuffIOUtil.java:96)

Is it because there is different handling of deserialization of Enum object than a java class?

dyu commented

Is it because there is different handling of deserialization of Enum object than a java class?

Yes. You can solve that using delegates - https://protostuff.github.io/docs/protostuff-runtime/delegate/

@dyu Thanks for your response, really appreciate it!
The current version of protostuff used by this codebase is 1.0.4, looks like it was never updated after the initial setup.

Since I see the delegate is available starting version 1.0.7, is it safe to upgrade my dependency to 1.0.7? My concern is whether it would have an impact on deserialization of existing data.

When I checked the release docs, it says 1.1.0+ might not be wire-compatible with 1.0.x so I guess it's not a good idea to update it to latest version?

dyu commented

@Vishv19 you can upgrate to 1.0.12 safely

@dyu Thank you!
I wasn't able to find any specific example of declaring delegate for use case similar to mine, so I just had few more relevant questions:

  1. So the FieldType getFieldType() should return FieldType.STRING if the output of my custom serialization is String?
  2. While debugging my codebase, I found that the deserialization was happening based on ordinal number, so I guess if I readEnum from my input, I can use it to derive and deserialize into my corresponding new object?
  3. Also since I have to maintain both types of serialization(custom and the existing one) going forward, can I assume that if readEnum() is empty I can check readString() and apply my custom logic to translate it to the object instance?