This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new 0419afd39bf CAMEL-24351: camel-platform-http-starter - the request
mapping must not be lazy (#1874)
0419afd39bf is described below
commit 0419afd39bf1eb03aa5c9353b5ae63765729209c
Author: henrik242 <[email protected]>
AuthorDate: Tue Aug 4 16:15:55 2026 +0200
CAMEL-24351: camel-platform-http-starter - the request mapping must not be
lazy (#1874)
@Lazy was added in 4.21.0, replacing an ObjectProvider that deferred the
CamelContext lookup. CamelRequestHandlerMapping registers itself as a
PlatformHttpListener and is only notified of endpoints created after it
exists, so creating it on first demand is unordered with respect to
CamelContext startup. When Camel starts first the mapping learns about no
endpoint at all, and every platform-http route answers 404 while reporting
itself as started. 4.18.3 and 4.20.0 both instantiated the bean eagerly.
---
.../SpringBootPlatformHttpAutoConfiguration.java | 15 +++-
.../SpringBootPlatformHttpEagerMappingTest.java | 85 ++++++++++++++++++++++
2 files changed, 97 insertions(+), 3 deletions(-)
diff --git
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpAutoConfiguration.java
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpAutoConfiguration.java
index ce1cdbd0682..f317e79169b 100644
---
a/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpAutoConfiguration.java
+++
b/components-starter/camel-platform-http-starter/src/main/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpAutoConfiguration.java
@@ -22,13 +22,13 @@ import
org.apache.camel.component.platform.http.spi.PlatformHttpEngine;
import org.apache.camel.spring.boot.ComponentConfigurationProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.ObjectProvider;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import
org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import
org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.thread.Threading;
import org.springframework.boot.web.server.autoconfigure.ServerProperties;
import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Lazy;
import org.springframework.core.env.Environment;
import org.springframework.core.task.SimpleAsyncTaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@@ -90,9 +90,18 @@ public class SpringBootPlatformHttpAutoConfiguration {
return new SpringBootPlatformHttpEngine(port, executor);
}
+ /**
+ * The mapping registers itself as a {@link
org.apache.camel.component.platform.http.PlatformHttpListener} and is
+ * only notified of endpoints created after it exists, so it must be
eager. A lazy mapping is created on first
+ * demand, which is unordered with respect to CamelContext startup: if
Camel starts first, every platform-http
+ * endpoint is already registered and the mapping never learns about any
of them, leaving all of them unreachable
+ * with a 404 while the routes report themselves as started. CamelContext
is taken as an ObjectProvider and
+ * resolved inside the method to avoid the circular dependency that
injecting it directly would create.
+ */
@Bean
- @Lazy
- public CamelRequestHandlerMapping
platformHttpEngineRequestMapping(PlatformHttpEngine engine, CamelContext
camelContext) {
+ public CamelRequestHandlerMapping platformHttpEngineRequestMapping(
+ PlatformHttpEngine engine, ObjectProvider<CamelContext>
camelContextProvider) {
+ CamelContext camelContext = camelContextProvider.getObject();
PlatformHttpComponent component =
camelContext.getComponent("platform-http", PlatformHttpComponent.class);
return new CamelRequestHandlerMapping(component, engine);
}
diff --git
a/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpEagerMappingTest.java
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpEagerMappingTest.java
new file mode 100644
index 00000000000..26ecdc0fd38
--- /dev/null
+++
b/components-starter/camel-platform-http-starter/src/test/java/org/apache/camel/component/platform/http/springboot/SpringBootPlatformHttpEagerMappingTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.platform.http.springboot;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.spring.boot.CamelAutoConfiguration;
+import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
+import org.assertj.core.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ConfigurableApplicationContext;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * {@link CamelRequestHandlerMapping} registers itself as a platform-http
listener and is only notified of endpoints
+ * created after it exists. It must therefore be instantiated eagerly:
creating it on first demand is unordered with
+ * respect to CamelContext startup, and when Camel starts first the mapping
never learns about the endpoints that
+ * already exist, so every platform-http route is answered with 404 while
reporting itself as started.
+ * <p>
+ * That the context starts at all also covers the circular dependency the
ObjectProvider avoids.
+ */
+@EnableAutoConfiguration
+@CamelSpringBootTest
+@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
classes = { CamelAutoConfiguration.class,
+ SpringBootPlatformHttpEagerMappingTest.class,
+ SpringBootPlatformHttpEagerMappingTest.TestConfiguration.class,
+ PlatformHttpComponentAutoConfiguration.class,
SpringBootPlatformHttpAutoConfiguration.class })
+public class SpringBootPlatformHttpEagerMappingTest {
+
+ @Autowired
+ ConfigurableApplicationContext applicationContext;
+
+ @Autowired
+ CamelRequestHandlerMapping mapping;
+
+ @Test
+ void mappingMustNotBeLazy() {
+ Assertions.assertThat(applicationContext.getBeanFactory()
+
.getBeanDefinition("platformHttpEngineRequestMapping").isLazyInit())
+ .isFalse();
+ }
+
+ @Test
+ void endpointIsMapped() {
+ assertThat(mapping.getHandlerMethods().keySet().stream()
+ .map(RequestMappingInfo::getPathPatternsCondition)
+ .anyMatch(condition -> condition != null &&
condition.getPatternValues().contains("/eager")))
+ .isTrue();
+ }
+
+ @Configuration
+ public static class TestConfiguration {
+
+ @Bean
+ public RouteBuilder routeBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+ from("platform-http:/eager").routeId("eager-route")
+ .setBody().constant("alive");
+ }
+ };
+ }
+ }
+}