Статьи

Конечная точка REST для интеграции с использованием Apache Camel

REST — это архитектурный стиль, используемый для организации ресурсов, и при применении к службам на основе HTTP позволяет создавать независимые, не связанные с состоянием, масштабируемые службы. Методы HTTP, заголовки HTTP и mime-типы позволяют разработчикам реализовать стиль REST. Фреймворки, такие как Jersey и Fuse Services Framework (Apache CXF), можно использовать для ускорения разработки и развертывания сервисов, пытающихся реализовать стиль RESTful, и в этом сообщении в блоге я хотел бы обсудить, как создать бэкэнд ресурса, который полагается на интеграцию, предоставляемую Fuse Mediation Router, также известным как Apache Camel .

Кроме того, ссылка, которую я спрятал в углублениях моих закладок, может представлять интерес для тех, кто интересуется, действительно ли ваша архитектура действительно RESTful или просто в том же стиле RPC с высокой связью, который REST пытается облегчить. Рой Филдинг, который написал свою диссертацию по REST, активно утверждает, что гиперссылки в представлениях ресурсов являются обязательными для стилей REST, и еще больше проясняет неопределенности, связанные с реализацией REST.

Исходный код этого примера можно найти в моем репозитории github.

Fuse Mediation Router — это усиленная версия Apache Camel корпоративного уровня FuseSource , предоставляющая удобный DSL для описания интеграций, посредников и маршрутизации. Это бесплатно, с открытым исходным кодом, и имеет лицензию Apache. Для тех, кто не знаком с Mediation Router / Camel, ознакомьтесь с введением Джона Ансти (соавтора Camel в действии ) о зоне интеграции предприятия DZone: Apache Camel: Integration Nirvana .

Мы будем использовать посреднический маршрутизатор, чтобы помочь написать простую интеграцию между конечной точкой REST и файлами ресурсов в файловой системе. Я буду использовать компонент camel-cxfrs для предоставления конечной точки REST и буду использовать компонент camel-file для чтения каталога в файловой системе. Цель этого примера — описать конфигурацию, необходимую для предоставления интерфейса REST через посреднический маршрутизатор, каким-либо образом интегрироваться с бэкэндом, преобразовать данные в соответствующий ответ REST и отправить ответ обратно.

Для начала давайте сосредоточимся на том, как настроить конечную точку REST. Для этого вы должны создать ресурс JAX-RS, который описывает методы java, которые будут действовать как конечные точки REST. Этот пример кода требует знакомства с Java API для веб-служб RESTful, также известного как JAX-RS. Для тех, кто незнаком, вот несколько хороших руководств, которые помогут понять JAX-RS.

@Path("/customerservice/")
public class CustomerServiceResource {
 
// NOTE: The instance member variables will not be available to the
// Camel Exchange. They must be used as method parameters for them to
// be made available
@Context
private UriInfo uriInfo;
 
public CustomerServiceResource() {
}
 
@GET
@Path("/customers/{id}/")
@Produces("text/xml")
public Customer getCustomer(@PathParam("id") String id) {
    return null;
}
 
@PUT
@Path("/customers/")
public Response updateCustomer(Customer customer) {
    return null;
}
 
}

Как вы можете видеть, аннотации — это аннотации JAX-RS, которые описывают операции, методы HTTP и типы MIME, связанные с конечной точкой REST. Обратите внимание, что все возвращаемые значения равны нулю, так как этот класс фактически не будет использоваться для обработки запросов, поступающих в конечную точку; маршруты-посредники будут отвечать за обработку и ответ. Тем не менее, обратите внимание, что элементы экземпляра недоступны для обменов посреднического маршрутизатора, т. Е. Любые элементы экземпляра, введенные с помощью аннотаций JAX-RS @Context, не будут доступны. Чтобы сделать их доступными, добавьте их в качестве параметров в ваши методы.

Объявление конечной точки CXF-RS с помощью посреднического маршрутизатора можно выполнить одним из двух способов: непосредственно в конфигурации конечной точки, например так:

 
from("cxfrs://http://localhost:9090/route?resourceClasses=com.fusesource.samples.CustomerServiceResource")

Создание этого непосредственно в конфигурации требует меньше конфигурации XML, но предлагает ограниченную гибкость. Другой вариант — создать отдельный компонент, отвечающий за конечную точку, а затем сослаться на него в конфигурации конечной точки:

from("cxfrs:bean:rsServer")

Компонент rsServer должен быть определен в контексте верблюда. Пример:

<cxf:rsServer id="rsServer" address="http://localhost:9090/route"
              serviceClass="com.fusesource.samples.CustomerServiceResource"/>

Этот подход позволяет отделить конфигурацию конечной точки и позволяет быть более быстрым и менее подробным в конфигурации конечной точки. Обе опции показаны в примере кода, хотя используется первая опция.

Вот и вся конфигурация, необходимая для предоставления конечной точки REST посредническим маршрутизатором. Довольно просто. Следующим шагом является использование файла из файловой системы на основе того, что поступает из конечной точки REST. Содержимое файла будет возвращено клиенту вызова REST. Для этого мы используем компонент camel-file и обогащаем Exchange вызовом pollEnrich в DSL:

.setHeader(Exchange.FILE_NAME, simple("test-${body}.xml"))
.pollEnrich("file:src/data?noop=true", 1000, new CustomerEnricher())

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

Наконец, мы можем добавить к маршруту дополнительную обработку:

.process(new CustomerServiceProcessor())

Цель этого примера, как описано выше, состоит в том, чтобы показать, как сконфигурировать конечную точку и подключить ее к дальнейшей обработке посреднического маршрутизатора. Обратите внимание, что шаблон обмена сообщениями (MEP) для конечной точки REST является InOut и ожидает ответа. Пример не предназначен для того, чтобы быть законченным комплексным решением, поскольку оно будет варьироваться в зависимости от предполагаемой функциональности. Пожалуйста, обратите внимание выше на ссылки на обсуждения Роя о том, что такое REST, а что нет.

Если я что-то пропустил или вам нужно больше пояснений по поводу примера, напишите мне комментарий, и мы сможем обсудить.