Using GPB, how do I make my wrapper classes stop accepting binary messages that aren't meant for them?
I'm using Google Protocol Buffers to serialize some of my business objects (in a Java app). As recommended in the tutorials, I wrap the message builder in a class of my own that implements getter and setter methods to access the message's properties. Also, I declared all message fields optional
, again following their recommendations.
Now, I can give any of the wrapper classes any of the encoded messages and they will always parse and accept them. This leads to wrapper objects that represent a message type which they don't actually contain and a lot of bogus happens.
When loading the binary content of a message into a wrapper class, how can I make it throw an error if it has been passed the wrong type?
The solution I'm currently thinking of would have all messages extend a base message with a required type field (and maybe a version field). This would have the generated builder class throw an exceptio开发者_开发知识库n if those fields are missing, and if they are there, I can check in my own code. However, I'm not yet done evaluating what repercussions this has for my code, and I'm not sure this is going to be easy.
If the data you pass to MyMessage.parseFrom() does not represent a message of that type, you will get a InvalidProtocolBufferException. Isn't that enough for you?
PB messages are not self-describing, so need to know (by some means) which message you are trying to parse. Of course, you can try to parse them and catch InvalidProtocolBufferException, but that isn't very nice. Instead, I think most people are using the approach you are describing: use a base message class with a type field (usually an enum) and a number of optional fields, one for each possible sub-type. This allows you to parse the message, and then switch on the message type to extract the actual "payload" of the message.
This seems to be what other people do, too, and it works fine for me:
message TypedMessage {
required string type = 1;
required bytes payload = 2;
}
The actual message goes into the payload field in serialized form and the type is used to get the proper builder and wrapper class. The field could also be an enum, I'm currently using Java class names, which I will likely replace by a different system later, since this means refactoring breaks backwards compatibility of the parser.
精彩评论