We finally solved it by adding another decoder which returns a byte[]
@BindToRegistry
public ChannelHandlerFactory epdecoderbyte() {
return ChannelHandlerFactories.newByteArrayDecoder("tcp");
}
________________________________
From: Gawie van der Merwe <[email protected]>
Sent: Thursday, 07 March 2024 10:51
To: [email protected] <[email protected]>
Subject: Netty TCP Producer- unable to get byte array from response
Hi guys,
We are upgrading from camel 2.12.2 --> 3.21.2. And we have been stuck on Netty
TCP.
On the old version we recieved a response as "BodyType:
org.jboss.netty.buffer.BigEndianHeapChannelBuffer"
Now we get it as "PooledSlicedByteBuf(freed)". For the life of me are not able
to get the bytes from the ByteBuf. It seems the camel netty component has
already read the bytes. How can we get the bytes from the response? We tried
retain()/release()/unwrap()/etc. Below a simple example to reproduce.
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[ main] MainSupport INFO Apache
Camel (Main) 3.21.2 is starting
[ main] BaseMainSupport INFO Classpath
scanning enabled from base package: com.adumo.test.netty
[ main] BaseMainSupport INFO
Auto-configuration summary
[ main] BaseMainSupport INFO
[application.properties] camel.main.routesIncludePattern=routes/*.xml
[ main] BaseMainSupport INFO
[application.properties] camel.main.name=MyXmlCamel
[ main] BaseMainSupport INFO
[application.properties] camel.main.routesReloadEnabled=true
[ main] BaseMainSupport INFO
[application.properties]
camel.main.routesReloadDirectory=src/main/resources/routes
[ main] BaseMainSupport INFO
[application.properties] camel.main.routesReloadPattern=*.xml
[ main] AbstractCamelContext INFO Apache
Camel 3.21.2 (MyXmlCamel) is starting
[ main] NettyComponent INFO Creating
shared NettyConsumerExecutorGroup with 17 threads
[ main] eWatcherResourceReloadStrategy INFO Live
route reloading enabled (directory: src/main/resources/routes)
[ main] BaseMainSupport INFO
Property-placeholders summary
[ main] BaseMainSupport INFO
[application.properties] hi=Hello
[ main] BaseMainSupport INFO
[application.properties] bye=Bye
[ main] AbstractCamelContext INFO Routes
startup (started:1)
[ main] AbstractCamelContext INFO
Started test-route1 (direct://test1)
[ main] AbstractCamelContext INFO Apache
Camel 3.21.2 (MyXmlCamel) started in 305ms (build:42ms init:139ms start:124ms
JVM-uptime:1s)
Sending
bufRes PooledSlicedByteBuf(freed)
lenght 635
io.netty.util.IllegalReferenceCountException: refCnt: 0
at
io.netty.buffer.AbstractByteBuf.ensureAccessible(AbstractByteBuf.java:1454)
at
io.netty.buffer.AbstractByteBuf.checkReadableBytes0(AbstractByteBuf.java:1440)
at
io.netty.buffer.AbstractByteBuf.checkReadableBytes(AbstractByteBuf.java:1428)
at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:895)
at io.netty.buffer.AbstractByteBuf.readBytes(AbstractByteBuf.java:903)
at com.adumo.test.netty.MyApplication$1.run(MyApplication.java:38)
at java.base/java.lang.Thread.run(Thread.java:829)
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.apache.camel.ProducerTemplate;
import org.apache.camel.main.Main;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
public final class MyApplication {
private MyApplication() {
}
public static void main(String[] args) throws Exception {
Main main = new Main(MyApplication.class);
Thread sendThread = new Thread(new Runnable() {
@Override
public void run() {
try {
Thread.sleep(2000);
System.out.println("Sending");
ProducerTemplate pdt = main.getCamelTemplate();
Path path = Paths.get("isoAuthReq");
byte[] data = Files.readAllBytes(path);
ByteBuf bufReq = Unpooled.wrappedBuffer(data);
ByteBuf bufRes = (ByteBuf)
pdt.requestBody("netty:tcp://x.x.x.x:49002?decoders=#epdecoder&encoders=#epencoder&disconnect=false&sync=true&reuseAddress=true&keepAlive=true&synchronous=true&requestTimeout=8000",
bufReq);
int lenght = bufRes.readableBytes();
System.out.println("lenght " + lenght);
byte[] bytes = new byte[lenght];
bufRes.readBytes(bytes);
System.out.println("Result " + bytes);
} catch (Exception e) {
e.printStackTrace();
}
}
});
sendThread.start();
main.run(args);
System.out.println("Done");
}
}
Here is my encoder / decoder:
@BindToRegistry
public LengthFieldPrepender epencoder() {
// this will create an instance of this bean with the name of the
method (eg epencoder)
return new LengthFieldPrepender(2);
}
@BindToRegistry
public ChannelHandlerFactory epdecoder() {
// this will create an instance of this bean with the name of the
method (eg epdecoder)
return ChannelHandlerFactories.newLengthFieldBasedFrameDecoder(4096, 0,
2, 0, 2);
}
[__tpx__]