I am very new to camel. I want to pull some xml file from a sftp location and feed the content to existing REST endpoint. Below is my configuration,
<route id="xml.FOEBRE">
<from uri="<sftp server uri>"/>
<marshal>
<string/>
</marshal>
<setHeader headerName="Content-Type">
<constant>application/xml</constant>
</setHeader>
<doTry>
<to uri="<REST URI>?httpMethod=POST"/>
<bean ref="myListener" method="onPushSuccess"/>
<doCatch>
<exception>java.lang.Exception</exception>
<!--<log message="error : ${exception.message}" loggingLevel="ERROR"/>-->
<process ref="globalExceptionListener"/>
</doCatch>
</doTry>
</route>
I am able to call it, but I want to capture the response status and body of the REST call. In my success processor I have written,
Message message = exchange.getIn();
int status = message.getHeader(Exchange.HTTP_RESPONSE_CODE, Integer.class);
LOG.debug("Response status : {}", status);
LOG.debug("Payload successfully sent to securecargo");
String body = message.getBody(String.class);
LOG.debug("Response Body : {}", body);
This code is returning me the proper response body. But the same code (in catch listener) is not working when the status code is 400. I have two question,
How to catch this response body when status code is 400? My processor in catch block is never invoked.
Why I getting this body in exchange.getIn(), not in exchange.getOut()?
Note: My REST service returns two status, 201 for success and 400 for failure. I know my service returns a JSON payload both in success and failre scenario.
You'll get the response code from headers inside getIn() method instead. By facing any issue (I mean, HTTP-call errors) other than the expected response, an exception will be thrown and set into the exchange properties (Exchange.EXCEPTION_CAUGHT).
Finally I got the answer
My processor was getting invoked, but encounters a NPE while excuting the processor body and that exception was internally consumed by camel
During an exception, all exception related information can be retrieved from exception object itself rather than In/Out
Below is my exception handler (processor) code,
HttpOperationFailedException cause = exchange.getProperty(Exchange.EXCEPTION_CAUGHT, HttpOperationFailedException.class);
LOG.error(cause.getMessage());
final String responseBody = cause.getResponseBody();
LOG.error(responseBody);
Related
I want to throw a SOAP exception when there are pending Entity Framework migrations and someone sends any SOAP request. If I throw a FaultException within my Global.asax, I get a html response from the IIS. This works but it is rather ugly. So I tried to throw it within the IServiceBehavior.Validate() method of my ServiceBehavior class.
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
var isDatabaseUpdateRequired = new MyDb().GetPendingMigrations().Any();
if (isDatabaseUpdateRequired) throw new FaultException("There are pending migrations.");
}
But I do not get any XML response with the error message on my SoapUI client. Where should I throw this exception?
You can throw this exception in a class that implements the interface IDispatchMessageInspector. Implement IDispatchMessageInspector to inspect or modify inbound or outbound application messages either prior to dispatching a request message to an operation or before returning a reply message to a caller.
When the server receives the client request, the DispatchMessageInspector intercepts all the client requests.
The picture above is the implementation of IDispatchMessageInspector, Throw an exception in the BeforeSendReply method.
The client sends a request to the server and gets an exception message.
Here is a link about the IDispatchMessageInspector interface.
When I call the actual SOAP service (using Postman and SoapUI) with an invalid parameter value, it causes a SOAP-Fault response, with HTTP 200 .
I copied the body of the response into a Wiremock response file, whose corresponding mapping file returns HTTP 200.
When I use Postman to invoke the SOAP service and the mocked one, the 'Body' of the responses are identical (apart from headers, as the mocked response doesn't explicitly set any).
When my API invokes the actual SOAP service, the SOAPError is caught, the processing stops and the API is processed as defined in the 'catch' section.
However, when the API invokes the mocked SOAP service, the SOAPError is not detected after 'invoke', processing continues and produces an incorrect response.
This suggests that there is something 'extra' returned in a fault from a real SOAP service, that APIC uses to detect a SOAPError. What is it?
I would add it to the mocked response, if only I knew what it should be.
BTW: The response headers are the same for both valid parameters and the SOAP Fault for an invalid one.
[edit]
Thanks #Jan Papenbrock. Adding "Content-Type = text/xml" sorted it out.
I don't know why I thought I was receiving the same headers from real and mocked responses - total rubbish!
John
[/edit]
Had the same error with WireMock and fixed it with the help of answers to this question. In my case, the Content-Type header was missing.
I suggest you try the following:
Send Content-Type: text/xml as response header (or try application/soap+xml)
Return HTTP status code 500 for the SOAP fault response, according to the specification (note: status 400 did not work for me).
My stub generation looks like this:
static ResponseDefinitionBuilder errorInvalidStopResponse() {
responseWithBodyFile('response-error-invalid-stop.xml')
.withStatus(500)
}
static ResponseDefinitionBuilder responseWithBodyFile(String responseBodyFileName) {
aResponse()
.withStatus(200)
.withHeader("Content-Type", "text/xml")
.withBodyFile(responseBodyFileName)
}
I am using xml based configuration - http outbound gateway to trii=gger a rest service, the response is ResponseEntity and I dont know that service details. The output I receive should be put in a JMS Queue.
How can I update the below to extract only the body of response entity and pass to output-channel? If there is a transformer, please give example. Is it possible using config?
<int:chain input-channel="gsInChannel" output-channel="dest-channel">
<int-http:outbound-gateway
url="https://ia-zatie.str13.tst.belst.nu/ia-zaatie/rest/signal/v2"
http-method="POST"
header-mapper="headerMapper"
request-factory="sslFactory"
>
</int-http:outbound-gateway>
</int:chain>
dest-channel is jms:outbound-channel-adapter
boot version 1.4.3 and integration version 4.3.6
Error: org.springframework.messaging.MessageHandlingException: error
occurred in message handler
[org.springframework.integration.jms.JmsSendingMessageHandler#0];
nested exception is
org.springframework.jms.support.converter.MessageConversionException:
Cannot convert object of type
[org.springframework.http.ResponseEntity] to JMS message. Supported
message payloads are: String, byte array, Map, Serializable
object.
I was using HTTP POST method and so not expecting, a response. SoO has not included expected-response-type, which returns the body
<int-http:outbound-gateway
url="https://ia-zatie.str13.tst.belst.nu/ia-zaatie/rest/signal/v2"
http-method="POST"
header-mapper="headerMapper"
request-factory="sslFactory"
expected-response-type="java.lang.String">
I am currently learning spring integration.I want to create a soap response from fault message.If any error is occurred spring gives response with fault in message body.I want to customize it.Instead of showing it i need to show a response object which contains pain response object.For eg:
if soap fault message is like this
<SOAP-ENV:Fault>
<faultcode xsi:type="xsd:string">SOAP-ENV:Client</faultcode>
<faultstring xsi:type="xsd:string">
Failed to locate method (ValidateCreditCard) in class (examplesCreditCard) at /usr/local/ActivePerl-5.6/lib/site_perl/5.6.0/SOAP/Lite.pm line 1555.
</faultstring>
</SOAP-ENV:Fault>
in its place i need to show its response as follows
<m:myResponse xmlns:m ="http://www.example.org/myschema">
<m:error> Failed to locate method (ValidateCreditCard) in class (examplesCreditCard) at /usr/local/ActivePerl-5.6/lib/site_perl/5.6.0/SOAP/Lite.pm line 1555</m:error>
</m:myResponse>
The <int-ws:inbound-gateway> has error-channel option to provide an ability to treat any downstream Exception with some error handling flow and return a desired result from there. That result is used as a SOAP response.
Hope I am clear.
I'm face with a situation where we cannot use schema to validate incoming request (basically schema is there but it accepts any String in request, wsdl designers have their own reasons to do that to accept request from different sources and flexibility). But when the request is received, I validate that the child element of request wrapper is what we expect (using XPath for that). Now if the child element is not what expected, I'd like to throw Soap Fault with Client code and may be include error message that schema validation failed, request doesn't contain valid element.
I'm using Mule 3.3 and doing my XPath validation in <choice> element and I want to throw exception in <otherwise> block.
Is there a way to throw Soap Fault manually in mule flow and
How to add custom fault string. I'm not sure if an outInterceptor will solve the purpose as I'm not using schemaValidation attribute of <cxf:proxyService>.
Here is part of my flow
<http:inbound-endpoint address="${service.address}" exchange-pattern="request-response">
<cxf:proxy-service wsdlLocation="classpath:service.wsdl" namespace="http://company.com/services/service" service="CompanyService" />
</http:inbound-endpoint>
<choice>
<when>.....</when>
<otherwise><!-- Here I want to throw Soap Fault ---></otherwise>
</choice>
<catch-exception-strategy>
<flow-ref name="generateErrorResponse" />
</catch-exception-strategy>
Since you are using a cxf:proxy-service you have complete control on the response. For example, if you add the following in your otherwise block, you'll be able to create whatever SOAP fault you want:
<expression-component><![CDATA[
message.payload = '<soap:Fault xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">'
+ '<faultcode>A code</faultcode><faultstring>A string</faultstring>'
+ '</soap:Fault>';
]]></expression-component>