Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to serialize / parse protobuf object between Ruby and Java?

What is the correct way to serialize a protobuf object in ruby and parse in Java? This is for automated testing, we are listening for this message on a Rabbit queue.

Publisher (Ruby):

protoNew = Protobuf::Request.new
protoNew.request = request
protoNew.id = id.to_i
protoNew.authentication = authentication

return protoNew.serialize_to_string

Consumer (Java):

    @Override
    public void onMessage(Message message, Channel channel) 
    {
        ProtoRequest protoRequest;
        try {
            protoRequest = ProtoRequest.parseFrom(message.getBody());
        } catch (InvalidProtocolBufferException e1) {
            logger.error("Error parsing protobuf", e1);
        } 

Here is the error I am seeing:

Error parsing protobuf: com.google.protobuf.InvalidProtocolBufferException: Protocol message end-group tag did not match expected tag. at com.google.protobuf.InvalidProtocolBufferException.invalidEndTag(InvalidProtocolBufferException.java:94) [protobuf-java-2.6.1.jar:] at com.google.protobuf.CodedInputStream.checkLastTagWas(CodedInputStream.java:174) [protobuf-java-2.6.1.jar:] at com.google.protobuf.AbstractParser.parsePartialFrom(AbstractParser.java:139) [protobuf-java-2.6.1.jar:] at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:168) [protobuf-java-2.6.1.jar:] at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:180) [protobuf-java-2.6.1.jar:] at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:185) [protobuf-java-2.6.1.jar:] at com.google.protobuf.AbstractParser.parseFrom(AbstractParser.java:49) [protobuf-java-2.6.1.jar:]

like image 774
crobicha Avatar asked Nov 09 '22 06:11

crobicha


1 Answers

It is not clear how you are packaging the protoNew.serialize_to_string output such that it becomes content of JMS message for Java Code. I guess something is getting messed due to char encoding.

As a work around, you can do Base 64 encoding of the binary output of protoNew.serialize_to_string, and do Base 64 decoding at Java end.

require "base64"
...
return Base64.encode64 protoNew.serialize_to_string

On Java Side,

import org.apache.commons.codec.binary.Base64;
...
protoRequest = ProtoRequest.parseFrom(Base64.decodeBase64(message.getBody()))

One thing bad about the above solution is that it will result in bigger payload size compared to pure binary form.

PS: Please note that if I write output of person.serialize_to_string to a file in Ruby side, and read that file on Java, it seems to work fine

f = File.open("data.dat", "wb")
f << person.serialize_to_string
f.close
like image 108
Wand Maker Avatar answered Nov 14 '22 23:11

Wand Maker