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)
Related
I receive a Request from the Client which returns a SendRequest-Object that has a HttpMethod, a path and data to send.
Now I would like to send the Request depending on the object I get to the API.
After sending I will get a Response.
The problem now is how can I send the payload and receive the response.
#Bean
public IntegrationFlow httpPostSendRawData() {
return IntegrationFlows.from(
Http.inboundGateway("/api/data/send")
.requestMapping(r -> r.methods(HttpMethod.POST))
.statusCodeExpression(dataParser().parseExpression("T(org.springframework.http.HttpStatus).BAD_REQUEST"))
.requestPayloadType(ResolvableType.forClass(DataSend.class))
.crossOrigin(cors -> cors.origin("*"))
.headerMapper(dataHeaderMapper())
)
.channel("http.data.send.channel")
.handle("rawDataEndpoint", "send")
.transform(/* here i have some transformations*/)
.handle(Http.outboundGateway((Message<SendRequest> r)->r.getPayload().getPath())
.httpMethod(/* Here I would like to get the Method of SendRequest*/)
//add payload
.extractPayload(true))
.get();
It's not clear what is your SendRequest, but the idea for the method is exactly the same what you have done for the url:
.httpMethodFunction((Message<SendRequest> r)->r.getPayload().getMethod())
Although, since you want to have some extraction for the request body, you need to do that in advance in the transform() and move values for url and method to the headers.
There is just no any payload extraction in the Http.outboundGateway: it deals with the whole request payload as an entity for HTTP request body.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
HTTP GET with request body
I've read few discussions here which do not advocate sending content via HTTP GET. There are restrictions on the size of data that can be sent via clients (web browsers). And handling GET data also depends on servers. Please refer section Resources below.
However, I've been asked to test the possibility to send content via HTTP GET using RestTemplate. I refered few discussions on spring forum but they were not answered. (Please note sending data via http Post works fine). The discussion here suggests using POST instead.
dev env - JBoss AS 5.1, Spring 3.1.3
Client
#Test
public void testGetWithBody()
{
// acceptable media type
List<MediaType> acceptableMediaTypes = new ArrayList<MediaType>();
acceptableMediaTypes.add(MediaType.TEXT_PLAIN);
// header
HttpHeaders headers = new HttpHeaders();
headers.setAccept(acceptableMediaTypes);
// body
String body = "hello world";
HttpEntity<String> entity = new HttpEntity<String>(body, headers);
Map<String, Object> uriVariables = new HashMap<String, Object>();
uriVariables.put("id", "testFile");
// Send the request as GET
ResponseEntity<String> result = restTemplate.exchange(
"http://localhost:8080/WebApp/test/{id}/body",
HttpMethod.GET, entity, String.class, uriVariables);
Assert.assertNotNull(result.getBody());
}
Server #Controller
#RequestMapping(value = "/{id}/body", method = RequestMethod.GET)
public #ResponseBody
String testGetWithBody(#PathVariable String id,
#RequestBody String bodyContent)
{
return id + bodyContent;
}
The problem -
executing this test case returns 500 Internal Server Error. On debugging, I found that the controller is not hit.
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Resources - discussions on sending body via HTTP GET using RestTemplate at spring forum
http://forum.springsource.org/showthread.php?129510-Message-body-with-HTTP-GET&highlight=resttemplate+http+get
http://forum.springsource.org/showthread.php?94201-GET-method-on-RestTemplate-exchange-with-a-Body&highlight=resttemplate+http+get
Resources - General discussions on sending body via HTTP GET
get-with-request-body
is-this-statement-correct-http-get-method-always-has-no-message-body
get-or-post-when-reading-request-body
http-uri-get-limit
Is it correct to understand that the RestTemplate provides the way to send data as request body, but the error occurs because the server could not handle the request body ?
You can tell by looking at network traffic (does the request get sent with a request body and a GET method?) and at server logs (the 500 result you receive must have a server-side effect that gets logged, and if not, configure the server to do so).
If the request body sent via HTTP Get is not conventional why does RestTemplate provide the APIs to allow sending it ? Does this mean there are few servers capable of handling the Request body via GET ?
Because it is a generic class that also allows you to craft requests that can include a message body.
As stated in HTTP GET with request body:
In other words, any HTTP request message is allowed to contain a message body, and thus [a server] must parse messages with that in mind. Server semantics for GET, however, are restricted such that a body, if any, has no semantic meaning to the request. The requirements on parsing are separate from the requirements on method semantics.
A body on a GET cannot do anything semantically, because you are requesting a resource. It's like you tell the server: "Give me resource X, oh, and have some apples!". The server won't care about your apples and happily serve resource X - or throw an error because it doesn't like any offers in a request.
However, I've been asked to test the possibility to send content via HTTP GET
Please tell the one who requested this that this is a case that should not have to be tested, because no sensible implementation supports it.
I have two apps. First of them executes some business logics and than calls other app with POST or DELETE
from("direct:firstapp").routeId("rst_firstapp").streamCaching()
//data preparation was here
.setHeader(Exchange.CONTENT_TYPE, simple(MediaType.APPLICATION_JSON_VALUE))
.convertBodyTo(MyRequest.class)
.choice().id("rst_req_lockCardChoice")
.when().simple("${mycondition} == '1'")
.setHeader(Exchange.HTTP_METHOD, simple("POST"))
.log(LoggingLevel.INFO, "Call post")
.when().simple("${mycondition} == '0'")
.setHeader(Exchange.HTTP_METHOD, simple("DELETE"))
.log(LoggingLevel.INFO, "Call delete")
.end()
.marshal(new JsonDataFormat(JsonLibrary.Jackson))
.log(LoggingLevel.INFO, " Call to service ${body}")
.to('myadress/mypath').id("rt_call_service")
.log(LoggingLevel.INFO, " Response from service ${body}");
Logs for line: .log(LoggingLevel.INFO, " Call to service ${body}")
print that body exists in both cases.
The second app receives this requests and does some other business logics.
rest().post("/mypath")
.consumes(MediaType.APPLICATION_JSON_VALUE)
.produces(MediaType.APPLICATION_JSON_VALUE)
.type(MyRequest.class)
.responseMessage().code("200").message("Success").endResponseMessage()
.route().routeId("rst_postrecieve")
.log(LoggingLevel.INFO, "Recieved request ${body}")
.id("rst_rst_post_recieved")
.to("direct:drt_rst_postbranch")
.endRest();
rest().delete("/mypath")
.consumes(MediaType.APPLICATION_JSON_VALUE)
.produces(MediaType.APPLICATION_JSON_VALUE)
.type(MyRequest.class)
.responseMessage().code("200").message("Success").endResponseMessage()
.route().routeId("rst_deleterecive")
.log(LoggingLevel.INFO, "Received request ${body}")
.id("rst_rst_delete_recieved")
.to("direct:drt_rst_deletebrach")
.endRest();
POST request works fine.
First app sends body. Second recieves it.
DELETE doesn't.
First app cuts the body out. Line .log(LoggingLevel.INFO, " Call to service ${body}") prints the body. But the reciever gets a DELETE request with empty body. I have sniffed the Http-request with Wireshark: the body is empty.
However, I'm perfectly able to send a DELETE request with body using any other tool like Swagger-ui, Postman, Soap-UI etc. The second app will recieve body and proccess it correctly.
Why does Camel forbid to send a DELETE body, while it allows to recieve it? I expected the behaviour to be the same.
What is the workaround? I can't change request type, it's a customer requirement.
Camel version: 2.21.0.000033-fuse-000001-redhat-1
P.S. I know that Http standards state that no body is expected for DELETE, however all the tools & frameworks I faced allowed to send and receive it. Including Spring, for example.
Most probably Delete method will ignore body while processing. This is no problem with your code, it was because of HTTP implementation.
If a DELETE request includes an entity body, the body is ignored [...]
If you still need to send some data from one app to another to Delete method. I suggest you can try with path param. So than you can get as parameter in second app and do you process.
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.
Would you please advise how to configure RestAssured to wait until complete response data is returned.
I am trying to validate a data feed using http get as shown below.
given()
.relaxedHTTPSValidation()
.header("Content-Type", "application/json")
.when()
.get("/API/data/")
.then()
.statusCode(200)
.log().all();
In this context, Rest Assured logging only few lines of data, does not seem to wait until complete response data is returned .
This works ok when data response is small.
In this case, it seems to log only data that's available when http status code is returned.
Consequently I am seeing the following error message: Premature end of Content-Length delimited message body (expected: 1486; received: 1088)
Thx
If you want to check the status code you should use the expect().statusCode(x).
Anyway the tool waits until the whole response is returned from the server and only logs it out after that. So it shouldn't be a problem with big JSON/XML responses either.