From aa59f40c07f468ebd1e36bb6498e31dc204dffe0 Mon Sep 17 00:00:00 2001 From: Otavio Rodolfo Piske Date: Fri, 23 Oct 2026 16:05:27 +0200 Subject: [PATCH 1/2] CAMEL-26108: camel-avro-rpc - the component should configure all options on the endpoint Co-Authored-By: Claude Opus 5.5 (1M context) (cherry picked from commit 55b266d9403f6d35e08752726156a8cf9bdc4387) --- .../camel/component/avro/AvroListener.java | 2 +- .../avro/AvroHttpConsumerHostTest.java | 80 +++++++++++++++++++ .../avro/spi/JettyHttpServerFactory.java | 5 ++ .../avro/spi/AvroRpcHttpServerFactory.java | 19 +++++ 4 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java index 9c15ec5076506..24380e08d1d81 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/main/java/org/apache/camel/component/avro/AvroListener.java @@ -84,7 +84,7 @@ private static Server createServer(AvroConfiguration configuration, CamelContext if (AVRO_HTTP_TRANSPORT.equalsIgnoreCase(configuration.getTransport().name())) { AvroRpcHttpServerFactory factory = ResolverHelper.resolveMandatoryService(camelContext, "avro-rpc-http-server-factory", AvroRpcHttpServerFactory.class, "camel-avro-rpc"); - return factory.create(responder, configuration.getPort()); + return factory.create(responder, configuration.getHost(), configuration.getPort()); } else if (AVRO_NETTY_TRANSPORT.equalsIgnoreCase(configuration.getTransport().name())) { return new NettyServer(responder, new InetSocketAddress(configuration.getHost(), configuration.getPort())); } else { diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java new file mode 100644 index 0000000000000..53253fc2d534f --- /dev/null +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java @@ -0,0 +1,80 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.camel.component.avro; + +import java.io.IOException; +import java.net.Inet4Address; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.NetworkInterface; +import java.net.Socket; +import java.net.SocketException; + +import org.apache.camel.builder.RouteBuilder; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +/** + * The http consumer listens on the host of the endpoint, as the netty consumer does. + */ +public class AvroHttpConsumerHostTest extends AvroTestSupport { + + @Override + protected RouteBuilder createRouteBuilder() { + return new RouteBuilder() { + @Override + public void configure() { + from("avro:http:127.0.0.1:" + avroPort + + "/getName?protocolClassName=org.apache.camel.avro.test.TestReflection") + .setBody(constant("Camel")); + } + }; + } + + @Test + public void testListensOnConfiguredHostOnly() throws Exception { + InetAddress other = findNonLoopbackAddress(); + assumeTrue(other != null, "No non-loopback IPv4 address available"); + + assertDoesNotThrow(() -> connect(InetAddress.getByName("127.0.0.1"))); + assertThrows(IOException.class, () -> connect(other)); + } + + private void connect(InetAddress address) throws IOException { + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(address, avroPort), 2000); + } + } + + private static InetAddress findNonLoopbackAddress() throws SocketException { + return NetworkInterface.networkInterfaces() + .filter(nic -> { + try { + return nic.isUp() && !nic.isLoopback(); + } catch (SocketException e) { + return false; + } + }) + .flatMap(NetworkInterface::inetAddresses) + .filter(address -> address instanceof Inet4Address && !address.isLoopbackAddress()) + .findFirst() + .orElse(null); + } +} diff --git a/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java b/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java index c74128f9840fb..ed7045a2f2dcb 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java +++ b/components/camel-avro-rpc/camel-avro-rpc-jetty/src/main/java/org/apache/camel/component/avro/spi/JettyHttpServerFactory.java @@ -33,4 +33,9 @@ public class JettyHttpServerFactory implements AvroRpcHttpServerFactory { public Server create(SpecificResponder responder, int port) throws IOException { return new HttpServer(responder, port); } + + @Override + public Server create(SpecificResponder responder, String host, int port) throws IOException { + return new HttpServer(responder, host, port); + } } diff --git a/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java b/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java index c53fde1fcffe6..f013a5149a610 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java +++ b/components/camel-avro-rpc/camel-avro-rpc-spi/src/main/java/org/apache/camel/component/avro/spi/AvroRpcHttpServerFactory.java @@ -25,5 +25,24 @@ */ public interface AvroRpcHttpServerFactory { + /** + * Creates a server that listens on the given port on all interfaces. + */ Server create(SpecificResponder responder, int port) throws Exception; + + /** + * Creates a server that listens on the given host and port. + * + * The default implementation ignores the host and calls {@link #create(SpecificResponder, int)}, so an + * implementation should override it to listen on the host the endpoint is configured with. + * + * @param responder the responder + * @param host the host or address to listen on + * @param port the port to listen on + * @return the server + * @since 4.24 + */ + default Server create(SpecificResponder responder, String host, int port) throws Exception { + return create(responder, port); + } } From 8717b3809bd409884097bf7092a88bc5610a0597 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 26 Oct 2026 09:17:58 +0000 Subject: [PATCH 2/2] CAMEL-26108: camel-avro-rpc - address review comments Use 127.0.0.2 in the test instead of looking up a non-loopback address, so it always runs, and remove trailing whitespace in the upgrade guide. Co-Authored-By: Claude Opus 5.5 (1M context) (cherry picked from commit aa2c0c3687da0ee0bfedd8c0721a844b5c8a535d) --- .../avro/AvroHttpConsumerHostTest.java | 33 +++---------------- 1 file changed, 5 insertions(+), 28 deletions(-) diff --git a/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java index 53253fc2d534f..7706cc6d58dca 100644 --- a/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java +++ b/components/camel-avro-rpc/camel-avro-rpc-component/src/test/java/org/apache/camel/component/avro/AvroHttpConsumerHostTest.java @@ -17,19 +17,14 @@ package org.apache.camel.component.avro; import java.io.IOException; -import java.net.Inet4Address; -import java.net.InetAddress; import java.net.InetSocketAddress; -import java.net.NetworkInterface; import java.net.Socket; -import java.net.SocketException; import org.apache.camel.builder.RouteBuilder; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; import static org.junit.jupiter.api.Assertions.assertThrows; -import static org.junit.jupiter.api.Assumptions.assumeTrue; /** * The http consumer listens on the host of the endpoint, as the netty consumer does. @@ -49,32 +44,14 @@ public void configure() { } @Test - public void testListensOnConfiguredHostOnly() throws Exception { - InetAddress other = findNonLoopbackAddress(); - assumeTrue(other != null, "No non-loopback IPv4 address available"); - - assertDoesNotThrow(() -> connect(InetAddress.getByName("127.0.0.1"))); - assertThrows(IOException.class, () -> connect(other)); + public void testListensOnConfiguredHostOnly() { + assertDoesNotThrow(() -> connect("127.0.0.1")); + assertThrows(IOException.class, () -> connect("127.0.0.2")); } - private void connect(InetAddress address) throws IOException { + private void connect(String host) throws IOException { try (Socket socket = new Socket()) { - socket.connect(new InetSocketAddress(address, avroPort), 2000); + socket.connect(new InetSocketAddress(host, avroPort), 2000); } } - - private static InetAddress findNonLoopbackAddress() throws SocketException { - return NetworkInterface.networkInterfaces() - .filter(nic -> { - try { - return nic.isUp() && !nic.isLoopback(); - } catch (SocketException e) { - return false; - } - }) - .flatMap(NetworkInterface::inetAddresses) - .filter(address -> address instanceof Inet4Address && !address.isLoopbackAddress()) - .findFirst() - .orElse(null); - } }