2010년 4월 4일 일요일

cxf와 apache-camel 연동하기

ESB 작업을 진행하고 있다. frontend channel은 cxf를 이용하여 웹서비스로 구현하고 있다.
cxf로 전달된 웹서비스를 enterprise intergration 엔진인 apache-camel과 연동하여 처리하고자 한다.
계속해서 자료를 찾아보고 있지만 일단 아래에 설명하는 것과 같이 작업하면 cxf와 camel이 연동하는 것을 확인했다.

spring 설정파일 작성



<?xml version="1.0" encoding="UTF-8"?>

<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://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://camel.apache.org/schema/cxf http://camel.apache.org/schema/cxf/camel-cxf.xsd
http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
">


<import resource="classpath:META-INF/cxf/cxf.xml"/>
<import resource="classpath:META-INF/cxf/cxf-extension-soap.xml" />
<import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

<bean id = "testBean" class="org.apache.camel.example.cxf.provider.TesterBean" />


<cxf:cxfEndpoint id="objectEndpoint"
serviceClass="org.apache.camel.example.cxf.amf.GreeterImpl"
address="/ObjectService"
endpointName="s:SoapOverHttpRouter"
serviceName="s:SOAPService"
wsdlURL="WEB-INF/wsdl/hello_world.wsdl"
xmlns:s="http://apache.org/hello_world_soap_http"/>
<camelContext id="test_context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxf:bean:objectEndpoint"/>
<to uri="bean:testBean?method=processObject"/>
</route>
</camelContext>


<cxf:cxfEndpoint id="orderEndpoint"
serviceClass="demo.order.OrderProcessImpl"
address="/OrderService"
endpointName="s:OrderProcessImplPort"
serviceName="s:OrderProcessImplService"
wsdlURL="classpath:wsdl/demo/order.wsdl"
xmlns:s="http://order.demo/"/>
<camelContext id="order_test_context" xmlns="http://camel.apache.org/schema/spring">
<route>
<from uri="cxf:bean:orderEndpoint"/>
<to uri="bean:testBean?method=processOrder"/>
</route>
</camelContext>


</beans>



TesterBean 클래스는 웹서비스 요청이 route되는 클래스다. 위의 설정 파일을 예로 든다면 ObjectService로 요청이 들어오면 testBean의 processObject 메소드로 전달된다. 메서드의 파라미터로는 Exchange 객체가 전달되는데, Exchange객체는 in(request), out(response), fault(exception)을 처리할 수 있도록 설계되었다고 생각하면 된다.
address는 서비스의 URL과 관련이 있으며, serviceName은 wsdl의 service name(service엘리먼트의 name 속성)과 동일하며 endpointName은 wsdl의 port name(port 엘리먼트의 name속성)과 동일하다.
wsdl파일은 위와 같이 WEB-INF 하위에서 지정할 수 도 있으며 classpath에서도 지정할 수 있다.
serviceClass는 웹서비스가 구현되어 있는 클래스명을 지정해야 한다. wsdl만으로 웹서비스를 제공해야 할 경우에는 cxf-codegen-plugin을 사용하여 서비스 클래스를 생성해야 한다.
서비스 클래스가 @WebService인 경우에는 exchange.getIn()의 바디가 자바 객체가 리턴되고 @WebServiceProvider로 제공되는 경우에는 SOAPMessage가 리턴된다.
라우팅될때 method명을 지정하면 클래스의 특정 메서드로 라우팅이 된다.
라우팅 메서드가 리턴 값이 있는 경우에는 파라미터로 전달되는 Exchange의 out에 값을 설정하더라도 리턴되는 값이 응답으로 전달되고, 리턴타입이 void인 경우에는 Exchange의 out에 설정한 값이 응답으로 전달된다.

TesterBean




package org.apache.camel.example.cxf.provider;

import java.util.List;

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPEnvelope;
import javax.xml.soap.SOAPException;
import javax.xml.soap.SOAPMessage;
import javax.xml.soap.SOAPPart;

import org.apache.camel.Exchange;
import org.apache.cxf.message.MessageContentsList;


public class TesterBean {

public SOAPMessage processSOAP(Exchange exchange) {
System.out.println(getClass().getName() + " - processSOAP()");

SOAPMessage soapMessage = (SOAPMessage)exchange.getIn().getBody(List.class).get(0);
if (soapMessage == null) {
System.out.println("Incoming null message detected...");
return createDefaultSoapMessage("Greetings from Apache Camel!!!!", "null");
}

try {
SOAPPart sp = soapMessage.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
SOAPBody sb = se.getBody();
String requestText = sb.getFirstChild().getTextContent();
System.out.println(requestText);
return createDefaultSoapMessage("Greetings from Apache Camel!!!!", requestText);
} catch (Exception e) {
e.printStackTrace();
return createDefaultSoapMessage("Greetings from Apache Camel!!!!", e.getClass().getName());
}
}

public String processObject(Exchange exchange) {
System.out.println("body: " + exchange.getIn().getBody(List.class).get(0).getClass().getName());
System.out.println("body value: " + exchange.getIn().getBody(List.class).get(0));
return "dummy";
}

public String processOrder(Exchange exchange) {
System.out.println("body: " + exchange.getIn().getBody(List.class).get(0).getClass().getName());
System.out.println("body value: " + exchange.getIn().getBody(List.class).get(0));
// if return type is void
//exchange.getOut().setBody("zzz");
return "dummy";

}

public static SOAPMessage createDefaultSoapMessage(String responseMessage, String requestMessage) {
System.out.println(TesterBean.class.getName() + " - createDefaultSoapMessage()");
try {
SOAPMessage soapMessage = MessageFactory.newInstance().createMessage();
SOAPBody body = soapMessage.getSOAPPart().getEnvelope().getBody();

QName payloadName = new QName("http://apache.org/hello_world_soap_http/types", "greetMeResponse",
"ns1");

SOAPBodyElement payload = body.addBodyElement(payloadName);

SOAPElement message = payload.addChildElement("responseType");

message.addTextNode(responseMessage + " Request was " + requestMessage);
return soapMessage;
} catch (SOAPException e) {
e.printStackTrace();
throw new RuntimeException(e);
}

}

}


댓글 없음:

댓글 쓰기