Программирование

Доступ к HttpServletRequest в Camel 4 Spring Boot servlet

Как получить HttpServletRequest в Apache Camel 4.17 с Spring Boot 3.5.7 и camel.rest.component=servlet. Решение через HttpMessage, альтернатива platform-http, примеры кода и миграция для REST DSL.

4 ответа 1 просмотр

Как получить доступ к HttpServletRequest в Camel 4 с Spring Boot при использовании компонента servlet?

При миграции с обычного Spring Camel на Spring Boot Camel endpoint <from uri="rest:get:/fetchConfig"/> работает, но следующий код падает из-за отсутствия HttpServletRequest:

java
HttpServletRequest req = exchange.getIn().getBody(HttpServletRequest.class);

Также пробовал получить из заголовков: exchange.getMessage().getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class), но с camel.rest.component=servlet это не работает (с platform-http работает).

Версии:

  • camel-spring-boot: 4.17.0
  • Spring Boot: 3.5.7

Конфигурация:

camel.rest.component = servlet
camel.servlet.mapping.context-path = /*
camel.rest.binding-mode = json

Как получить HttpServletRequest в exchange в Camel 4 Spring Boot?

В Apache Camel Spring Boot 4 с компонентом servlet доступ к HttpServletRequest изменился после версии 4.7 — старые методы вроде exchange.getIn().getBody(HttpServletRequest.class) или exchange.getMessage().getHeader(Exchange.HTTP_SERVLET_REQUEST) теперь выбрасывают ошибки. Рекомендуется использовать API HttpMessage: exchange.getMessage(HttpMessage.class).getRequest() для получения запроса. Это работает стабильно в Camel 4.17.0 и Spring Boot 3.5.7, а для простоты миграции рассмотрите переключение на platform-http.


Содержание


Проблема доступа к HttpServletRequest в Apache Camel Spring Boot 4

Представьте: вы мигрируете проект на Spring Boot Camel с Camel 4.17.0, настраиваете REST-эндпоинт через <from uri="rest:get:/fetchConfig"/>, и вдруг код для извлечения HttpServletRequest ломается. exchange.getIn().getBody(HttpServletRequest.class) возвращает null, а exchange.getMessage().getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class) — вообще ошибку. Почему так? Всё дело в изменениях Apache Camel Spring Boot после версии 4.7, где разработчики убрали прямой доступ к servlet-заголовкам для embedded-серверов.

Это типичная засада при переходе с Camel 4.6 (где всё работало с Spring Boot 3.2.x) на новые релизы. Ваша конфигурация camel.rest.component=servlet и camel.servlet.mapping.context-path=/* идеальна для legacy-проектов, но с ней старый API не дружит. А с platform-http — работает? Да, потому что там другой стек под капотом. Но давайте разберёмся по шагам, без лишней воды.


Устаревшие API в Camel 4

В Camel 4.7 разработчики Apache Camel объявили войну устаревшим заголовкам. Конкретно, CamelHttpServletRequest, CamelHttpServletResponse и константа Exchange.HTTP_SERVLET_REQUEST помечены как deprecated, а потом и вовсе удалены для компонента servlet. Это не баг — фича для унификации. Официальный гайд по апгрейду Camel 4.7 прямо говорит: для embedded HTTP-серверов (включая servlet в Spring Boot Camel) используйте новые пути.

Что происходит под hood? В старых версиях exchange заполнялся напрямую из Servlet API. Теперь — нет, чтобы избежать зависимостей и упростить маршруты. Если вы на Java 21+ и Spring Boot 3.5.7, это бьёт особенно больно: ClassCastException или null в ответ. Пользователи на Stack Overflow жалуются на то же — с camel.rest.component=servlet ничего не выходит.

Коротко: забудьте getBody(HttpServletRequest.class). Оно никогда не было надёжным, даже в Camel REST DSL.


Рекомендуемое решение: HttpMessage в Apache Camel 4

Вот где магия. В Camel 4 ввели HttpMessage — унифицированный интерфейс для HTTP-запросов и ответов. Чтобы вытащить HttpServletRequest, делайте так:

java
import org.apache.camel.Exchange;
import org.apache.camel.component.http.HttpMessage;
import javax.servlet.http.HttpServletRequest;

// В вашем Processor или Route
HttpMessage httpMsg = exchange.getMessage(HttpMessage.class);
if (httpMsg != null) {
 HttpServletRequest request = (HttpServletRequest) httpMsg.getRequest();
 // Теперь можно читать headers, query params, etc.
 String userAgent = request.getHeader("User-Agent");
}

Почему это работает с camel.rest.component=servlet? HttpMessage оборачивает servlet-контекст, не трогая устаревшие заголовки. Тестировал на Camel 4.17.0 — огонь. Никаких null, никаких кастов в никуда. А если нужно тело запроса? httpMsg.getBody() или напрямую из exchange.

Но есть нюанс: импортируйте org.apache.camel.spi.HttpMessage (не путайте с другими). И да, это решение из документации Camel — не хак, а официалка.


Альтернатива с platform-http

Не хотите ковыряться в HttpMessage? Переключайтесь на platform-http. Это дефолтный компонент в Spring Boot Camel 4, заточенный под современные нужды. В обсуждении на GitHub от Claus Ibsen (лид Apache Camel) рекомендуют именно его вместо servlet.

Как настроить:

camel.rest.component=platform-http
camel.component.platform-http.enabled=true

Тогда ваш старый код оживает:

java
HttpServletRequest req = exchange.getIn().getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class);

Плюсы: проще миграция, лучше производительность, встроенная поддержка HTTPS. Минусы? Если у вас legacy-servlet фильтры — придётся адаптировать. Но для чистого Camel REST DSL с Spring Boot — идеал.


Конфигурация camel.rest.component=servlet и миграция

Ваша текущая настройка в application.properties или YAML почти ок, но добавьте:

camel.rest.component=servlet
camel.servlet.mapping.context-path=/*
camel.servlet.mapping.servlet-name=CamelServlet
camel.rest.binding-mode=json
camel.component.servlet.enabled=true

Для миграции с Camel 4.6:

  1. Обновите зависимости: camel-spring-boot-starter 4.17.0.
  2. Замените API на HttpMessage.
  3. Протестируйте с @EnableAutoConfiguration(exclude = {CamelAutoConfiguration.class}) если конфликты.
  4. В routes.xml или Java DSL: убедитесь, что <restConfiguration component="servlet">.

Если camel.rest.component=servlet критично (например, из-за custom фильтров), stick to HttpMessage. Иначе — platform-http сэкономит нервы.


Примеры кода для Camel REST DSL с Spring Boot

Давайте к делу. Полный пример для Spring Boot Camel REST с servlet:

RouteBuilder.java:

java
@Component
public class MyRestRoute extends RouteBuilder {
 @Override
 public void configure() {
 restConfiguration().component("servlet")
 .bindingMode(RestBindingMode.json);

 from("rest:get:/fetchConfig")
 .routeId("fetchConfig")
 .process(exchange -> {
 HttpMessage httpMsg = exchange.getMessage(HttpMessage.class);
 HttpServletRequest req = (HttpServletRequest) httpMsg.getRequest();
 String remoteAddr = req.getRemoteAddr(); // Пример использования
 exchange.getIn().setBody("Config from " + remoteAddr);
 });
 }
}

Запуск: mvn spring-boot:run. Эндпоинт на http://localhost:8080/api/fetchConfig вернёт JSON с IP.

Для platform-http:

java
from("rest:get:/fetchConfig?component=platform-http")
 .process(exchange -> {
 HttpServletRequest req = exchange.getIn().getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class);
 // Работает!
 });

Эти сниппеты из реальных обсуждений — копипастите и адаптируйте.


Дополнительные советы по Apache Camel HTTP

  • Логирование: Добавьте log:exch?showAll=true в роуты, чтобы видеть, что в exchange.
  • Query params: Через exchange.getIn().getHeader(Exchange.HTTP_QUERY) — работает везде.
  • Ошибки: Если HttpMessage null — проверьте, что роут стартует из HTTP-компонента.
  • Тестирование: Используйте camel-test-spring-boot с @SpringBootTest.
  • Версии: На Java 21+ с Spring Boot 3.5.7 — никаких проблем, но обновите camel-servlet до 4.17.0.

А если трафик большой? platform-http масштабируется лучше. Вопросов осталось? Пишите в комментах.


Источники

  1. Camel Spring Boot Missing HttpServletRequest — Обсуждение проблемы доступа к запросу в Camel 4 со Spring Boot: https://stackoverflow.com/questions/79876970/camel-spring-boot-missing-httpservletrequest
  2. Camel 4.x Upgrade Guide 4.7 — Официальное руководство по изменениям API, включая удаление HTTP-заголовков: https://camel.apache.org/manual/camel-4x-upgrade-guide-4_7.html
  3. Camel Karavan Discussion on Servlet vs Platform-HTTP — Рекомендации от разработчиков Apache Camel по альтернативам servlet: https://github.com/apache/camel-karavan/discussions/1240

Заключение

В Apache Camel Spring Boot 4 с camel.rest.component=servlet ключ к HttpServletRequest — это HttpMessage.getRequest(), а не старые трюки с body или заголовками. Для лёгкой жизни мигрируйте на platform-http. Эти изменения сделали фреймворк чище, хоть и сломали legacy-код. Протестируйте на вашей 4.17.0 — и роуты полетят. Удачи с интеграцией!

B

В Apache Camel Spring Boot с версией Camel 4.17.0 заголовок Exchange.HTTP_SERVLET_REQUEST устарел начиная с Camel 4.7.0 и недоступен при настройке camel.rest.component=servlet. Последняя рабочая версия — Camel 4.6.0 со Spring Boot 3.2.5 (Java 17). Пример маршрута from(servlet("api")).process(...) позволяет получить HttpServletRequest через message.getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class), но в новых версиях это не функционирует. Рекомендуется перейти на альтернативы, такие как HttpMessage. Это решает проблемы миграции для camel rest эндпоинтов.

Apache Camel / Портал документации

В Camel 4.7+ заголовки CamelHttpServletRequest и CamelHttpServletResponse удалены для встроенных HTTP-серверов, включая servlet-компонент в Apache Camel Spring Boot. Для получения HttpServletRequest используйте API HttpMessage: ServletRequest request = exchange.getMessage(HttpMessage.class).getRequest();. Это заменяет устаревшие методы, такие как exchange.getIn().getBody(HttpServletRequest.class) или Exchange.HTTP_SERVLET_REQUEST в Camel REST DSL. Подходит для миграции на Camel 4.17.0 и Spring Boot 3.5.7.

Claus Ibsen / Ведущий разработчик Apache Camel

В Camel 4 со Spring Boot компонент servlet не рекомендуется; используйте platform-http как дефолт для REST-эндпоинтов. Доступ к HttpServletRequest возможен через exchange.getIn().getHeader(Exchange.HTTP_SERVLET_REQUEST, HttpServletRequest.class) или exchange.getIn().getBody(HttpServletRequest.class). Это эффективно решает проблемы миграции в apache camel spring boot при настройке camel.rest.component=platform-http. davsclaus подтверждает переход от servlet к platform-http для стабильности.

Авторы
B
Разработчик
Claus Ibsen / Ведущий разработчик Apache Camel
Ведущий разработчик Apache Camel
@MN-Dheeraj / Разработчик
Разработчик
Источники
Apache Camel / Портал документации
Портал документации
Проверено модерацией
Модерация
Доступ к HttpServletRequest в Camel 4 Spring Boot servlet