Hi again :)<div><br></div><div>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 &quot;union type&quot; or a sort of a container that you put your actual message inside:</div>
<div><br></div><div><div>message Foo{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>optional string some_field = 1;</div><div>}</div><div><br></div><div>message Bar{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>optional string some_other_field = 1;</div>
<div>}</div><div><br></div><div><br></div><div>message MessageWrapper{</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>enum Type {FOO = 1; BAR = 2; }</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>required Type type = 1;</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">        </span>optional Foo foo = 2;</div><div><span class="Apple-tab-span" style="white-space:pre">        </span>optional Bar bar = 3;</div><div>}</div><div><br>
</div><div><br></div><div>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</div><div> 1) Set just one of the optional fields</div>
<div> 2) Set the Type field to the enum representing that field.</div><div><br></div><div>For example to send Foo:</div><div><br></div><div><div><span class="Apple-tab-span" style="white-space:pre">                </span>Foo fooMsg = </div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>Foo.newBuilder().</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>setSomeField(&quot;SomeValue&quot;).</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>build();</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>MessageWrapper wrapperMsg = </div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>MessageWrapper.newBuilder().</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>setType(Type.FOO).</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>setFoo(fooMsg).</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>build();</div>
<div><br></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>someChannel.write(wrapperMsg);</div><div><br></div><div>Note: It&#39;s important that you always remember to wrap the messages you send, otherwise you get a very strange behavior. </div>
<div><br></div><div>You then setup your pipeline with a handler to receive this wrapper message:</div><div><span class="Apple-tab-span" style="white-space:pre">                </span>p.addLast(&quot;protobufDecoder&quot;, new ProtobufDecoder(MessageWrapper.getDefaultInstance()));</div>
<div><br></div><div>and in your application specific handler do something like:</div><div><br></div><div><div><span class="Apple-tab-span" style="white-space:pre">        </span>public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>MessageWrapper wrapperMsg = (MessageWrapper)e.getMessage();</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>switch (wrapperMsg.getType()){</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>case FOO:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Foo fooMsg = wrapperMsg.getFoo();</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>//Handle a Foo message</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>break;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>case BAR:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>Bar barMsg = wrapperMsg.getBar();</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>//Handle a Bar message</div>
<div><span class="Apple-tab-span" style="white-space:pre">                        </span>break;</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div><div><span class="Apple-tab-span" style="white-space:pre">                        </span></div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span>default:</div><div><span class="Apple-tab-span" style="white-space:pre">                        </span>throw new IllegalArgumentException(&quot;..... Type: &quot; + wrapperMsg.getType());</div>
<div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div><span class="Apple-tab-span" style="white-space:pre">                </span>}</div><div><span class="Apple-tab-span" style="white-space:pre">                </span></div><div>
<span class="Apple-tab-span" style="white-space:pre">        </span>}</div></div></div></div><div><br></div><div><br></div><div>Hope this helps. Will see if I can find time to put a complete sample together. </div><div><br></div>
<div>Regards</div><div>Jannick</div><div><br><br><div class="gmail_quote">2010/1/7 &quot;Trustin Lee (이희승)&quot; <span dir="ltr">&lt;<a href="mailto:trustin@gmail.com">trustin@gmail.com</a>&gt;</span><br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Tom,<br>
<br>
I would write a custom decoder instead of using ProtobufDecoder in such<br>
a case; something like the following, which prepends the message type<br>
and the message length field:<br>
<br>
public class MyProtobufDecoder extends FrameDecoder {<br>
<br>
  boolean waitingForHeader;<br>
  int msgType;<br>
  int msgLength;<br>
<br>
  Message prototypeA =<br>
      MessageA.getDefaultInstance().getDefaultInstanceForType();<br>
  Message prototypeB =<br>
      MessageB.getDefaultInstance().getDefaultInstanceForType();<br>
  Message prototypeC =<br>
      MessageC.getDefaultInstance().getDefaultInstanceForType();<br>
<br>
  @Override<br>
  protected Object decode(ctx, msg) {<br>
    ChannelBuffer buf = (ChannelBuffer) msg;<br>
    if (waitingForHeader) {<br>
      // Wait until at least 5 bytes are received in the buffer<br>
      if (buf.readableBytes() &lt; 5) {<br>
        return null;<br>
      }<br>
      msgType = buf.readByte();<br>
      msgLength = buf.readInt();<br>
      waitingForHeader = false;<br>
    }<br>
<br>
    if (!waitingForHeader) {<br>
      ChannelBuffer pbmsg = buf.readBytes(msgLength);<br>
      Message prototype;<br>
      switch (msgType) {<br>
      case 0: prototype = prototypeA; break;<br>
      case 1: prototype = prototypeB; break;<br>
      case 2: prototype = prototypeC; break;<br>
<br>
      // This is a user defined exception.<br>
      // Handle this exception in exceptionCaught()<br>
      // in your terminal handler<br>
      default: throw new ProtocolViolationException();<br>
      }<br>
<br>
      try {<br>
        return prototype.newBuilderForType().mergeFrom(<br>
                    new ChannelBufferInputStream(pbmsg)).build();<br>
      } finally {<br>
        waitingForHeader = true;<br>
      }<br>
    }<br>
  }<br>
}<br>
<br>
You will have to learn how to write a decoder eventually to customize<br>
the protocol to meet your need.  The user guide and the factorial<br>
example is a good starting point.<br>
<br>
However, I would still recommend the solution Jannick provided.<br>
<br>
HTH,<br>
<font color="#888888">Trustin<br>
</font><div><div></div><div class="h5"><br>
ritom wrote:<br>
&gt; Thanks for very much for the insight. If you do have multiple messages how to<br>
&gt; you handle them in the decoder. In the example looks like everything is<br>
&gt; based on one object what if you have two message type Foo and Bar instead of<br>
&gt; LocalTimeProtocol alone. Can you please give a example. Thanks a lot in<br>
&gt; advance.<br>
&gt;<br>
&gt;   p.addLast(&quot;protobufDecoder&quot;, new<br>
&gt; ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));<br>
&gt;<br>
&gt;<br>
&gt; Thingfish wrote:<br>
&gt;&gt; Hi<br>
&gt;&gt;<br>
&gt;&gt; The easiest solution is to wrap all your messages in a &#39;union type&#39; as<br>
&gt;&gt; described in this protobuf tutorial:<br>
&gt;&gt; <a href="http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union" target="_blank">http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union</a><br>
&gt;&gt;<br>
&gt;&gt; Alternatively you will have to manually prepend some kind of command id to<br>
&gt;&gt; identity the kind of protobuf message being sent, but unlikely to be worth<br>
&gt;&gt; the trouble.<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; Regards<br>
&gt;&gt; Jannick<br>
&gt;&gt; &lt;<a href="http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union" target="_blank">http://code.google.com/intl/da-DK/apis/protocolbuffers/docs/techniques.html#union</a>&gt;<br>
&gt;&gt;<br>
&gt;&gt; 2010/1/2 ritom &lt;<a href="mailto:ritom@hotmail.com">ritom@hotmail.com</a>&gt;<br>
&gt;&gt;<br>
&gt;&gt;&gt; Can somebody please help me understand the google protobuf support within<br>
&gt;&gt;&gt; Netty.<br>
&gt;&gt;&gt; In the LocalTimeServerPipelineFactory example we have<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; p.addLast(&quot;protobufDecoder&quot;, new<br>
&gt;&gt;&gt; ProtobufDecoder(LocalTimeProtocol.Locations.getDefaultInstance()));<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; That would mean we can now receive the Locations message in<br>
&gt;&gt;&gt; TimeServerHandler.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;  public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) {<br>
&gt;&gt;&gt;        Locations locations = (Locations) e.getMessage();<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; How would I implement support for multiple incoming message types where<br>
&gt;&gt;&gt; you<br>
&gt;&gt;&gt; might be receiving different types of request from the client. Lets say<br>
&gt;&gt;&gt; you<br>
&gt;&gt;&gt; are receiving Logon first then BalanceRequest, TransferRequest and so on.<br>
&gt;&gt;&gt; Also server will reply with multiple Message Types depending on the<br>
&gt;&gt;&gt; request.<br>
&gt;&gt;&gt; Can somebody please please help.<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; Tom<br>
&gt;&gt;&gt; --<br>
&gt;&gt;&gt; View this message in context:<br>
&gt;&gt;&gt; <a href="http://n2.nabble.com/Google-protocol-Buffer-Codec-tp4241485p4241485.html" target="_blank">http://n2.nabble.com/Google-protocol-Buffer-Codec-tp4241485p4241485.html</a><br>
&gt;&gt;&gt; Sent from the Netty User Group mailing list archive at Nabble.com.<br>
&gt;&gt;&gt; _______________________________________________<br>
&gt;&gt;&gt; netty-users mailing list<br>
&gt;&gt;&gt; <a href="mailto:netty-users@lists.jboss.org">netty-users@lists.jboss.org</a><br>
&gt;&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/netty-users" target="_blank">https://lists.jboss.org/mailman/listinfo/netty-users</a><br>
&gt;&gt;&gt;<br>
&gt;&gt; _______________________________________________<br>
&gt;&gt; netty-users mailing list<br>
&gt;&gt; <a href="mailto:netty-users@lists.jboss.org">netty-users@lists.jboss.org</a><br>
&gt;&gt; <a href="https://lists.jboss.org/mailman/listinfo/netty-users" target="_blank">https://lists.jboss.org/mailman/listinfo/netty-users</a><br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;<br>
<br>
--<br>
</div></div><div><div></div><div class="h5">what we call human nature in actuality is human habit<br>
<a href="http://gleamynode.net/" target="_blank">http://gleamynode.net/</a><br>
<br>
<br>
</div></div><br>_______________________________________________<br>
netty-users mailing list<br>
<a href="mailto:netty-users@lists.jboss.org">netty-users@lists.jboss.org</a><br>
<a href="https://lists.jboss.org/mailman/listinfo/netty-users" target="_blank">https://lists.jboss.org/mailman/listinfo/netty-users</a><br>
<br></blockquote></div><br></div>