Http Inbound Gateway takes 2x timeout to send timeout response to client - spring-integration

We're using an http inbound gateway to process http requests. Lately , we wanted to set specific http response code that will be sent to user after a timeout.
We upgraded to spring 4.2.1 and set
the reply-timeout-status-code-expression attribute
and it's working now.
But there is a problem : if we set the timeout to 10 seconds , a ReplyTimeoutException is raised in the web application after exactly 10 seconds but the response arrives to the client after 20 seconds ( exactly the double ).
We changed the timeout several times but it always take 2x timeout for the response to be received by client.
This is the xml config for the http inbound gateway :
<int-http:inbound-gateway id="inboundRequest" request-channel="inbound-channel"
supported-methods="POST" path="/Request" error-channel="errorChannel" reply-channel="gateway_response"
reply-timeout="5000" request-payload-type="java.lang.String" reply-timeout-status-code-expression="'504'" >
A Help would be really appreciated

I see you have an error-channel - if the error flow returns no response, the reply timer starts again when the error flow ends (we're waiting for a reply from the error flow).
Instead of returning nothing from the error flow, you need to throw a MessageTimeoutException.
Turning on DEBUG logging and following the message flow is the best way to diagnose issues like this.
If that's not the problem, you need to show the rest of your configuration (edit the question, don't try to post it in a comment).

Related

exception scenario handling for input http headers in a REST api using spring integration

I need to do some validations on the input http headers, trying to write GET http rest api with some http headers, need to validate if one of the headers has specific value, if not throw an exception. I have used http inbound gateway, created error-channel and using service activator to notify error handler, I am getting below error,
No reply received from error channel within timeout
My code looks like,
<int-http:inbound-gateway
request-channel="sampleRequestChannel"
reply-channel="sampleResponseChannel"
error-channel="apiErrorChannel"
reply-timeout="15000"
supported-methods="GET"
path="/test/{testId}"
mapped-request-headers="*"
payload-expression="#pathVariables.testId">
<int-http:header name="source" expression="#requestParams[source]"/>
</int-http:inbound-gateway>
<int:service-activator input-channel="sampleRequestChannel" ref="testAdapterController" method="getDetails" output-channel="testSourceRouter"/>
<int:service-activator input-channel="apiErrorChannel" ref="testErrorHandler" method="handleFailedRequest" output-channel="sampleResponseChannel"/>
<bean id="loadErrorHandler" class="com.test.adapter.controller.TestErrorHandler"/>
<int:router input-channel="testSourceRouter" expression="headers.source">
<int:mapping value="ABCD" channel="callABCDChannel"/>
<!--<int:mapping value="std" channel="intermediateStdChannel"/>-->
</int:router>
I am throwing exception in the code but its not reaching to the output channel even though I tried using output channel as reply channel.
I can see exception being thrown in my console logs but api doesn't throw it as a part of api response. I am pretty sure my understanding of working with spring integration is very limited, just started to work with it.
could someone please help?
To re-throw an exception to MVC there is just enough to not have that error-channel="apiErrorChannel" configured.
If you'd like to swallow it and return something else, then your testErrorHandler must return that object.
This is going to work as is if all your channels in the flow are DirectChannel which is a default type. If it is not, then you must look into this section of the doc and ensure an errorChannel downstream as a header: https://docs.spring.io/spring-integration/docs/current/reference/html/error-handling.html#error-handling

Azure app service some requests returns 400 Bad Request. The request could not be understood by the server due to malformed syntax

So we have a simple .net core 5.0 service that only serves some simple pages with mvc. We are starting to get 400 Errors (details below) on some of the requests. Our frontend is embedded in an iframe which forces us to use our own domain for our api-calls. The 400 errors disappears when we use the azure internal-urls. (*.azurewebsites.net instead of *.ourdomain.net). When I get to the "diagnose and solve problems" -> "availability and performance" -> HTTP 4XX ERRORS i can se below errors. Any ideas on what can cause this error?
Bad Request. The request could not be understood by the server due to malformed syntax. The client should not repeat the request without modifications.
So, the biggest problem above is that we do not get the correct errormessage. After a lot of experimentation we activated the ConnectionLogging for Kestrel.
WebHost.CreateDefaultBuilder(args)
.UseKestrel(options =>
{
options.ConfigureEndpointDefaults(listenOptions =>
{
listenOptions.UseConnectionLogging();
});
})
And after that we found some more intressting logs. One that said:
Connection id "0HMFSA73IA4LS" bad request data: "Malformed request: invalid headers."
Microsoft.AspNetCore.Server.Kestrel.Core.BadHttpRequestException: Malformed request: invalid headers.
After some more investigation we could diff a succesful request from a failing request. And the problem was related to the certificate of *.ourdomain.se. In a part of the certificate we hade a string thats named "Stockholms län" in the cases where it failed the string decoded to l�n and when it succeeded the string decoded to l%C3%A4n. We are now investigating if this is a load balancer problem. But this app is running hostingmodel outofprocess. By changing this to inprocess and wrap our Kestrel in IIS the errors disapears.

Force client to wait for response from azure function

