2015-04-16 2 views
3

Я создал прокси-верблюд, который принимает SOAP (через HTTP) и RESTful запросы и пересылает их на правильный веб-сервис. Camel не знает о структуре сообщений, он не знает WSDL или что-то еще, он просто знает, является ли это SOAP или нет в соответствии с заголовком http. Конечной точки CXF нет.Camel return simple SoapFault без CXF/Spring-ws

Далее он обрабатывает некоторые виды обработки. Исключение может происходить внутри, например, когда служба не найдена или URL недействителен. Есть ли простой способ вернуть действительный SOAPFault прямо с этого верблюда? Я попытался написать простой процессор, который называется onException. Это выглядит следующим образом:

.choice().when().header("SOAP").processRef(ExceptionToSoapProcessor()) 

Процессор, который должен превратить любое исключение в SoapFault выглядит следующим образом

@Override 
public void process(Exchange exchange) throws Exception { 
    Exception exception = (Exception) exchange.getProperty(Exchange.EXCEPTION_CAUGHT); 
    Integer responseCode = (Integer) exchange.getOut().getHeader(Exchange.HTTP_RESPONSE_CODE); 

    QName qName = SoapFault.FAULT_CODE_SERVER; 
    if (responseCode != null && responseCode < 500) { 
     qName = SoapFault.FAULT_CODE_CLIENT; 
    } 

    SoapFault fault = new SoapFault(exception.getMessage(), qName); 
    Message outMessage = exchange.getOut(); 
    outMessage.setHeader(Message.RESPONSE_CODE, 500); 
    outMessage.setFault(true); 
    outMessage.setBody(fault); 

    exchange.setException(null); 
    exchange.removeProperty(Exchange.EXCEPTION_CAUGHT); 
    exchange.setProperty(Exchange.EXCEPTION_HANDLED, true); 
} 

Но теперь я не понимаю, как я мобилизует его, реакция выглядит следующим образом :

org.apache.cxf.binding.soap.SoapFault: Unauthorized 

("Несанкционированный" является фактическим сообщение)

PS: Я раньше использовал dataformat SOAP, но, как уже упоминалось, у меня нет ServiceInterface в этом Camel.

ответ

5

Я бы переместил обработку сценария ошибки на блок onException(). Таким образом, вы можете «объявить» какое-то поведение, например, маркировать исключение, как обрабатываемое. ИМХО делает его немного чище.

Простое возвращение ошибки SOAP не приведет к действительному ответу SOAP. Вы должны построить полную структуру сообщений. Я не думаю, что есть текстовый конвертер для SOAP-сообщений в текстовый поток, поэтому вы должны сами маршалировать ответ SOAP.

Это код, я использую, чтобы сделать работу:

<onException> 
    <exception>java.lang.Exception</exception> 
    <handled> 
     <constant>true</constant> 
    </handled> 
    <bean beanType="some.package.WSHelper" method="createSOAPFaultServerError" /> 
</onException> 


public static String createSOAPFaultServerError(final Exception cause) { 
    String result = null; 
    LOG.error("Creating SOAP fault, hiding original cause from client:", cause); 
    try { 
     SOAPMessage message = MessageFactory.newInstance().createMessage(); 
     SOAPEnvelope envelope = message.getSOAPPart().getEnvelope(); 
     SOAPBody body = message.getSOAPBody(); 
     SOAPFault fault = body.addFault(); 
     fault.setFaultCode("Server"); 
     fault.setFaultString("Unexpected server error."); 
     Detail detail = fault.addDetail(); 
     Name entryName = envelope.createName("message"); 
     DetailEntry entry = detail.addDetailEntry(entryName); 
     entry.addTextNode("The server is not able to complete the request. Internal error."); 

     result = soapMessage2String(message); 
    } catch (Exception e) { 
     LOG.error("Error creating SOAP Fault message", e); 
    } 

    return result; 
} 

private static String soapMessage2String(final SOAPMessage message) throws SOAPException, IOException { 
    String result = null; 

    ByteArrayOutputStream outStream = new ByteArrayOutputStream(); 
    message.writeTo(outStream); 
    result = new String(outStream.toByteArray(), StandardCharsets.UTF_8); 

    return result; 
} 

НТН

+0

Это именно то, что я искал, спасибо! – Chrisport