Ignore response from Mule HTTP outbound endpoint and continue processing - http

I have a simple Mule flow where I receive an XML message via an HTTP endpoint and then do some processing on it. One of the first steps is to send the message via another outbound HTTP endpoint to a web service. The service just saves the message and does no processing on it. Therefore I effectively want to ignore the return value of the outbound endpoint and continue processing the message that was originally received. I tried making the endpoint on-way, but then my current Mule message becomes empty.
How do I call a endpoint, but ignore any return and continue processing with my original message?

You could use a <wiretap>: http://www.mulesoft.org/documentation/display/current/Routing+Message+Processors#RoutingMessageProcessors-WireTap
Or use <async> scope: http://www.mulesoft.org/documentation/display/current/Async+Scope+Reference
Or use an <enricher> if you want store the response in a variable but leave the current payload alone: http://www.mulesoft.org/documentation/display/current/Message+Enricher
Note that wiretap and enricher are synchronous and will block further processing where async won't.

In this case Async should be a better option.
Async in Mule helps to continue with the processing ignoring the results of the message processors called inside the async.
ex:
<flow name="sample" >
<http:inbound-endpoint ...... />
.... Some processing.....
<async>
<http:outbound-endpoint ....... />
</async>
...... Continue with the processing with the original message....
</flow>
Hope this helps.

Related

AsyncHandlerInterceptor - ASYNC dispatcher request not called while client closes

Well, this is an exceptional behavior, one needed for our use-case.
We are using handler interceptor to "increment active request count" at "preHandle" method. On "afterCompletion" method we decrement the active request counter. So far so good.
Sync calls are straight forward. But in case of async there is a 2nd request (DispatcherType: ASYNC) which is being used to decrement the counter while the main request (DispatcherType: REQUEST) is used to increment the counter. We check the dispatcher type to avoid double increment.So far so good.
The problem happening in case of some problematic clients, which disconnects after firing the request. In such a case while the main request enters the server but before the async thread starts the client disconnect itself (like close the browser).In this case the 2nd request (DispatcherType: ASYNC) not getting created at all.
This situation leaving the counter increased (by the main request).
For our use-case, we have to decrement the counter no matter what if it is incremented for a request.
Looking forward to your help/suggestion here. Thanks in advance.
Other details:
Spring Boot application
Spring framework: 4.3.4.RELEASE
Tomcat : 7
Using RestController
Handler Interceptor: AsyncHandlerInterceptor
In the asynchronous mode we use ResponseBodyEmitter to send data to client
Log in server:
Exception in thread "pool-87-thread-1" java.lang.IllegalStateException: The request associated with the **AsyncContext has already completed processing**.
at org.apache.catalina.core.AsyncContextImpl.check(AsyncContextImpl.java:497)
at org.apache.catalina.core.AsyncContextImpl.getRequest(AsyncContextImpl.java:209)
at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:198)
at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:170)
at org.apache.catalina.core.AsyncContextImpl.dispatch(AsyncContextImpl.java:164)
at org.springframework.web.context.request.async.StandardServletAsyncWebRequest.dispatch(StandardServletAsyncWebRequest.java:123)
at org.springframework.web.context.request.async.WebAsyncManager.setConcurrentResultAndDispatch(WebAsyncManager.java:353)
at org.springframework.web.context.request.async.WebAsyncManager.access$200(WebAsyncManager.java:58)
at org.springframework.web.context.request.async.WebAsyncManager$7.handleResult(WebAsyncManager.java:416)
at org.springframework.web.context.request.async.DeferredResult.setResultInternal(DeferredResult.java:199)
at org.springframework.web.context.request.async.DeferredResult.setErrorResult(DeferredResult.java:214)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitterReturnValueHandler$HttpMessageConvertingHandler.completeWithError(ResponseBodyEmitterReturnValueHandler.java:219)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.completeWithError(ResponseBodyEmitter.java:204)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.sendInternal(ResponseBodyEmitter.java:169)
at org.springframework.web.servlet.mvc.method.annotation.ResponseBodyEmitter.send(ResponseBodyEmitter.java:159)
at net.atpco.pipeline.common.post.KryoResponseEmitterPostBox.send(KryoResponseEmitterPostBox.java:48)
at net.atpco.pipeline.common.post.KryoResponseEmitterPostBox.lambda$0(KryoResponseEmitterPostBox.java:37)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745)
Updates:
On further research I found this in spring documentation... "Note that HandlerInterceptor implementations may need to do work when an async request times out or completes with a network error. For such cases the Servlet container does not dispatch and therefore the postHandle and afterCompletion methods will not be invoked. Instead, interceptors can register to track an asynchronous request through the registerCallbackInterceptor and registerDeferredResultInterceptor methods on WebAsyncManager. This can be done proactively on every request from preHandle regardless of whether async request processing will start." This deferredResultInterceptor seems like solving the issue.

Unable to process a synchronous event asynchronously error in http

I have following flows in my mule config .
<flow name="SimpleTest" processingStrategy="asynchronous">
<http:listener path="/orders/{id}" config-ref="myRequestConfig"
allowedMethods="GET" />
<set-payload value="SUCCESS" />
<flow-ref name="subFlowTest" />
<logger level="ERROR" message="value is : after subflow" />
</flow>
<sub-flow name="subFlowTest">
<scripting:component doc:name="sleep">
<scripting:script engine="groovy">
<scripting:text>
java.lang.Thread.sleep(5000);
</scripting:text>
</scripting:script>
</scripting:component>
</sub-flow>
It gives Unable to process a synchronous event asynchronously error . i want to call the subflow asynchronously , so if my parent flow is asyncronous , the subflow will automatically becomes asyncronous , correct ? so why am i getting this error ?
You can call your subflow asynchronously by using async message processor.
<async doc:name="Async">
<flow-ref name="subFlowTest" doc:name="Call Sub Flow"/>
</async>
HTTP endpoint makes a call to this flow through it automatically synchronous, so you have a conflict between your flow's strategy and its inbound endpoint. By definition, HTTP is synchronous.
Your problem lies on your understanding of HTTP.
Hope it helps.
/T
subflow semantic is more like a macro expansion than a function call. You don't call a subflow, but use a subflow to extract message processors into a different xml structure for readability. In runtime it is the same than if you copy all the message processors of the subflow and put them inside the flow.
Why would you execute your script component asynchronously?

