Serialize message in C++, parse using Java

679 views
Skip to first unread message

Jun8

unread,
Oct 27, 2010, 2:50:08 PM10/27/10
to Protocol Buffers
I've Google for a day now and could not find full information on the
following problem.

I want to serialize protobuf messages in C++, send them to a JMS
(using activemq-cpp API) and parse in my Java server. Based on what I
found in my searches, here's my C++ function that serializes the
message:

/*
* Serialize given protobuf message and send to Active MQ JMS using
the producer.
*/
void MessageProducer::send( const diva::messaging::Message&
proto_mesg )
{
using namespace google::protobuf::io;

long bufLength = proto_mesg.ByteSize() +
CodedOutputStream::VarintSize32( proto_mesg.ByteSize() );
unsigned char buf[bufLength];

ZeroCopyOutputStream* raw_output = new ArrayOutputStream( buf,
bufLength );
CodedOutputStream* coded_output = new CodedOutputStream(raw_output);

// Prepend the message size to wire message.
coded_output->WriteVarint32( proto_mesg.ByteSize() );

proto_mesg.SerializeToCodedStream(coded_output);

// Create an ACtive JMS message and insert task & module information
in header.
cms::BytesMessage* message = m_session->createBytesMessage();

// Write serialized protobuf message to the JMS message and send.
message->writeBytes( buf, 0, bufLength );
m_producer->send( message );

delete message;
delete coded_output;
delete raw_output;
}

And here's the part in Java that parses teh received messages from
JMS:

// Create a byte array for received message.
BytesMessage receivedMessage = (BytesMessage)received_message;
logger.info("received message in NAC");
byte[] mesg_bytes = new byte[(int)receivedMessage.getBodyLength()];
int num_read = receivedMessage.readBytes(mesg_bytes);
if ( num_read != receivedMessage.getBodyLength() ) {
throw new Exception("Error reading message into byte array");
}

// Create registry for all possible DIVA messages.
ExtensionRegistry er = ExtensionRegistry.newInstance();
DivaBase.registerAllExtensions(er);

// Parse the received message.
diva.messaging.DivaBase.Message m =
diva.messaging.DivaBase.Message.parseFrom( mesg_bytes, er );

Currently, I get

Problem parsing message received in NAC:
com.google.protobuf.InvalidProtocolBufferException: Protocol message
end-group tag did not match expected tag.
Problem parsing message received in NAC: java.lang.ClassCastException:
org.apache.activemq.command.ActiveMQTextMessage cannot be cast to
javax.jms.BytesMessage

errors for each message and cannot see what I'm doing wrong.

Thanks for any comments on the code and/or pointers you might provide.

Jason Hsueh

unread,
Oct 28, 2010, 3:16:10 PM10/28/10
to Jun8, Protocol Buffers
On Wed, Oct 27, 2010 at 11:50 AM, Jun8 <ctas...@gmail.com> wrote:
I've Google for a day now and could not find full information on the
following problem.

I want to serialize protobuf messages in C++, send them to a JMS
(using activemq-cpp API) and parse in my Java server. Based on what I
found in my searches, here's my C++ function that serializes the
message:

/*
 *  Serialize given protobuf message and send to Active MQ JMS using
the producer.
 */
void MessageProducer::send( const diva::messaging::Message&
proto_mesg )
{
       using namespace google::protobuf::io;

       long bufLength = proto_mesg.ByteSize() +
CodedOutputStream::VarintSize32( proto_mesg.ByteSize() );
       unsigned char buf[bufLength];

       ZeroCopyOutputStream* raw_output = new ArrayOutputStream( buf,
bufLength );
       CodedOutputStream* coded_output = new CodedOutputStream(raw_output);

       // Prepend the message size to wire message.
       coded_output->WriteVarint32( proto_mesg.ByteSize() );

You're writing the message size as a prefix to the message data here...
 

       proto_mesg.SerializeToCodedStream(coded_output);

       // Create an ACtive JMS message and insert task & module information
in header.
       cms::BytesMessage* message = m_session->createBytesMessage();

       // Write serialized protobuf message to the JMS message and send.
       message->writeBytes( buf, 0, bufLength );
       m_producer->send( message );

       delete message;
       delete coded_output;
       delete raw_output;
}

And here's the part in Java that parses teh received messages from
JMS:

                       // Create a byte array for received message.
                       BytesMessage receivedMessage = (BytesMessage)received_message;
                       logger.info("received message in NAC");
                       byte[] mesg_bytes = new byte[(int)receivedMessage.getBodyLength()];
                       int num_read = receivedMessage.readBytes(mesg_bytes);

Presumably these bytes contain all the data that you wrote out, including the size prefix...
 
                       if ( num_read != receivedMessage.getBodyLength() ) {
                               throw new Exception("Error reading message into byte array");
                       }

                       // Create registry for all possible DIVA messages.
                       ExtensionRegistry er = ExtensionRegistry.newInstance();
                       DivaBase.registerAllExtensions(er);

                       // Parse the received message.
                       diva.messaging.DivaBase.Message m =
diva.messaging.DivaBase.Message.parseFrom( mesg_bytes, er );

...but parseFrom expects only the message data, not a message length prefix.

I'd just remove the WriteVarint32(proto_mesg.ByteSize()) call, since you are using a transport mechanism that has its own means for delimiting messages.


Currently, I get

Problem parsing message received in NAC:
com.google.protobuf.InvalidProtocolBufferException: Protocol message
end-group tag did not match expected tag.
Problem parsing message received in NAC: java.lang.ClassCastException:
org.apache.activemq.command.ActiveMQTextMessage cannot be cast to
javax.jms.BytesMessage

errors for each message and cannot see what I'm doing wrong.

Thanks for any comments on the code and/or pointers you might provide.

--
You received this message because you are subscribed to the Google Groups "Protocol Buffers" group.
To post to this group, send email to prot...@googlegroups.com.
To unsubscribe from this group, send email to protobuf+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/protobuf?hl=en.


Reply all
Reply to author
Forward
0 new messages