В этой статье рассмотрим как можно использовать вебсервисы cxf с использованием Apache Camel в качестве транспорта.
Наш роутер будет работать с сообщением как с JAXB Объктом.
Первым делом создадим Maven-проект на основе camel-archetype-java. У вас должен быть установлен соответствующий плагин для Eclipse
Зададим необходимые значения Group Id и Artifact ID
В результате у нас будет сгенерирована следующая структура проекта:
В качестве контейнера для вебсервисов, будем использовать Jetty.
Добавляем все необходимые зависимости.
А именно:
camel-cxf
camel-jetty
camel-jaxb
cxf-rt-transports-http-jetty
Вот так вот выглядит часть pom.xml моего проекта с добавлеными зависимостями:
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-cxf</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jetty</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
<artifactId>camel-jaxb</artifactId>
<version>2.9.1</version>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-transports-http-jetty</artifactId>
<version>2.5.1</version>
</dependency>
Проверяем что проект собирается: pom.xml/Run As/Maven buildMaven скачает необходимые зависимости и выведет следующее:
[INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
Создадим простую wsdl для нашего веб-сервиса и разместим ее в нашем проекте
simplews\src\main\resources\wsdl\simplews.wsdl
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<wsdl:definitions xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://com.bssys/simplews/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="simplews"
targetNamespace="http://com.bssys/simplews/">
<wsdl:types>
<xsd:schema targetNamespace="http://com.bssys/simplews/">
<xsd:element name="UserOperation" type="tns:RequestBO" />
<xsd:element name="UserOperationResponse" type="tns:ResponseBO" />
<xsd:complexType name="RequestBO">
<xsd:sequence>
<xsd:element name="user" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
<xsd:complexType name="ResponseBO">
<xsd:sequence>
<xsd:element name="account" type="xsd:string"
minOccurs="1" maxOccurs="unbounded" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
</wsdl:types>
<wsdl:message name="UserOperationRequest">
<wsdl:part element="tns:UserOperation" name="parameters" />
</wsdl:message>
<wsdl:message name="UserOperationResponse">
<wsdl:part element="tns:UserOperationResponse" name="parameters" />
</wsdl:message>
<wsdl:portType name="simplews">
<wsdl:operation name="UserOperation">
<wsdl:input message="tns:UserOperationRequest" />
<wsdl:output message="tns:UserOperationResponse" />
</wsdl:operation>
</wsdl:portType>
<wsdl:binding name="simplewsSOAP" type="tns:simplews">
<soap:binding style="document"
transport="http://schemas.xmlsoap.org/soap/http" />
<wsdl:operation name="UserOperation">
<soap:operation soapAction="http://com.bssys/simplews/UserOperation" />
<wsdl:input>
<soap:body use="literal" />
</wsdl:input>
<wsdl:output>
<soap:body use="literal" />
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:service name="simplews">
<wsdl:port binding="tns:simplewsSOAP" name="simplewsSOAP">
<soap:address location="http://www.example.org/" />
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Интерфейс простой. На входе имя пользователя, на выходе список его неких аккаунтов.RequestBO это запрос
ResponseBO это ответ
Этого уже достаточно чтобы реализовать вебсервис. Генерации классов не требуется. Для разработки логики на Camel будет необходимо вручную работать с SOAP пакетом.
Чуть позже будем использовать jaxb чтобы избавиться от рутинной работы с xml и сконцентрироваться на бизнес-логике.
Заглянем в spring контекст, сгенерированый по умолчанию
scr/main/java/META-INF/spring/camel-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- 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. -->
<!-- Configures the Camel Context -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>com.bssys.simplews</package>
</camelContext>
</beans>
Добавляем необходимые namespaсe для cxf и прописываем cxf-beanВот что у нас получилось:
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:cxf="http://camel.apache.org/schema/cxf"
xsi:schemaLocation="
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
<cxf:cxfEndpoint id="SimpleWSEndpoint" address="http://0.0.0.0:8083/SimpleWS"
xmlns:tns="http://www.bssys.org/simplews/" wsdlURL="/wsdl/simplews.wsdl" />
<bean id="SimpleLogic" class="com.bssys.simplews.SimpleLogicProcess"/>
<camelContext xmlns="http://camel.apache.org/schema/spring">
<package>com.bssys.simplews</package>
</camelContext>
</beans>
Мы добавили namespace
xmlns:cxf="http://camel.apache.org/schema/cxf"
schemaLocation
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
и собственно cxfEndpoint
<cxf:cxfEndpoint id="SimpleWSEndpoint" address="http://0.0.0.0:9093/SimpleWS"
xmlns:tns="http://com.bssys/simplews/" wsdlURL="/wsdl/simplews.wsdl" />
id- это имя конечной точки, которое будет использоваться в Camel routeaddress- адрес, по которому будет подниматься веб-сервис
xmlns:tns="http://www.bssys.org/simplews/" - 'это namespace нашей wsdl
wsdlURL=локальный путь к wsdl
Теперь откроем MyRouteBuilder.java, который также был сгенерирован при создании проекта, удалим сгенерированый роутинг и напишем следующее
from("cxf:bean:SimpleWSEndpoint?dataFormat=PAYLOAD").log("${body}");
Следует обратить внимание на параметер dataFormat=PAYLOAD, который задает тип работы endpoint. Почитать об этом можно в документации
Теперь проверим Запускаем и проверяем работу:
[ main] MainSupport INFO Apache Camel 2.9.1 starting [ main] SpringCamelContext INFO Apache Camel 2.9.1 (CamelContext: camel-1) is starting [ main] ManagementStrategyFactory INFO JMX enabled. Using ManagedManagementStrategy. [ main] ultManagementLifecycleStrategy INFO StatisticsLevel at All so enabling load performance statistics [ main] AnnotationTypeConverterLoader INFO Found 3 packages with 15 @Converter classes to load [ main] DefaultTypeConverter INFO Loaded 169 core type converters (total 169 type converters) [ main] AnnotationTypeConverterLoader INFO Loaded 5 @Converter classes [ main] DefaultTypeConverter INFO Loaded additional 23 type converters (total 192 type converters) in 0.016 seconds [ main] CxfEndpoint WARN The endpoint/port name of cxf://bean:SimpleWSEndpoint?dataFormat=PAYLOAD is empty, cxf will try to load the first one in wsdl for you. [ main] CxfEndpoint WARN The service name of cxf://bean:SimpleWSEndpoint?dataFormat=PAYLOAD is empty, cxf will try to load the first one in wsdl for you. [ main] ReflectionServiceFactoryBean INFO Creating Service {http://com.bssys/simplews/}simplews from WSDL: /wsdl/simplews.wsdl [ main] ServerImpl INFO Setting the server's publish address to be http://0.0.0.0:8083/SimpleWS [ main] Server INFO jetty-7.5.4.v20111024 [ main] AbstractConnector INFO Started SelectChannelConnector@0.0.0.0:8083 STARTING [ main] ContextHandler INFO started o.e.j.s.h.ContextHandler{,null} [ main] SpringCamelContext INFO Route: route1 started and consuming from: Endpoint[cxf://bean:SimpleWSEndpoint?dataFormat=PAYLOAD] [ main] SpringCamelContext INFO Total 1 routes, of which 1 is started. [ main] SpringCamelContext INFO Apache Camel 2.9.1 (CamelContext: camel-1) started in 1.422 seconds
Можно проверить доступность WSDL по адресу http://127.0.0.1:8083/SimpleWS/?wsdl
Запустив стандартный SOAP UI, Webservice explorer в Eclipse или любой другой клиент и выполнив запрос, увидим в логах следующее:
<sim:UserOperation xmlns:sim="http://com.bssys/simplews/">
<user>Sergey</user>
</sim:UserOperation>
Рассмотрим что произошло. При старте приложения была поднята конечная точка для cxf-webservices. Apache Camel слушает конечную точку, и при поступлении запроса выводит тело запроса в лог.
Заметили что наш сервис не возвращает ответа? Теперь воспользуемся JAXB чтобы разработать бизнес логику нашего вебсервиса!
Сгенерируем необходимые артефакты с помощью команды:
xjc -p com.bssys.simplews -wsdl simplews.wsdl
parsing a schema... compiling a schema... com\bssys\simplews\ObjectFactory.java com\bssys\simplews\RequestBO.java com\bssys\simplews\ResponseBO.java com\bssys\simplews\package-info.java
Скопируем полученные исходники в папку с исходниками.
Создаем Processor который будет выполнять всю работу.
package com.bssys.simplews;
import java.util.List;
import javax.xml.bind.JAXBElement;
import org.apache.camel.Exchange;
import org.apache.camel.Processor;
public class SimpleLogicProcess implements Processor{
@Override
public void process(Exchange exchange) throws Exception {
// TODO Auto-generated method stub
RequestBO body = exchange.getIn().getBody(RequestBO.class);
ObjectFactory factory = new ObjectFactory();
ResponseBO responseBO = factory.createResponseBO();
List list = responseBO.getAccount();
list.add("account1");
list.add("account2");
list.add("account3");
JAXBElement userOperationResponse = factory.createUserOperationResponse(responseBO);
exchange.getOut().setBody(userOperationResponse);
}
}
Наш Processor берет поступающий запрос как объект класса RequestBO. Потом создает класс ответа ResponseBO, заполняет его и устанавливает как тело ответа.
С помощью JAXB мы работаем с xml как с java-объектами, в этом вся прелесть!
Для того чтобы его можно было использовать в Camel-route добавим описание в контекст:
<bean id="SimpleLogic" class="com.bssys.simplews.SimpleLogicProcess"/>
Теперь немного модифицируем роутинг MyRouteBuilder.java, для работы с jaxb.
Вот такой итоговый роутинг у нас получился:
// TODO create Camel routes here.
JaxbDataFormat jaxb = new JaxbDataFormat("com.bssys.simplews");
from("cxf:bean:SimpleWSEndpoint?dataFormat=PAYLOAD").unmarshal(jaxb).log("${body}").processRef("SimpleLogic").marshal(jaxb);
Запускаем. и проверяем с помощью любого клиента.Вот результат работы в SOAP UI.
Удачи
Комментариев нет:
Отправить комментарий