Announcement Announcement Module
Collapse
No announcement yet.
si-http:outbound/inbound-gateway and MessageHeaders Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • si-http:outbound/inbound-gateway and MessageHeaders

    i am working with a si-http:outbound-gateway and si-http:inbound-gateway pair, and i am trying to pass primitives in

    MessageHeaders across that boundary.

    basically, i was looking for the default behavior exhibited when using the si-jms analogy outbound/inbound gateways.

    my test client looks like:

    Code:
        Message<?> message = MessageBuilder.withPayload(m_request).setHeader(KEY_1, VAL_1).build();
        message = new MessagingTemplate(m_channel).sendAndReceive(message);
    my inbound definition looks like:

    Code:
     <http:inbound-gateway id="inboundGateway" request-channel="request.input" convert-exceptions="true"
        request-payload-type="java.lang.String" />
    
      <si:service-activator input-channel="request.input">
        <bean class="com.aetna.framework.integration.test.RequestProcessor" p:name="processor-1" />
      </si:service-activator>
    the method signature of the RequestProcessor referred to in the service-activator above looks like:

    Code:
      public Message<?> invoke(Message<?> message) {...}
    when my outbound definition looks like (extract-request-payload="true"):

    Code:
      <http:outbound-gateway id="http" request-channel="http.output" url="${url}"
        extract-request-payload="true" charset="UTF-8" request-timeout="1000" expected-response-type="java.lang.String" />
    the Message received on the inbound side looks like (KEY_1 header not present):

    Code:
    [Payload=<request/>][Headers={timestamp=1290868776859, id=146c3e71-f6aa-4f6a-84ad-062dc917d722, errorChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChannel@148e798, http_requestMethod=POST, replyChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChannel@148e798, http_requestUrl=http://localhost:8080/aefw-inbound-gateway-webapp/si}]
    when my outbound definition looks like (extract-request-payload="false"):

    Code:
      <http:outbound-gateway id="http" request-channel="http.output" url="${url}"
        extract-request-payload="false" charset="UTF-8" request-timeout="1000" expected-response-type="java.lang.String" />
    the Message received on the inbound side looks like (KEY_1 header present, but...):

    Code:
    [Payload=[Payload=<request/>][Headers={id=4b2cf18c-a487-4f6f-ae0e-262934d4ae96, timestamp=1290867389625, key-1=val-1}]][Headers={timestamp=1290867389765, id=20afa961-1934-46c1-813e-3cdac762269d, errorChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChannel@1b5c22f, http_requestMethod=POST, replyChannel=org.springframework.integration.core.MessagingTemplate$TemporaryReplyChannel@1b5c22f, http_requestUrl=http://localhost:8080/aefw-inbound-gateway-webapp/si}]
    the Message received contains a *nested* Message as the payload with KEY_1 present (?!).

    i could probably work with this, but over on the outbound side i see the following INFO messages:

    Code:
    [inbound-gateway-test] 2010-11-27 10:24:52,984 INFO [org.springframework.integration.MessageHeaders] - removing non-serializable header: errorChannel
    [inbound-gateway-test] 2010-11-27 10:24:52,984 INFO [org.springframework.integration.MessageHeaders] - removing non-serializable header: replyChannel
    and then the following exception:

    Code:
    org.springframework.integration.support.channel.ChannelResolutionException: no output-channel or replyChannel header available
    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.sendReplyMessage(AbstractReplyProducingMessageHandler.java:166)
    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.produceReply(AbstractReplyProducingMessageHandler.java:125)
    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleResult(AbstractReplyProducingMessageHandler.java:119)
    	at org.springframework.integration.handler.AbstractReplyProducingMessageHandler.handleMessageInternal(AbstractReplyProducingMessageHandler.java:101)
    	at org.springframework.integration.handler.AbstractMessageHandler.handleMessage(AbstractMessageHandler.java:78)
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.doDispatch(UnicastingDispatcher.java:110)
    	at org.springframework.integration.dispatcher.UnicastingDispatcher.dispatch(UnicastingDispatcher.java:97)
    	at org.springframework.integration.channel.AbstractSubscribableChannel.doSend(AbstractSubscribableChannel.java:44)
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:157)
    	at org.springframework.integration.channel.AbstractMessageChannel.send(AbstractMessageChannel.java:128)
    	at org.springframework.integration.core.MessagingTemplate.doSend(MessagingTemplate.java:288)
    	at org.springframework.integration.core.MessagingTemplate.doSendAndReceive(MessagingTemplate.java:318)
    	at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:239)
    	at org.springframework.integration.core.MessagingTemplate.sendAndReceive(MessagingTemplate.java:235)
    	at com.aetna.framework.integration.test.HttpInboundGatewayIntegrationTest.test_1(HttpInboundGatewayIntegrationTest.java:57)
    can any one provide guidance for an appropriate setup for this type of interaction?

    thanks,
    tony.

  • #2
    The Exception that you are seeing is because the outbound side has no "reply-channel" configured nor do the Messages being passed to it do not contain a "replyChannel" header. Do you intend for it to be a request/reply (bidirectional) flow? If so, one or the other needs to be present (or an upstream "gateway" would add the "replyChannel" header automatically).

    As for the header not being mapped, have a look at DefaultHttpHeaderMapper. There you will see that the user-defined header prefix is appended to any header names that are mapped to HTTP Headers (the default prefix being "X-" as that is the recommended/conventional approach). You can either work with that behavior, or you can implement your own HeaderMapper and reference it via the "header-mapper" attribute.

    HTH,
    Mark

    Comment


    • #3
      thanks mark,

      w.r.t. the exception when extract-request-payload="false"

      i'm using MessagingTemplate which should apply a dynamic replyChannel if one isn't specified:

      Code:
          Message<?> message = MessageBuilder.withPayload(m_request).setHeader(KEY_1, VAL_1).build();
          message = new MessagingTemplate(m_channel).sendAndReceive(message);
      and i understand why replyChannel is being stripped for non-serializability for the transport:

      Code:
      [inbound-gateway-test] 2010-11-27 10:24:52,984 INFO [org.springframework.integration.MessageHeaders] - removing non-serializable header: errorChannel
      [inbound-gateway-test] 2010-11-27 10:24:52,984 INFO [org.springframework.integration.MessageHeaders] - removing non-serializable header: replyChannel
      but it seems like MessagingTemplate should still hold on to that dynamic replyChannel to field the response.

      the MessagingTemplate auto-replyChannel behavior works as expected when extract-request-payload="true", so it is

      curious that it doesn't work with extract-request-payload="false"...?

      w.r.t. DefaultHttpHeaderMapper

      this hint really helped!

      i was having an issue with STS inadvertently picking up the SI-2.M4 namespace schemas and the mapped-request-headers attribute wasn't being offered for si-http:outbound-gateway.

      i used your suggested trick "window->preferences->spring->beans support->namespaces->use xsd's from classpath",
      and was able to see the latest list of namespace attributes which is obviously a great help in understanding the available options for a component.

      so, i altered my outbound-gateway definition to:

      Code:
        <http:outbound-gateway id="http" request-channel="http.output" url="${url}"
          extract-request-payload="true" charset="UTF-8" request-timeout="1000" expected-response-type="java.lang.String"
          mapped-request-headers="key-1" mapped-response-headers="key-1,key-2" />
      i also found that i had to modify the inbound-gateway to look like:

      Code:
        <bean id="my.headerMapper" class="org.springframework.integration.http.support.DefaultHttpHeaderMapper">
          <property name="inboundHeaderNames" value="key-1" />
          <property name="outboundHeaderNames" value="key-1,key-2" />
        </bean>
      
        <http:inbound-gateway id="inboundGateway" request-channel="request.input" convert-exceptions="true"
          request-payload-type="java.lang.String" header-mapper="my.headerMapper" />
      is this correct that there is no mapped-request-headers attribute in the namespace xsd for inbound-gateway,
      and that i have to provide a specially configured header-mapper...?

      the above configuration provided the expected behavior with respect to passing the "key-1" header from the outbound to the inbound gateways.

      i was however unsuccesful in my (perhaps misguided) attempt to change the "key-1" header and add a "key-2" header on the response from the inbound side to the outbound side.

      here is what my service-activator method on the response side looks like,
      but the "key-1" header was unchanged and "key-2" header absent on the response message at the outbound side:

      Code:
        public Message<?> invoke(Message<?> message)
        {
          s_log.debug("invoke(): received message={}", message);
          return MessageBuilder.withPayload("result").setHeader("key-1", "val-1-2").setHeader("key-2", "val-2-1").build();
        }
      are we supposed to be able to update/add headers on the response in this way...?

      thanks,
      tony.

      Comment

      Working...
      X