Mule: Migrating to the New HTTP Connector

I've upgraded from Mule 3.5.x to 3.6.x and since the old http transport is deprecated in 3.6.x I wanted to migrate to the new HTTP connector.
Here is the original code for calling my webservice:
<http:outbound-endpoint ref="OrderEndpoint" doc:name="GetApprovedOrder">
<cxf:jaxws-client serviceClass="com.acme.orders.IOrderServiceBean"
port="OrderServiceBean_v2_0Port"
operation="getApprovedOrderOp" />
</http:outbound-endpoint>
The point I have got to with the new connector is as follows:
<cxf:jaxws-client serviceClass="com.acme.orders.v2_0.IOrderServiceBean" port="OrderServiceBean_v2_0Port" operation="getApprovedOrderOp" />
<http:request config-ref="http.request.config" path="acme-services/OrderServiceBean_v2_0" method="POST" />
The issue that I have is that with the old version of the code, after calling the web service, the payload would be the response [java] object. With the new version of the code the payload is a org.glassfish.grizzly.utils.BufferInputStream containing the soap xml.
I could use a combination of xpath and a jaxb-xml-object-transformer to convert the contents of the stream to the response object, this just seems like a backwards step though.
I have looked into using the jaxws-client without the request and also at the ws-consumer, but my following requirements seems to rule these options out (unless I'm just misunderstanding how to use them).
I need to use the contract first method for calling the web services, see above where I have specified serviceClass rather than wsdl.
The web services use basic auth, therefore I need to specify a username and password.
I need to be able to specify the host and port (or at least the address) of the web service.
The solution is: wrap your element into a processor-chain
As follows:
<processor-chain>
<cxf:jaxws-client serviceClass="com.acme.orders.v2_0.IOrderServiceBean" port="OrderServiceBean_v2_0Port" operation="getApprovedOrderOp" />
<http:request config-ref="http.request.config" path="acme-services/OrderServiceBean_v2_0" method="POST" />
</processor-chain>
This is because cxf is intercepting, so after the processor chain you would have the same object as you had in your previous solution.

Spring Integration jms aysnchronous request/reply

We have a requirement to service the GUI with a SI service. The GUI communicates with the backend over JMS queues, and will wait for a response on a tmp queue that is specified in the jms replyTo header property.
So there can be 10 gui's making queries to the backend, and receiving messages on their individual tmp queues.
So I wrote a SI service using inbound gateway that looks like this
<int:channel id="inChannel" />
<int:channel id="outChannel" />
<int-jms:inbound-gateway id="jmsSampleService" request-destination-name="TEST_QUEUE_2" request-channel="inChannel"
connection-factory="qpidJmsConnectionFactory" extract-request-payload="true" error-channel="errorChannel" />
<int:service-activator input-channel="inChannel" ref="sampleService2" method="processMessage" />
public class SampleService2 {
public Response processMessage(Object obj) throws Exception {
LOG.info("Message received on sample service. ");
Thread.sleep(5000);
Response response = new ResponseImpl();
response.setPayload("Test response");
return response;
}
This works fine, i can see the service return a message back on the jmsReplyTo queue. However, this is a single threaded synchronous operation which means unless GUI1 was serviced, GUI2 's call will be blocked. I want to do this asynchronously since this is simply a method call on a class.
We were doing something similar in mule
<flow name="sampleServiceFlow">
<jms:inbound-endpoint queue="TEST_QUEUE" connector-ref="queryQpidConnector" />
<byte-array-to-object-transformer />
<component>
<spring-object bean="sampleService" />
</component>
<object-to-byte-array-transformer />
<expression-filter evaluator="groovy"
expression="message.getOutboundProperty('replyToQueueName') != null" />
<jms:outbound-endpoint queue="#[header:OUTBOUND:replyToQueueName]" connector-ref="queryQpidConnector" />
</flow>
Since the mule service does not have any txns, it is able to simply consume a message in auto-ack, and have the SampleService's method call service the call.
Is there a way of implementing something like this in SI? perhaps by using the message-driven-channel-adapter? Is there a way to propagate jms header properties between channels?
Simply use concurrency on the inbound gateway. concurrent-consumers is the min max-concurrent-consumers (if specified) is the max; the adapter's container with adjust the concurrency depending on demand.
I am not sure what you mean by
Is there a way to propagate jms header properties between channels?
The jms headers are mapped to integration headers and vice-versa.

Muel-esb: Testing Choice Router

Is there a way to test a choice router for the following scenario which is based on the http.status? I am seeking a way to test the first condition of the router
<flow>
<choice>
<when expression="#[message.inboundProperties['http.status'] !=201">
......
<otherwise>
.....
</otherwise>
</choice>
</flow>
I want to verify that a javax.ws.rs.core.Response with can be correctly handled by the HTTP endpoint.
The flow doesn't have an inbound endpoint (thus it's a private flow) so to test it
create a test flow in a test XML config file that you will load side by side with your other Mule configuration XML files,
add an inbound VM endpoint to this test flow and make it call the private flow you want to test,
in your functional test case, use the Mule Client to dispatch a test message over the VM endpoint, setting properties on this test message that will end-up as inbound properties in the private flow.

Resources