Apache Camel с Spring Boot

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 Boot Application :

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

4. Конфигурации на камили за пролетно зареждане

Нека сега конфигурираме нашето приложение с 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 Servlet

Един от начините да започнете да използвате 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 () Път

След това създаваме 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. Най- ID е идентифицирането на маршрута във вътрешността на CamelContext . Следващият ред определя типа MIME. Режимът на обвързване е дефиниран тук, за да покаже, че можем да зададем режим на restConfiguration () .

The post() method adds an operation to the API, generating a “POST /bean” endpoint, while the MyBean (a regular Java bean with an Integer id and String name) defines the expected parameters.

Similarly, HTTP actions such as GET, PUT and DELETE are all available as well in the form of get(), put(), delete().

Finally, the to() method creates a bridge to another route. Here it tells Camel to search inside its context/engine to another route that we're going to create – which is named and detected by the value/id “direct: …“, matching the route defined in the from() method.

6.3. The from() Route With transform()

When working with Camel, a route receives parameters and then converts, transforms and process these parameters. After that, it sends these parameters to another route that forwards the result to the desired output (a file, a database, an SMTP server or a REST API response).

In this article, we only create another route inside the configure() method that we are overriding. It will be the destination route for our last to() route:

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));

The from() method follows the same principles and has many of the same methods as the rest() method, except that it consumes from the Camel context messages. This is the reason for the parameter “direct-route“, that creates a link to the aforementioned method rest().to().

Many other conversions are available, including extraction as Java primitives (or objects) and sending it down to a persistence layer. Notice that the routes always read from incoming messages, so that chained routes will ignore outgoing messages.

Our example is ready, and we can try it:

  • Run the prompt command: 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 Ръководство за потребителя
  • Камила ПРОСТО Език