Apache Camel is not capturing the SOAP service response - java

I'm using Apache Camel 2.19.2 DSL and trying to consume a soap service hosted in a different server. My camel code is -
SoapJaxbDataFormat soap = new SoapJaxbDataFormat("<Service Class Package Path>");
soap.setContextPath("Root element package path");
soap.setVersion("1.1");
from("direct:invokeSOAPService")
.process(new Processor1()) //Constructs the main message body that will be set as body of the soap-Envelope
.removeHeaders("*")
.setHeader(Exchange.SOAP_ACTION, simple("Soap Action of the service from ASDL"))
.setHeader(Exchange.HTTP_METHOD, simple("POST"))
.setHeader(Exchange.CONTENT_TYPE, constant("text/xml"))
.marshal(soap)
.log(LoggingLevel.DEBUG, LOG, "Request xml===========>${body}")
.log(LoggingLevel.DEBUG, LOG, "Posting request to server url")
.to("cxf://http://<ip>:<port>/<wsdl server location without ?wsdl>?serviceClass=<qualified service class name without .class extension>&dataFormat=MESSAGE&synchronous=true&continuationTimeout=100000&serviceName={<target-name-space-name>}<service-name>&endpointName={<target-name-space-name>}<service port name>")
.log(LoggingLevel.DEBUG, LOG, "Posted request successfully to server url")
.log(LoggingLevel.DEBUG, LOG, "Received response from server ==========>${body}")
.end();
Application is able to generate the soap-request and able to post the same to the server and server is sending back the soap response (as confirmed by the owner of the soap server) but I can't see the response at my application end.
it is printing the request xml using below log:
Request xml===========> <soap request xml>
Posting request to server url
**org.apache.camel.component.cxf.feature.AbstractDataFormatFeature.removeInterceptors><removing the interceptor org.apache.cxf.interceptor.ClientFaultConverter#58811c5b
org.apache.camel.component.cxf.feature.AbstractDataFormatFeature.removeInterceptors><removing the interceptor org.apache.cxf.jaxws.interceptors.WrapperClassInInterceptor#1d25437
org.apache.camel.component.cxf.feature.AbstractDataFormatFeature.removeInterceptors><removing the interceptor org.apache.cxf.jaxws.interceptors.HolderInInterceptor#4451805d
org.apache.camel.component.cxf.feature.AbstractDataFormatFeature.removeInterceptors><removing the interceptor org.apache.cxf.jaxws.interceptors.WrapperClassOutInterceptor#2514dd3d
org.apache.camel.component.cxf.feature.AbstractDataFormatFeature.removeInterceptors><removing the interceptor org.apache.cxf.jaxws.interceptors.HolderOutInterceptor#75a76e00**
Posted request successfully to server url
Received response from server ==========> **PRINTING THE REQUEST XML**
Could you please help me to understand the issue, why camel is not able to capture the response! It is because of those camel internal remove methods?
Could you please help me to capture the response.

Related

Dropwizard HttpClient Multipart http Request - Java

