Announcement Announcement Module
No announcement yet.
Message Gateway Timeouts Page Title Module
Move Remove Collapse
Conversation Detail Module
  • Filter
  • Time
  • Show
Clear All
new posts

  • Message Gateway Timeouts

    Hi, I'm looking to handle gateway timeouts resulting from null payloads downstream. However, I'm finding that no errors occur until my test is completed, at which point a NPE is thrown.

    Here are the core components of my service. The gateway takes in an array of Documents and returns a list of boolean representing the results. The channels I route to aren't important here. Just know that they send their resulting messages to 'eventRouteChainChannel' and 'eventRouteAggregatorChannel' respectively, and that the former context includes a service activator with an expression of 'null' for this particular test case.

    <!-- The main gateway for the Event Router. -->
    <int:gateway service-interface="com.c.c.event.gateway.EventGateway"
    	id="eventGateway" default-request-channel="eventGatewayInputChannel"
    	default-reply-channel="eventGatewayOutputChannel" error-channel="eventErrorChannel"
    	default-reply-timeout="10000" />
    <!-- A chain to encapsulate the event router. An event array is split and 
    	each event passes through the singular event gateway. After single events 
    	have been routed, their results are aggregated into a final list of booleans. -->
    <int:chain input-channel="eventGatewayInputChannel"
    	<int:splitter />
    	<int:service-activator expression="@routeGateway.receiveEvent(payload)" />
    	<int:aggregator expression="#this.![payload]" />
    <!-- The main gateway for the Event Router used for singular events. -->
    <int:gateway service-interface="com.c.c.event.gateway.EventGateway"
    	id="routeGateway" default-request-channel="eventRouteAccessChainChannel"
    	default-reply-channel="eventRouteOutputChannel" error-channel="eventErrorChannel"
    	default-reply-timeout="5000" />
    <!-- The route access chain will validate the emitter event schema, create 
    	headers based on its data, and route it to the appropriate route retrieval 
    	channel. -->
    <int:chain input-channel="eventRouteAccessChainChannel">
    	<int-xml:validating-filter schema-location="classpath:schemas/emitterEvent.xsd"
    		discard-channel="eventDiscardChannel" />
    		<int-xml:header name="eventType" xpath-expression-ref="eventTypeExp" />
    		<int-xml:header name="eventAll" xpath-expression="/"
    			evaluation-type="NODE_RESULT" />
    		<int-xml:header name="eventEid" xpath-expression-ref="eventEidExp" />
    		<int-xml:header name="eventEntityId"
    			xpath-expression-ref="eventEntityIdExp" />
    	<int:router default-output-channel="eventErrorChannel"
    		expression="headers.eventType + 'RoutesChannel'" />
    <!-- The route chain channel will split an event by its routes, place the 
    	route in a header and the event in the payload, transform the event into 
    	a 'token event', and route the event to the appropriate 
    	queue channel. -->
    <int:chain input-channel="eventRouteChainChannel">
    		<int:header name="errorChannel" value="routeErrorChannel" />
    		<int-groovy:script location="groovy/RouteValidator.groovy" />
    	<int:splitter />
    		<int:header name="eventRoute" expression="payload" />
    		<int:header name="errorChannel" value="eventErrorChannel" />
    	<int:service-activator expression="headers.eventAll" />
    	<int-xml:xslt-transformer xsl-resource="xsl/emitterEvent-to-event-transformer.xsl"
    		source-factory="domSourceFactory" result-factory="domResultFactory"
    		<int-xml:xslt-param name="processor"
    			expression="headers.eventRoute.processor" />
    	<int:router default-output-channel="eventErrorChannel"
    		expression="'queue' + headers.eventRoute.queue + 'Channel'" />
    <!-- An aggregator to return true only if all routes for an event have succeeded. -->
    <int:aggregator input-channel="eventRouteAggregatorChannel"
    	output-channel="eventRouteOutputChannel" expression="not #this.![payload].contains(false)" />
    As you can see, I have two gateways: one to split and aggregate arrays of events, and an inner one (called via service activator) to split and aggregate event route configurations and their results. I had to put timeouts on both to get any sort of collective functionality out of them, but even with only one I get the same error.

    Here's my wiretap log. As you can see, the message passes through my channels up until the 'test4RoutesChannel', where it hits the service activator and the payload is nullified.

    2013-03-13 14:53:36,112 DEBUG | main | com.c.c.event.router                       | [Payload=[Lorg.w3c.dom.Document;@17050f5][Headers={timestamp=1363200816108, id=8225838c-3f48-42d9-a340-74c714f17a87, history=eventGateway,eventGatewayInputChannel,eventLoggerChannel,eventLoggerChannel.adapter, errorChannel=org.springfra[email protected]d337d3, replyChannel=org.springfra[email protected]d337d3}] 
    2013-03-13 14:53:36,124 DEBUG | main | com.c.c.event.router                       | [Payload=[#document: null]][Headers={timestamp=1363200816124, id=00755c1b-e00b-46a3-bb52-fc3291d212bf, history=routeGateway,eventRouteAccessChainChannel,eventLoggerChannel,eventLoggerChannel.adapter, errorChannel=org.springfra[email protected]1de8aa8, replyChannel=org.springfra[email protected]1de8aa8}]  
    2013-03-13 14:53:36,143 DEBUG | main | com.c.c.event.router                       | [Payload=[#document: null]][Headers={timestamp=1363200816143, id=7c6beb99-8c70-466d-8b91-cb17aed20f1e, errorChannel=org.springfra[email protected]1de8aa8, history=routeGateway,eventRouteAccessChainChannel,test4RoutesChannel,eventLoggerChannel,eventLoggerChannel.adapter, eventEid=eid4, eventAll=[#document: null], replyChannel=org.springfra[email protected]1de8aa8, eventType=test4, eventEntityId=entityId4}] 
    FAILED: eventGatewayDeadRoutesTest
    	at com.c.c.event.test.EventRouterTests.eventGatewayDeadRoutesTest(
    I've tried walking through the service in debug. The message seems to unwrap itself backwards through the chains once it hits the 'null' service activator. It then waits for the timeout at each gateway, but doesn't do anything special when it expires.

    I read that I should be getting a MessageTimeoutException instead, but honestly, I don't care either way as long as I can at least handle the error somehow.

    Any ideas? Thanks.

  • #2
    Where did you read that you should get a MessageTimeoutException ?

    The gateway returns null when the gateway times out.


    • #3
      Hi Gary. I read it in a pretty old thread here. I think I may have been confused by the outcome of its related JIRA story, but perhaps that decision was discarded.

      That said, is there any way to invoke some sort of error handling when a null payload is returned to the gateway? I have an error channel set, but it isn't invoked.


      • #4
        No; you just have to test for a null reply.

        However, you CAN set 'requires-reply' on your service activator - then you'll immediately get a 'ReplyRequiredException' rather than having to wait for the timeout.


        • #5
          All right. I was aware of the "requires-reply" property, and it works fine, but as the implementation of these dynamically-routed contexts will largely be out of my hands I wanted to fool-proof them as much as possible. I'll just need to specify that the downstream endpoint should have that property set.



          • #6
            You could open a 'New Feature' issue, requesting a 'requires-reply' attribute on the <gateway/>, in which case we could throw a MessageTimeoutException.

            Even better - send a pull request -