Apache Camel с загрузкой Spring

1. Обзор

По своей сути Apache Camel - это механизм интеграции, который, проще говоря, может использоваться для облегчения взаимодействия между широким и разнообразным спектром технологий.

Эти мосты между сервисами и технологиями называются маршрутами. Маршруты реализованы в движке ( CamelContext ), и они взаимодействуют с помощью так называемых «сообщений обмена».

2. Зависимости Maven

Для начала нам нужно включить зависимости для Spring Boot, Camel, Rest API с Swagger и JSON:

  org.apache.camel camel-servlet-starter ${camel.version}   org.apache.camel camel-jackson-starter ${camel.version}   org.apache.camel camel-swagger-java-starter ${camel.version}   org.apache.camel camel-spring-boot-starter ${camel.version}   org.springframework.boot spring-boot-starter-web ${spring-boot-starter.version}  

Последние версии зависимостей Apache Camel можно найти здесь.

3. Главный класс

Давайте сначала создать Spring загрузки приложений :

@SpringBootApplication @ComponentScan(basePackages="com.baeldung.camel") public class Application { public static void main(String[] args) { SpringApplication.run(Application.class, args); } }

4. Конфигурации Camel для загрузки Spring

Теперь давайте настроим наше приложение с помощью Spring, начиная с файлов конфигурации (свойств).

Например, давайте настроим журнал для нашего приложения в файле application.properties в src / main / resources :

logging.config=classpath:logback.xml camel.springboot.name=MyCamel server.address=0.0.0.0 management.address=0.0.0.0 management.port=8081 endpoints.enabled = true endpoints.health.enabled = true

В этом примере показан файл application.properties, который также задает путь к конфигурации Logback. Установив для IP-адреса значение «0.0.0.0», мы полностью ограничиваем доступ администратора и управления на веб-сервере, предоставляемом Spring Boot. Кроме того, мы обеспечиваем необходимый сетевой доступ к конечным точкам наших приложений, а также к конечным точкам проверки работоспособности.

Другой файл конфигурации - application.yml . В нем мы добавим некоторые свойства, которые помогут нам вводить значения в маршруты наших приложений:

server: port: 8080 camel: springboot: name: ServicesRest management: port: 8081 endpoints: enabled: false health: enabled: true quickstart: generateOrderPeriod: 10s processOrderPeriod: 30s

5 . Настройка сервлета Camel

Один из способов начать использовать Camel - зарегистрировать его как сервлет, чтобы он мог перехватывать HTTP-запросы и перенаправлять их в наше приложение.

Как упоминалось ранее, начиная с версии Camel 2.18 и ниже, мы можем воспользоваться нашим application.yml , создав параметр для нашего конечного URL. Позже он будет внедрен в наш Java-код:

baeldung: api: path: '/camel'

Возвращаясь к нашему классу Application , нам нужно зарегистрировать сервлет Camel в корне нашего контекстного пути, который будет вставлен из ссылки baeldung.api.path в application.yml при запуске приложения:

@Value("${baeldung.api.path}") String contextPath; @Bean ServletRegistrationBean servletRegistrationBean() { ServletRegistrationBean servlet = new ServletRegistrationBean (new CamelHttpTransportServlet(), contextPath+"/*"); servlet.setName("CamelServlet"); return servlet; }

Начиная с версии 2.19 Camel, эта конфигурация была удалена, поскольку CamelServlet по умолчанию установлен на «/ camel» .

6. Построение маршрута

Давайте начнем составлять маршрут с расширения класса RouteBuilder из Camel и установки его как @Component, чтобы процедура сканирования компонентов могла найти его во время инициализации веб-сервера:

@Component class RestApi extends RouteBuilder { @Override public void configure() { CamelContext context = new DefaultCamelContext(); restConfiguration()... rest("/api/")... from("direct:remoteService")... } }

В этом классе мы переопределяем метод configure () из класса RouteBuilder Camel .

Camel всегда нужен экземпляр CamelContext - основной компонент, в котором хранятся входящие и исходящие сообщения.

В этом простом примере достаточно DefaultCamelContext, поскольку он просто связывает сообщения и маршрутизирует в него, как и служба REST, которую мы собираемся создать.

6.1. RestConfiguration () Route

Затем мы создаем объявление REST для конечных точек, которые планируем создать в методе restConfiguration () :

restConfiguration() .contextPath(contextPath) .port(serverPort) .enableCORS(true) .apiContextPath("/api-doc") .apiProperty("api.title", "Test REST API") .apiProperty("api.version", "v1") .apiContextRouteId("doc-api") .component("servlet") .bindingMode(RestBindingMode.json)

Здесь мы регистрируем контекстный путь с помощью нашего внедренного атрибута из файла YAML. Та же самая логика была применена к порту нашего приложения. CORS включен, что позволяет использовать эту веб-службу на нескольких сайтах. Режим привязки позволяет и преобразует аргументы в наш API.

Затем мы добавляем документацию Swagger к ранее установленным URI, заголовку и версии. Когда мы создаем методы / конечные точки для нашей веб-службы REST, документация Swagger будет автоматически обновляться.

