Hot questions for Using Transmission Control Protocol in apache camel

Question:

Apache camel netty tcp component doc(http://camel.apache.org/netty.html) says,

encoder

A custom ChannelHandler class that can be used to perform special marshalling of outbound payloads. Must override org.jboss.netty.channel.ChannelDownStreamHandler.

decoder

A custom ChannelHandler class that can be used to perform special marshalling of inbound payloads. Must override org.jboss.netty.channel.ChannelUpStreamHandler.

Could you please point me an example on how/what to do in overriding class. I want a custom tcp encoder/decoder to read/write bytes.


Answer:

This class and it's super class are encoders and you can use it as an example: org.jboss.netty.handler.codec.string.StringEncoder

There are other classes used in the examples on the netty page from the "Using multiple codecs" heading which you can look at the source code for to see how they use the interface.

Failing that it's best to look at the netty project and look at the unit tests for the encoders.

Question:

I am using Camel Netty4 component to listen data on a TCP port. Below is my code:

public class TcpListener {


    public static void main(String hh[]) throws Exception{

        MyMessageDecoder byteDecoder = new MyMessageDecoder();
        SimpleRegistry reg = new SimpleRegistry();
        reg.put("decoder", byteDecoder);
        CamelContext context = new DefaultCamelContext(reg);

        context.addRoutes(new RouteBuilder() {
            public void configure() {

                from("netty4:tcp://0.0.0.0:5150?decoder=#decoder")
                .to("file://C:/Users/Rahul/Desktop?fileName=tcpOutput.txt");
            }
        });

        context.start();
    }

}

class MyMessageDecoder extends ByteToMessageDecoder {

    static FileWriter writer;
    static {
        try {
            writer = new FileWriter("C:/Users/Rahul/Desktop/tcpOutputNew1.txt");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    protected void decode(ChannelHandlerContext context, ByteBuf buffer, List<Object> out) throws Exception {

        if (buffer.readableBytes() < 1) {
            return;
        }

        byte[] bytes = new byte[1];
        buffer.readBytes(bytes);

        MyMessage myMessage = new MyMessage(bytes);
        System.out.println(bytes[0]);
        System.out.println(Integer.toBinaryString(bytes[0]));
        System.out.println(Integer.toHexString(bytes[0]));
        System.out.println(myMessage);

        out.add(myMessage);
    }
}

class MyMessage {

    protected byte data1;

    public MyMessage(byte[] data) {
        data1 = data[0];
    }

    public String toString() {
        return "MyMessage: { " + this.data1 +" }";
    }
}

In my code I am trying to read 1 byte at a time because in each byte I will receive IMEI number of device . For IMEI number

351608084153316

I should receive data like

0x03 0x51 0x60 0x80 0x84 0x15 0x33 0x16

But data I am receiving is

0x03 0x51 0x60 0xffffff80 0xffffff84 0x15 0x33 0x16. 

How can I resolve this or how can I ignore these unwanted bytes appended with some parts of the IMEI number.


Answer:

Here's what is happening.

  1. You have an array of bytes, which in Java are considered to be signed even though you don't care about a sign bit
  2. When you attempt to use them, they are automatically "promoted" to int. Since both byte and int are signed if the leftmost bit is 1 it is propagated leftwards so that the int value is the same as the byte numerical value. From you example

    0x03 0x51 0x60 0x80 0x84 0x15 0x33 0x16
    

    The first byte is 0x03 or bit pattern 0000_0011. This is a positive value and gets promoted to 0x00000003. Same for 0x51 and 0x60. Things are different for 0x80. Its bit pattern is 1000_0000 and its numeric value is -128. When it is promoted, its sign is left-extended, resulting in the int value 0xFFFFFF80, which still has the numerical value -128.

  3. In actuality, none of this affects you because the bit patterns in the low-order bytes have not changed. The solution for you is simply to mask out the unwanted bits whenever you access a byte from the array. As in

    Integer.toHexString(0x000000FF & (int) bytes[0])