Preface
I have a parser utility that takes in a valid JSON object from a UDP feed, encodes it, and returns a byte[]
. This byte[]
is to be sent to Kafka.
Issue at hand
I cannot get the byte[]
to send without getting the error. It keeps seeming that I am not setting the body or something. However, for "New Body", I do get a byte[]
printed
[INFO ] 2021-02-09 14:30:37 | (SpecialRouter) - New body: [B@526447c2
RouteBuilder
camelContext.addRoutes(new RouteBuilder() {
public void configure() throws Exception {
from("netty:udp://0.0.0.0:30244")
.routeId("Router")
.convertBodyTo(String.class, "UTF-8")
.choice()
.when(simple("${body} contains 'specialWord'"))
.log("---------- [ Received special message ] ----------")
.log("${body}")
.process(new MyProcessor(new MyJsonParser().getInstance()))
.setHeader(KafkaConstants.KEY, constant("MyProcessor"))
.log("New body: ${body}")
.choice()
.when(body().isEqualTo("skip"))
.log(">>>>> skipping")
.when(body().isNotEqualTo("skip"))
.log("Sending to kafka: ")
// .convertBodyTo(byte[].class, "UTF-8")
.to(generateKafkaEndpoint())
.log("DONE sending");
}
});
Kafka Endpoint Generator
private static String generateKafkaEndpoint() {
final StringBuilder sb = new StringBuilder();
sb.append("kafka:{{topic_name}}");
sb.append("?brokers={{kafka_server}}:{{kafka_port}}");
sb.append("&clientId=TestClient");
sb.append("&valueSerializer=org.apache.kafka.common.serialization.ByteArraySerializer");
sb.append("&keySerializer=org.apache.kafka.common.serialization.StringSerializer");
sb.append("&requestRequiredAcks=all");
return sb.toString();
}
Processor
class MyProcessor implements Processor {
private final Parser<byte[], Special> parser;
public MyProcessor(Parser<byte[], Special> parser) {
this.parser = parser;
}
@Override
public void process(Exchange exchange) throws Exception {
String specialJson = exchange.getIn().getBody(String.class);
Gson gson = new Gson();
Special wrapper = gson.fromJson(specialJson, Special.class);
byte[] parsedSpecial = parser.parse(wrapper);
System.out.println(">>> parsedSpecial: " + new String(parsedSpecial));
System.out.println(">>> byte[] size: " + parsedSpecial.length);
if (parsedSpecial.length > 0) {
// using getMessage() instead of getOut() since getOut() is deprecated
exchange.getMessage().setBody(parsedSpecial);
} else {
exchange.getMessage().setBody("skip");
}
}
}
Error
[WARN ] 2021-02-09 14:30:37 | (NettyConsumer) - Caused by: [org.apache.camel.CamelExchangeException - Cannot write response to null. Exchange[07C825B4A7863D1-0000000000000008]. Caused by: [io.netty.handler.codec.EncoderException - DatagramPacketStringEncoder must produce at least one message.]]
org.apache.camel.CamelExchangeException: Cannot write response to null. Exchange[07C825B4A7863D1-0000000000000008]. Caused by: [io.netty.handler.codec.EncoderException - DatagramPacketStringEncoder must produce at least one message.]
at org.apache.camel.component.netty.handlers.ServerResponseFutureListener.operationComplete(ServerResponseFutureListener.java:53)
at org.apache.camel.component.netty.handlers.ServerResponseFutureListener.operationComplete(ServerResponseFutureListener.java:35)
at io.netty.util.concurrent.DefaultPromise.notifyListener0(DefaultPromise.java:578)
at io.netty.util.concurrent.DefaultPromise.notifyListenersNow(DefaultPromise.java:552)
at io.netty.util.concurrent.DefaultPromise.notifyListeners(DefaultPromise.java:491)
at io.netty.util.concurrent.DefaultPromise.setValue0(DefaultPromise.java:616)
at io.netty.util.concurrent.DefaultPromise.setFailure0(DefaultPromise.java:609)
at io.netty.util.concurrent.DefaultPromise.tryFailure(DefaultPromise.java:117)
at io.netty.util.internal.PromiseNotificationUtil.tryFailure(PromiseNotificationUtil.java:64)
at io.netty.channel.AbstractChannelHandlerContext.notifyOutboundHandlerException(AbstractChannelHandlerContext.java:814)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:719)
at io.netty.channel.AbstractChannelHandlerContext.invokeWriteAndFlush(AbstractChannelHandlerContext.java:764)
at io.netty.channel.AbstractChannelHandlerContext$WriteTask.run(AbstractChannelHandlerContext.java:1071)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at java.lang.Thread.run(Thread.java:748)
Caused by: io.netty.handler.codec.EncoderException: DatagramPacketStringEncoder must produce at least one message.
at io.netty.handler.codec.MessageToMessageEncoder.write(MessageToMessageEncoder.java:96)
at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
... 8 more
The issue was with the consumer URL. Since the consumer has sync=true
by default, this sets it to request-response - meaning it was trying to send a response back to a remote address I didn't have setup (that is what the null
was).
So to fix this, all I had to do was add ?sync=false
to the URL in the "from" to make it netty:udp://0.0.0.0:30244?sync=false
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.