2015-09-25 1 views
0

Я новичок в ESB в целом, однако мне было поручено реализовать TCP-считыватель, который выводит данные XML в JBoss Fuse. Я пробовал несколько методов с ограниченным успехом.Декодирование двоичных данных из 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 [email protected]3a0f1 
is not @Shareable or an ChannelHandlerFactory instance. The decoder cannot safely be used. 

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

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

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

+0

попробовать добавить '@ Shareable' к пользовательскому кодеком класса –

+0

Согласно API, это не так просто: **«Имейте в виду, что подклассы ByteToMessageDecoder НЕ ДОЛЖНЫ аннотацию @Sharable.»** [ Link] (http://netty.io/4.0/api/io/netty/handler/codec/ByteToMessageDecoder.html) –

ответ

0

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

+0

Спасибо за помощь. Означает ли это, что декодер на основе ByteToMessageDecoder является неправильным подходом и вместо этого я должен идти через ChannelHandlerFactory? Или можно использовать декодер, но только в определенных обстоятельствах? –

0

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

<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> 
Смежные вопросы