I wrote an azure function with python that do some data processing, when I test on large dataset (150 lines), chrome raise a 502 http error : (tested the azure function on 10 lines and everything was ok)
I think the problem is that chrome browser wait for so long and when no response coming from azure function it automatically raises 502 error. I checked that the logic function is executed till the end but I don't get my json response when code is completed. Here is my http response I should get
return func.HttpResponse(json.dumps({"file" : file.name.split('/')[2]}),
mimetype="application/json",)
expected output :
{"file": "filename.json"}
In production I have to process more then 1500 lines, and within 150 lines the azure function take about 2 minutes to complete.
How to force chrome client or any client who hit the url of my azure function to wait to complete? is there any workaround pls?
For this problem, we are not client so we can't determine timeout value of client.
For your problem of force chrome client to wait the function complete, I'm afraid we can't do this setting. You can refer to this post (also shown as below screenshot).
According to the screenshot above, we can see chrome can't change the timeout setting and we can change it in other browsers.
If the client do not use browser but use code(such as .net) to request the function, the code should be like:
HttpClient httpClient = new HttpClient();
httpClient.Timeout = TimeSpan.FromMinutes(10);

Spring JMS Outbound Gateway receive timeout being ignored

I have a Spring Integration flow which sends a message out via a JMS Outbound Gateway which is configured to have a receive timeout of 45 seconds. I am trying to test the receive timeout period by sending a message out in a setup where the message is never consumed on the other side (therefore a response doesn't come back). However, when I run the test, the message is placed in the outbound queue but, the Outbound Gateway's receive timeout never occurs (after 45 seconds). Any ideas what reasons there could be for this happening (not happening)?
My stack is:
o.s.i:spring-integration-java-dsl:1.0.0.M3
o.s.i:spring-integration-jms:4.0.4.RELEASE
My IntegrationgConfig.class:
#Configuration
#EnableIntegration
public class IntegrationConfig {
...
#Bean
public IntegrationFlow testFlow() {
return IntegrationFlows
.from("test.request.ch")
.handle(Jms.outboundGateway(connectionFactory)
.receiveTimeout(45000)
.requestDestination("REQUEST_QUEUE")
.replyDestination("RESPONSE_QUEUE")
.correlationKey("JMSCorrelationID"))
.handle("testService",
"testMethod")
.channel("test.response.ch").get();
}
...
}
In terms of JMS configuration, the connection factory used is a standard CachingConnectionFactory which targets an MQConnectionFactory.
Thanks in advance for any help on this.
PM
--- UPDATE ---
I have turned on debugging and I can see that when the timeout occurs the following message is logged:
AbstractReplyProducingMessageHandler - handler 'org.springframework.integration.jms.JmsOutboundGateway#0' produced no reply for request Message: [Payload byte[835]][...]
Just need to find out how to capture this event in the flow?
--- UPDATE 2 ---
The message being sent out has an ERROR_CHANNEL header set on it to which I would expect the timeout exception to be routed to - but this routing does not happen?
Is it possible that the CachingConnectionFactory is handling the exception and not passing it back to the flow?
To make it working you need to add the second Lambda to the .handle() with Jms:
.handle(Jms.outboundGateway(connectionFactory)
.receiveTimeout(45000)
.requestDestination("REQUEST_QUEUE")
.replyDestination("RESPONSE_QUEUE")
.correlationKey("JMSCorrelationID"),
e -> e.requiresReply(true))
By default AbstractReplyProducingMessageHandler doesn't require reply even if receiveTimeout is exhausted, and we see that by logs shown by you.
However, I see that we should revise all MessageHandlerSpecs, because XML support changes the requires-reply for some components to true by default.
Feel free to raise a JIRA issue on the matter and we'll address it soon, because the GA release for Java DSL is planned over a week or two: https://spring.io/blog/2014/10/31/spring-integration-java-dsl-1-0-rc1-released
Thank you for the attention to this stuff!

Intermittent BridgeHandler & PublishSubscribeChannel call when gateways' reply channel is pub/sub

I'm seeing weird behaviour when sending data through my channels. I'm using SI gateway when sending a message to be processed. The gateway is setup as below
<integration:gateway id="rptPubGateway"
default-request-channel="rptPubInChannel"
default-reply-channel="rptOutputAvailableChannel"
default-reply-timeout="60000"
service-interface="xxxx.RptPubGateway" />
The reply channel is being set up as a publish/subscribe channel
<integration:publish-subscribe-channel id="rptOutputAvailableChannel" />
The last service that processes the message is being declared as below
<integration:service-activator input-channel="rptOutputAvailableChannel" ref="requestMessageHandler" method="rptIsDone" output-channel="nullChannel"/>
Now, the issue that i have is that while the code works fine most of the time, it fails sometimes. When everything works fine the last component processing my message is PublishSubsChannel
PublishSubscribeChannel - preSend on channel 'rptOutputAvailableChannel'
but when it fails the last component becomes BridgerHandler
BridgeHandler#e851a798' sending reply Message:
I should mention that there are no exceptions being thrown while processing my message. (after the failure I can always resend the same message and everything will work OK)
I'm not sure how that BridgerHandler gets created. From what I know this bridge gets created for pub/subs channels but then why I don't see it in the log when everything works fine ?
I'd appreciate any help
When you say "fails" what do you mean?
What are the other consumers on rptOutputAvailableChannel?
The BridgeHandler you see is an internal bridge to the message's replyChannel header, which is where the reply ultimately must go. When explicitly sending to rptOutputAvailableChannel, the bridge handler is always invoked to get the reply to the message's temporary reply channel.

Resources