Camel:如何在处理CXF请求后返回有效的SOAP响应

时间:2013-03-04 14:35:29

标签: soap cxf response apache-camel envelope

所以,我有一个公开Webservice端点的路由。收到请求后,我将一些信息发送到某些队列,我想向原始呼叫者返回一个响应。 响应是一个枚举,可以有4个值(OK,NULL,RPT,NOK)

我可以在soapUI中获得响应,但它不在有效的SOAP信封中。这意味着当在Java或.Net中处理响应时,会抛出异常,说没有有效的Envelope命名空间。

我如何保证发送的响应是SOAPMessage?

要生成我的回复消息,我有这个方法:

public OnClientEventResponse process(Message message){
    if(message.getBody().toString().contains("OnClientEventResponse")){
        return (OnClientEventResponse) message.getBody();
    }
    OnClientEventResponse resp = new OnClientEventResponse();
    resp.setReturn(Response.OK);
    return resp;
}

在soapUi中我得到了这个:

<onClientEventResponse>
   <Response>OK</Response>
</onClientEventResponse>

但我需要这样的东西:

<soap:Envelope xmlns:soap="blabla/soap/envelope">
<soap:Headers/>
<soap:Body>
    <onClientEventResponse>
       <Response>OK</Response>
    </onClientEventResponse>
<soap:Body>
<soap:Envelope>

我的Webservice接口类是:

@WebService(name = "ClientEventNotifierEndpoint")
public interface ClientEventNotifierEndpoint {

@WebMethod(operationName = "onClientEvent", action = "urn:OnClientEvent")
@WebResult(name = "return")
public Response onClientEvent(@WebParam(name = "readerCode") String readerCode, @WebParam(name = "clientRfid") String clientRfid,
        @WebParam(name = "eventType") String eventType, @WebParam(name = "dateTime") Date dateTime);

}

2 个答案:

答案 0 :(得分:4)

我相信你不再等待这个答案,但是因为我刚刚完成了寻找同样的事情,所以你需要做的是:

package com.xxxxx.esb.invoice.processors;

import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.dom.DOMSource;

import org.apache.camel.Exchange;
import org.apache.camel.Processor;
import org.apache.camel.component.cxf.CxfPayload;
import org.apache.camel.converter.jaxp.XmlConverter;
import org.apache.cxf.binding.soap.SoapHeader;
import org.apache.log4j.Logger;
import org.w3c.dom.Document;

import com.xxxxx.esb.invoice_service_spec.ProcessFileResponse;

/**
 * @author pantinor
 * 
 * 
 * 
 */
public class SoapResponseProcessor implements Processor {
    private static final String ROOT_NODE = "processFileResponse";
    private static final String NAMESPACE = "http://www.xxxxx.com/Esb/invoice-service    -spec";
    private static final String OK = "OK";
    protected static final Logger LOG = Logger
            .getLogger(SoapResponseProcessor.class);

    @Override
    public void process(Exchange exchange) throws Exception {
        //lots a support classes to serialize my answer
        List<Source> outElements = new ArrayList<Source>();
        XmlConverter converter = new XmlConverter();
        StringWriter writer = new StringWriter();
        JAXBContext context = JAXBContext
                .newInstance(ProcessFileResponse.class);
        Marshaller m = context.createMarshaller();

        //build my business answer
        ProcessFileResponse result = new ProcessFileResponse();
        result.setReturn(OK);

        //serialize the answer

        //the following is required since the JAXB annotated class does not include     the XMLRoot annotation
        m.marshal(new JAXBElement<ProcessFileResponse>(new QName(NAMESPACE,
                ROOT_NODE), ProcessFileResponse.class, result), writer);

        Document outDocument = converter.toDOMDocument(writer.toString());
        outElements.add(new DOMSource(outDocument.getDocumentElement()));

        //use camel class cxf class to produce a payload that the cxf component can     consume for the answer
        CxfPayload<SoapHeader> responsePayload = new CxfPayload<SoapHeader>(
                null, outElements, null);

        //write the anwer
        exchange.getIn().setBody(responsePayload);


    }

}    

答案 1 :(得分:0)

我不确定它是否适用于驼峰,但尝试将此注释添加到您的界面。

@WebService(name = "ClientEventNotifierEndpoint")
@SOAPBinding(style = SOAPBinding.Style.RPC)

public interface ClientEventNotifierEndpoint {