How to parse various objects in Netty(java)?

Question!

I use netty and i want to send various objects from client to server and vice versa.

I created same decoders and encoders classes on client and server ;

decoder:

public class UserInfoDecoder extends ByteToMessageDecoder {
    @Override
    protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
...
list.add(new UserInfo(...))
 }
}

encoder:

public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
        @Override
        protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
...
 out.writeBytes(...);
}

Here is my server initChannel method:

public void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline p = ch.pipeline();
                            if (sslCtx != null) {
                                p.addLast(sslCtx.newHandler(ch.alloc()));
                            }
                            p.addLast(
                                  //  new ObjectEncoder(),
                                  //  new ObjectDecoder(ClassResolvers.cacheDisabled(null)),

                                    new UserInfoDecoder(),
                                    new UserInfoEncoder(),

                                    new ObjectEchoServerHandler());
}

There is a method channelRead in server handler class

@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {


...
    }

How to differ objects what was sent by client? For e.g. now I have only "UserInfo" class and i can cast "Object msg" in channelRead to "UserInfo", but i want to send "UsersCar" object too for e.g., how to differ objects by types which were sent?



Answers

As the current implementation stands, the easiest way to accomplish this would be to add a 'magic byte' prefix to your encoded bytes before sending them across the channel.

public class UserInfoEncoder extends MessageToByteEncoder<UserInfo> {
    @Override
    protected void encode(ChannelHandlerContext ctx, UserInfo msg, ByteBuf out) {
    final int USER_BYTE = 0;
    out.writeBytes(USER_BYTE);
    out.writeBytes(msg.toBytes());
}

Then on the server side, when message is being decoded, check this magic byte and assign the appropriate decoder based on the value read. E.g. If the first undecoded byte has a value of 0, use the UserInfo decoder. If the value of the first undecoded byte is 1, use UsersCar decoder.

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
   final ByteBuf message = (ByteBuf) msg;
   final byte magicByte= message.getByte(0);

   if(magicByte == 0){
      new UserInfoDecoder().decode(message);
   }else if {
    ....
   }
}

Not the neatest solution, but the simplest.

Note: This is assuming the handler you're using is extending ChannelInboundHandlerAdapter

A good example to get your head around Netty encoding/decoding: http://shengwangi.blogspot.ie/2016/03/netty-tutorial-hello-world-example.html

By : etiescu


Sorry I don't get how to put pictures or code into the comments field.... Very confusing...

This is the code I am using. Does this make sense?

Stage:Stage 1
Loop: 1
    The contents of this loop will run repeatedly while: Current Item:Survey Distribution Date is less than 1901-01-13 12:00:00
        Pause until Current Item:Survey Distribution Date
        If Current Item:Survey Distribution Date equals (ignoring time) Today
        and Current Item:Survey Email Sent equals No
        and Current Item:Ultrabook deployed Y/N equals Yes
            Email Current Item:Recipient
            Update item in Current Item

Transition to stage Go to End of Workflow

By : barnie206


I think you could rewrite this as a single query on the status table, using ORs to test each scenario, like so:

SELECT ss.int_tran_id
FROM   status SS
WHERE  ss.stage in ('ACHPayment_Confirmed', 'HIFV4', 'HIFV5_FTRINF', 'Payment_HIFV5_FTRINF')
OR     (ss.stage = 'PREVDAY'
        AND (EXISTS (SELECT NULL
                     FROM   references rf
                     WHERE  ss.int_tran_id = rf.int_tran_id
                     AND    rf.mid_ref IS NOT NULL)
             OR EXISTS (SELECT NULL
                        FROM   app_data ad
                               INNER JOIN ach aa
                                 ON (ad.app_data_id = aa.ach_id)
                        WHERE  ss.int_tran_id = ad.int_tran_id
                        AND    aa.par_number IS NOT NULL)));
By : Boneist


This video can help you solving your question :)
By: admin