Декодирование двоичных данных из TCP в XML в JBoss Fuse

Я новичок в ESB в целом, однако мне было поручено реализовать средство чтения TCP, которое выводит XML-данные в JBoss Fuse. Я пробовал несколько методов, пока с ограниченным успехом.

Я начал с использования Camel Blueprint ArchType (поскольку на нем основано большинство руководств по Fuse). Затем я определил простой маршрут, начинающийся с входа Netty4, проходящий через пользовательский класс декодера и регистрирующий результат.

blueprint.xml

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
       http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd">

    <bean id="myMessageDecoder" class="com.mycompany.binaryreceiver.binaryreceiver.MyMessageDecoder" />

  <camelContext allowUseOriginalMessage="false" xmlns="http://camel.apache.org/schema/blueprint">
  <route>
    <from uri="netty4:tcp://localhost:9999?decoder=#myMessageDecoder&amp;sync=false"/>
    <log message="Message Received: ${body}"/>
  </route>
</camelContext>

</blueprint>

MyMessageDecoder.java

package com.mycompany.binaryreceiver.binaryreceiver;

import java.util.List;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;

public class MyMessageDecoder extends ByteToMessageDecoder {

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

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

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

        MyMessage myMessage = new MyMessage(bytes);

        out.add(myMessage);
    }
}

MyMessage.java

package com.mycompany.binaryreceiver.binaryreceiver;

public class MyMessage {

    protected int data1;
    protected int data2;
    protected int data3;

    public MyMessage(byte[] data) {
        data1 = data[0];
        data2 = data[1];
        data3 = data[2];
    }

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

Декодер просто проверяет, есть ли в буфере три байта. Если есть, то он помещает эти байты в MyMessage, который предлагает интерфейс toString, к которому может получить доступ регистратор.

Очевидно, что это всего лишь пример, а окончательное сообщение намного сложнее, включая содержимое переменной длины, однако это иллюстрирует основной процесс.

Похоже, все это работает, если я нажимаю поток байтов на порт 9999, регистратор выводит ожидаемые значения:

INFO  Message Received: MyMessage: { 1, 13, 58 }
INFO  Message Received: MyMessage: { 2, 36, 63 }
INFO  Message Received: MyMessage: { 3, 74, 5 }
INFO  Message Received: MyMessage: { 4, 12, 92 }
INFO  Message Received: MyMessage: { 5, 111, -121 }
INFO  Message Received: MyMessage: { 6, 0, 0 }
INFO  Message Received: MyMessage: { 7, 80, 64 }
INFO  Message Received: MyMessage: { 8, 0, 0 }
INFO  Message Received: MyMessage: { 9, 0, -116 }
INFO  Message Received: MyMessage: { 10, -108, 111 }
INFO  Message Received: MyMessage: { 11, -17, -100 }
INFO  Message Received: MyMessage: { 12, -35, -28 }

Однако во время запуска я получаю следующее сообщение:

[Blueprint Extender: 1] NettyConfiguration  WARN  
The decoder com.mycompany.binaryreceiver.binaryreceiver.MyMessageDecoder@2413a0f1
is not @Shareable or an ChannelHandlerFactory instance. The decoder cannot safely be used.

После просмотра предупреждения я нашел ссылки, которые, казалось, предполагали, что я неправильно обхожу весь процесс и что мне следует пройти через Netty4 ChannelHandlerFactories.

Есть ли у кого-нибудь опыт выполнения аналогичного двоичного -> XML-процесса, который может прокомментировать или помочь с правильным/рекомендуемым процессом для выполнения этих задач?

Является ли предупреждение законной проблемой или отвлекающим маневром? Должен ли я использовать ChannelHandlerFactories или совершенно другой подход?


person Iain Smith    schedule 25.09.2015    source источник
comment
попробуйте добавить @Shareable в свой собственный класс кодека   -  person Claus Ibsen    schedule 25.09.2015
comment
Согласно API, это не так просто: Имейте в виду, что подклассы ByteToMessageDecoder НЕ ДОЛЖНЫ аннотироваться @Sharable. [Ссылка] (netty.io/4.0/api/io/netty/handler/codec/)   -  person Iain Smith    schedule 25.09.2015


Ответы (2)


См. документацию по camel-netty4 в разделе о кодировщиках и декодерах, не предназначенных для совместного использования. Это вся документация, что вам нужно сделать:

person Claus Ibsen    schedule 25.09.2015
comment
Спасибо за помощь. Означает ли это, что декодер на основе ByteToMessageDecoder является неправильным подходом и что вместо этого мне следует использовать ChannelHandlerFactory? Или декодер можно использовать, но только при определенных обстоятельствах? - person Iain Smith; 26.09.2015

Я планировал реализовать фабрику, чтобы попытаться справиться с созданием декодеров; однако мне повезло, и нужный мне функционал можно было реализовать с помощью встроенного декодера полей длины.

<bean id="lengthFieldDecoder"
      class="org.apache.camel.component.netty4.ChannelHandlerFactories"
      factory-method="newLengthFieldBasedFrameDecoder">
  <argument value="10000" /> <!-- Max Frame Length -->
  <argument value="0" />     <!-- Length Field Offset -->
  <argument value="4" />     <!-- Length Field Length -->
  <argument value="0" />     <!-- Length Adjustment -->
  <argument value="4" />     <!-- Initial Bytes to Strip -->
</bean>

<camelContext trace="false" xmlns="http://camel.apache.org/schema/blueprint">
  <route>
    <from uri="netty4:tcp://localhost:9999?decoder=#lengthFieldDecoder&amp;
               clientMode=true&amp;sync=false"
          id="Netty4 TCP Client" />
    <log message="Message (Binary): ${body}" id="Log Binary"/>
  </route>
</camelContext>
person Iain Smith    schedule 10.11.2015