Этот контекст Swagger сам по себе является маршрутом Camel, и мы можем увидеть некоторую техническую информацию о нем в журнале сервера во время процесса запуска. Документация нашего примера по умолчанию находится по адресу // localhost: 8080 / camel / api-doc.

6.2. Остальное () Маршрут

Теперь давайте реализуем вызов метода rest () из метода configure (), указанного выше:

rest("/api/") .id("api-route") .consumes("application/json") .post("/bean") .bindingMode(RestBindingMode.json_xml) .type(MyBean.class) .to("direct:remoteService");

Этот метод довольно прост для тех, кто знаком с API. Идентификатор является определение маршрута внутри CamelContext . Следующая строка определяет тип MIME. Режим привязки определяется здесь, чтобы показать, что мы можем установить режим для restConfiguration () .

Метод post () добавляет операцию к API, генерируя конечную точку « POST / bean », в то время как MyBean (обычный Java-компонент с идентификатором Integer и именем String ) определяет ожидаемые параметры.

Точно так же HTTP-действия, такие как GET, PUT и DELETE, также доступны в форме get () , put () , delete () .

Наконец, метод to () создает мост к другому маршруту. Здесь он сообщает Camel искать внутри своего контекста / движка другой маршрут, который мы собираемся создать - который назван и обнаружен значением / id « direct:… », совпадающим с маршрутом, определенным в методе from () .

6.3. Из () маршрута с преобразованием ()

При работе с Camel маршрут получает параметры, а затем преобразует, преобразует и обрабатывает эти параметры. После этого он отправляет эти параметры другому маршруту, который перенаправляет результат на желаемый вывод (файл, базу данных, SMTP-сервер или ответ REST API).

В этой статье мы создаем только другой маршрут внутри метода configure (), который мы переопределяем. Это будет конечный маршрут для нашего последнего маршрута to () :

from("direct:remoteService") .routeId("direct-route") .tracing() .log(">>> ${body.id}") .log(">>> ${body.name}") .transform().simple("Hello ${in.body.name}") .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

Метод from () следует тем же принципам и имеет многие из тех же методов, что и метод rest () , за исключением того, что он использует сообщения контекста Camel. Это причина для параметра « direct-route », который создает ссылку на вышеупомянутый метод rest (). To () .

Доступны многие другие преобразования , в том числе извлечение в виде примитивов (или объектов) Java и отправка их на уровень сохраняемости. Обратите внимание, что маршруты всегда считываются из входящих сообщений, поэтому связанные маршруты будут игнорировать исходящие сообщения.

Наш пример готов, и мы можем его попробовать:

  • Запустите командную строку: mvn spring-boot: run
  • Do a POST request to //localhost:8080/camel/api/bean with header parameters: Content-Type: application/json, and a payload {“id”: 1,”name”: “World”}
  • We should receive a return code of 201 and the response: Hello, World

6.4. The SIMPLE Scripting Language

The example outputs logging using the tracing() method. Notice that we've used the ${} placeholders; these are part of a scripting language that belongs to Camel called SIMPLE. It is applied to messages that are exchanged over the route, like the body of the in-message.

In our example, we are using SIMPLE to output to the log the bean attributes that are inside the Camel message body.

We can also use it to do simple transformations as well, as was shown with the transform() method.

6.5. The from() Route With process()

Let's do something more meaningful, such as calling a service layer to return processed data. SIMPLE isn't meant for heavy data processing, so let's replace the transform() with a process() method:

from("direct:remoteService") .routeId("direct-route") .tracing() .log(">>> ${body.id}") .log(">>> ${body.name}") .process(new Processor() { @Override public void process(Exchange exchange) throws Exception { MyBean bodyIn = (MyBean) exchange.getIn().getBody(); ExampleServices.example(bodyIn); exchange.getIn().setBody(bodyIn); } }) .setHeader(Exchange.HTTP_RESPONSE_CODE, constant(200));

This allows us to extract the data into a bean, the same one previously defined on the type() method, and process it in our ExampleServices layer.

Since we set the bindingMode() to JSON previously, the response already is in a proper JSON format, generated based on our POJO. This implies that for an ExampleServices class:

public class ExampleServices { public static void example(MyBean bodyIn) { bodyIn.setName( "Hello, " + bodyIn.getName() ); bodyIn.setId(bodyIn.getId() * 10); } }

The same HTTP request now returns with a response code 201 and body: {“id”: 10,”name”: “Hello, World”}.

7. Conclusion

With a few lines of code, we managed to create a relatively complete application. All dependencies are built, managed and run automatically with a single command. Moreover, we can create APIs that tie together all sorts of technologies.

This approach is also very container friendly, resulting in a very lean server environment that can be easily replicated on demand. The extra configuration possibilities can easily be incorporated into a container template configuration file.

Этот пример REST можно найти на GitHub.

Наконец, помимо API filter () , process () , transform () и marshall () , в Camel доступны многие другие шаблоны интеграции и манипуляции с данными:

  • Шаблоны интеграции Camel
  • Руководство пользователя Camel
  • Верблюд простой язык