Google protocol Buffer Codec
ritom
ritom at hotmail.com
Thu Jan 7 23:01:45 EST 2010
Jannick,
Thanks for taking time to write the sample for me.
Trustin,
You always amaze me I only started using netty because you were on the team.
I could now see Mina on the small corner of the world down the road. I only
wish we could have some one take initiative to upgrade quickfix/j to the
netty implementation with Java 1.5.
I took Jannick's advice and wrote a RequestProtocol and ResponseProtocol
request is for sending messages to server which consist of multiple objects
and Response to get the response back from server and it works like charm.
Thanks a lot.
Thingfish wrote:
>
> Hi again :)
>
> Made a quick example of doing the same thing Trustin just demonstrated, by
> using the protobuf union type/wrapper trick. Should note that protobuf
> does
> not (and can not be made to) generate any code to provide easy handling
> for
> this approach, so its a bit cumbersome. Okay, to the example, lets say you
> want to send the messages Foo and Bar. The trick is to define a "union
> type"
> or a sort of a container that you put your actual message inside:
>
> message Foo{
> optional string some_field = 1;
> }
>
> message Bar{
> optional string some_other_field = 1;
> }
>
>
> message MessageWrapper{
> enum Type {FOO = 1; BAR = 2; }
> required Type type = 1;
>
> optional Foo foo = 2;
> optional Bar bar = 3;
> }
>
>
> So when you want to send a Foo message, you construct the Foo message as
> usual, and then wrap it inside a MessageWrapper mesage. You then have to
> adhere to the convention, that always
> 1) Set just one of the optional fields
> 2) Set the Type field to the enum representing that field.
>
> For example to send Foo:
>
> Foo fooMsg =
> Foo.newBuilder().
> setSomeField("SomeValue").
> build();
> MessageWrapper wrapperMsg =
> MessageWrapper.newBuilder().
> setType(Type.FOO).
> setFoo(fooMsg).
> build();
>
> someChannel.write(wrapperMsg);
>
> Note: It's important that you always remember to wrap the messages you
> send,
> otherwise you get a very strange behavior.
>
> You then setup your pipeline with a handler to receive this wrapper
> message:
> p.addLast("protobufDecoder", new
> ProtobufDecoder(MessageWrapper.getDefaultInstance()));
>
> and in your application specific handler do something like:
>
> public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {
> MessageWrapper wrapperMsg = (MessageWrapper)e.getMessage();
> switch (wrapperMsg.getType()){
> case FOO:
> Foo fooMsg = wrapperMsg.getFoo();
> //Handle a Foo message
> break;
> case BAR:
> Bar barMsg = wrapperMsg.getBar();
> //Handle a Bar message
> break;
> default:
> throw new IllegalArgumentException("..... Type: " + wrapperMsg.getType());
> }
> }
>
>
> Hope this helps. Will see if I can find time to put a complete sample
> together.
>
> Regards
> Jannick
>
>
> 2010/1/7 "Trustin Lee (이희승)" <trustin at gmail.com>
>
>> Tom,
>>
>> I would write a custom decoder instead of using ProtobufDecoder in such
>> a case; something like the following, which prepends the message type
>> and the message length field:
>>
>> public class MyProtobufDecoder extends FrameDecoder {
>>
>> boolean waitingForHeader;
>> int msgType;
>> int msgLength;
>>
>> Message prototypeA =
>> MessageA.getDefaultInstance().getDefaultInstanceForType();
>> Message prototypeB =
>> MessageB.getDefaultInstance().getDefaultInstanceForType();
>> Message prototypeC =
>> MessageC.getDefaultInstance().getDefaultInstanceForType();
>>
>> @Override
>> protected Object decode(ctx, msg) {
>> ChannelBuffer buf = (ChannelBuffer) msg;
>> if (waitingForHeader) {
>> // Wait until at least 5 bytes are received in the buffer
>> if (buf.readableBytes() < 5) {
>> return null;
>> }
>> msgType = buf.readByte();
>> msgLength = buf.readInt();
>> waitingForHeader = false;
>> }
>>
>> if (!waitingForHeader) {
>> ChannelBuffer pbmsg = buf.readBytes(msgLength);
>> Message prototype;
>> switch (msgType) {
>> case 0: prototype = prototypeA; break;
>> case 1: prototype = prototypeB; break;
>> case 2: prototype = prototypeC; break;
>>
>> // This is a user defined exception.
>> // Handle this exception in exceptionCaught()
>> // in your terminal handler
>> default: throw new ProtocolViolationException();
>> }
>>
>> try {
>> return prototype.newBuilderForType().mergeFrom(
>> new ChannelBufferInputStream(pbmsg)).build();
>> } finally {
>> waitingForHeader = true;
>> }
>> }
>> }
>> }
>>
>> You will have to learn how to write a decoder eventually to customize
>> the protocol to meet your need. The user guide and the factorial
>> example is a good starting point.
>>
>> However, I would still recommend the solution Jannick provided.
>>
>> HTH,
>> Trustin
>>
>> ritom wrote:
>> > Thanks for very much for the insight. If you do have multiple messages
>> how to
>> > you handle them in the decoder. In the example looks like everything is
>> > based on one object what if you have two message type Foo and Bar
>> instead
>> of
>> > LocalTimeProtocol alone. Can you please give a example. Thanks a lot in
>> > advance.
>> >
>> > p.addLast("protobufDecoder", new
>> > ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
>> >
>> >
>> > Thingfish wrote:
>> >> Hi
>> >>
>> >> The easiest solution is to wrap all your messages in a 'union type' as
>> >> described in this protobuf tutorial:
>> >>
>> http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union
>> >>
>> >> Alternatively you will have to manually prepend some kind of command
>> id
>> to
>> >> identity the kind of protobuf message being sent, but unlikely to be
>> worth
>> >> the trouble.
>> >>
>> >>
>> >> Regards
>> >> Jannick
>> >> <
>> http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union
>> >
>> >>
>> >> 2010/1/2 ritom <ritom at hotmail.com>
>> >>
>> >>> Can somebody please help me understand the google protobuf support
>> within
>> >>> Netty.
>> >>> In the LocalTimeServerPipelineFactory example we have
>> >>>
>> >>> p.addLast("protobufDecoder", new
>> >>> ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));
>> >>>
>> >>> That would mean we can now receive the Locations message in
>> >>> TimeServerHandler.
>> >>>
>> >>> public void messageReceived(ChannelHandlerContext ctx, MessageEvent
>> e)
>> {
>> >>> Locations locations = (Locations) e.getMessage();
>> >>>
>> >>> How would I implement support for multiple incoming message types
>> where
>> >>> you
>> >>> might be receiving different types of request from the client. Lets
>> say
>> >>> you
>> >>> are receiving Logon first then BalanceRequest, TransferRequest and so
>> on.
>> >>> Also server will reply with multiple Message Types depending on the
>> >>> request.
>> >>> Can somebody please please help.
>> >>>
>> >>> Tom
>> >>> --
>> >>> View this message in context:
>> >>>
>> http://n2.nabble.com/Google-protocol-Buffer-Codec-tp4241485p4241485.html
>> >>> Sent from the Netty User Group mailing list archive at Nabble.com.
>> >>> _______________________________________________
>> >>> netty-users mailing list
>> >>> netty-users at lists.jboss.org
>> >>> https://lists.jboss.org/mailman/listinfo/netty-users
>> >>>
>> >> _______________________________________________
>> >> netty-users mailing list
>> >> netty-users at lists.jboss.org
>> >> https://lists.jboss.org/mailman/listinfo/netty-users
>> >>
>> >>
>> >
>>
>> --
>> what we call human nature in actuality is human habit
>> http://gleamynode.net/
>>
>>
>>
>> _______________________________________________
>> netty-users mailing list
>> netty-users at lists.jboss.org
>> https://lists.jboss.org/mailman/listinfo/netty-users
>>
>>
>
> _______________________________________________
> netty-users mailing list
> netty-users at lists.jboss.org
> https://lists.jboss.org/mailman/listinfo/netty-users
>
>
--
View this message in context: http://n2.nabble.com/Google-protocol-Buffer-Codec-tp4241485p4270424.html
Sent from the Netty User Group mailing list archive at Nabble.com.
More information about the netty-users
mailing list