I am getting Multipart request from UI to upload csv file but call is going through one orchestrator service (dropwizard-version : 0.9.2) to target service (dropwizard-version : 1.2.2) for upload. While adding support for Multipart request in orchestrator service using MultipartRequestEntity, call is failing at target service with error -
[2022-03-08 16:23:44,474] io.dropwizard.jersey.errors.LoggingExceptionMapper: Error handling a request: 4c0693ee31713edf
! java.util.concurrent.TimeoutException: Idle timeout expired: 30005/30000 ms
! at org.eclipse.jetty.io.IdleTimeout.checkIdleTimeout(IdleTimeout.java:166)
! at org.eclipse.jetty.io.IdleTimeout$1.run(IdleTimeout.java:50)
Expected Request at Resource Layer for both services :
public void request(#FormDataParam("file") InputStream body,
#FormDataParam("file") FormDataContentDisposition fileDetails,
#FormDataParam("comment") String comment){}
Is there any solution for this?
In this case tried using JerseyClient instead of HTTP Client in orchestrator service for making call to target service, created temporary csv file in orchestrator service and sent updated Headers (Content-Type, Content-Encoding, Content-Length, Content-Language, Host) while making call to target service, which is working fine.

Unable to send `multipart/form-data` request with python requests module

I have Java spring server that requires the Content-Type of the requests being sent to the server to be multipart/form-data.
I can correctly send requests to the server with postman:
However, I got The current request is not a multipart request error when trying to send the request with requests module in python3.
My python code is:
import requests
headers = {
'Authorization': 'Bearer auth_token'
}
data = {
'myKey': 'myValue'
}
response = requests.post('http://127.0.0.1:8080/apiUrl', data=data, headers=headers)
print(response.text)
If I add 'Content-Type': 'multipart/form-data' to the header of the request, the error message then becomes Could not parse multipart servlet request; nested exception is org.apache.commons.fileupload.FileUploadException: the request was rejected because no multipart boundary was found.
How can I make the same request as postman sends with python?
requests's author thinks this situation is not pythonic, so requests doesn't support this usage natively.
You need to use requests_toolbelt which is an extension maintained by members of the requests core development team, doc, example:
import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder
m = MultipartEncoder(
fields={'field0': 'value', 'field1': 'value',
'field2': ('filename', open('file.py', 'rb'), 'text/plain')}
)
r = requests.post('http://httpbin.org/post', data=m,
headers={'Content-Type': m.content_type})

Making a POST request using Camel

I have a camel route configured for reading from a JMS queue and POST it to a service.
My route is :
from("jms:queue")
.marshal()
.json(JsonLibrary.GSON)
.setHeader(Exchange.CONTENT_TYPE,constant("application/json"))
.setHeader(Exchange.HTTP_METHOD, constant("POST"))
.process(new Processor1())
.to("https4:xxxxxx?throwExceptionOnFailure=false")
.process(new MyProcessor())
My Configuration :
HttpComponent httpc = getContext().getComponent("http4",HttpComponent.class);
httpc.setHttpConfiguaration(customHttpConfig())
and in customHttpConfig i set my auth details.
I am getting a 400 error from the server. But i am able to hit the server from Postman api and get successfull response.
In my Processor1 class ( before making the request), i am able to print the body of the message, which contains a json representation of my object.
But in the processor after the POST request, i am doing this and getting below responses:
Message in = exchange.getIn();
in.getBody(String.class); // print the error code 400
HttpServletRequest request = in.getBody(HttpServletRequest.class)// This is null.
Anything i am doing wrong? Do i need to set the message Content to the body of my Post Request?
It will not be String.class:
in.getBody(String.class);
First check the type of server response, then try to print or log exchange body.
It should be HttpServletResponse:
HttpServletRequest request = in.getBody(HttpServletRequest.class)

Ws-Addressing feature in Mule ESB

I'm building a middleware based on Mule ESB, implementing Asyncronous Web Services.
I have a client who sends Soap requests to my ESB endpoint implemented with CXF Jax-ws service with WS-Addressing feature enabled, via SoapUI. I send the response string "Hello" and start processing the input parameters to make the asyncronous reply to the client, who has a callBack web service endpoint.
The request has the correct Soap Header, with the tag ReplyTo, which has the address of the callBack endpoint in the client.
Here is my server jax-ws web service code:
#WebService(serviceName = "OrderReceive")
#Addressing
public class OrderReceive {
public String perform(String id, long creditCardNumber, List<Product> products) {
//Save values to process the async reply
setSessionVariable(id,creditCardNumber,products);
return "Hello, i will send the response soon";
}
}
The thing is my web service is autorespoding to the ReplyTo address and i don't have any control of the response.
Is it possible to intercept that response, and set the correct body of it?
Why is my web service autoresponding?
Regards
this is why I love stackoverflow. I have never heard about this!!!
Your "automatic response" can be caused by a behavior in mule:
If mule detects the reply_to property in the message , launches an automatic response to that endpoint. This is for request-reply funcionality in jms, but maybe is affecting the http connector.
Source of this :
Automatic response when sending message
-------------------*------------------------
After my researching I found that the proper behaviour of ws-addressing is:
client -- SOAP request ( on port A ) --> server
client <-- HTTP 202 ( "Hello, i will send the response soon" HTTP body ) --- server
client <-- SOAP response ("Response is ready!!" on port B ) --- server
Source :jax-ws 2.2.8 and ws-addressing
To make this possible , we need:
1.- Server Endpoint : mule/cxf
2.- Client of service : soapui
3.- Callback Endpoint : to recieve the async response (I think this is in mule)
Understood this, the offical documentation about it is sad :
MULE 3.7 Enabling WS-Addressing
I think you need the CallBack Enpoint to create and execute the async response. I have not found anything in mule :(.
Here some links of java implementation, no mule:
Asynchronous web services with WS-Addressing
Invoke a single port async service using JAX-WS and WS-Addressing
-------------------*------------------------
An alternative solution could be :
1.- Web Service in mule/cxf without addressing.
2.- Inside operation method :
public Response operation ( Request requestPayload ) {
MuleClient client = new MuleClient(muleContext);
client.dispatch("jms://my.queue", requestPayload , null);// this is async
return new Response("Hello, i will send the response soon.");
}
Reference : Using the Mule Client
3.- Create a jms inbound endpoint listen to : jms://my.queue
<flow>
<jms:inbound-endpoint queue="my.queue" >
<do something>
<launch a response to client>
</flow>
This could be :
a.- By email to client
b.- Consume a service published by client
c.- SMS notification
d.- Whatever
This approach can be more flexible and support future crazy requirements.
If you need some help with mule cxf service or jms, let me know to help you!!
http://jrichardsz.github.io/

One or more http request headers was not valid for the SOAP request

I'm trying to connect my Java application with the Channel Advisor API and I get this error:
<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/'>
<soap:Body>
<soap:Fault>
<faultcode>soap:Server</faultcode>
<faultstring>Server was unable to process request. One or more http request headers was not valid for the SOAP request. </faultstring>
<detail/>
</soap:Fault>
</soap:Body>
</soap:Envelope>
Here is my request:
String requestURL = "https://api.channeladvisor.com/ChannelAdvisorAPI/v7/InventoryService.asmx";
String request =
"<soapenv:Envelope xmlns:soapenv='http://schemas.xmlsoap.org/soap/envelope/' xmlns:web='http://api.channeladvisor.com/webservices/'>"+
"<soapenv:Header>"+
"<web:APICredentials>"+
"<!--Optional:-->"+
"<web:DeveloperKey>XXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXX</web:DeveloperKey>"+
"<!--Optional:-->"+
"<web:Password>XXXXXXXXXX</web:Password>"+
"</web:APICredentials>"+
"</soapenv:Header>"+
"<soapenv:Body>"+
"<web:GetInventoryQuantity>"+
"<web:accountID>XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXXX</web:accountID>"+
"<web:sku>XXXXXX-XX-XXX</web:sku>"+
"</web:GetInventoryQuantity>"+
"</soapenv:Body>"+
"</soapenv:Envelope>";
The strange thing is that if I try the same request with SoapUI I get back a successful response.
Any idea how to fix this?
Have you tried to address the actual message the web service is returning (emphasis mine)?
Server was unable to process request. One or more http request headers was not valid for the SOAP request
If it works from SoapUI then it means you are not sending a proper request from your Java application. SoapUI records some logs when it performs the request. You can look at he HTTP logs and see what headers it sends.
My guess is you are either missing the SOAPAction or the Content-Type. Start adding the headers one by one and see when the web service stops complaining.

Categories