Camel
  1. Camel
  2. CAMEL-5234

Spring-WS does neither set message body nor message headers if exchange is not outCapable

    Details

    • Estimated Complexity:
      Unknown

      Description

      Spring-WS component does not behave as expected from pipes and filters pattern if exchange is not outCapable.
      If ExchangeHelper.isOutCapable returns false for the given exchange the IN-message is returned instead of the WS-Response.
      Example:

      ExampleRoute
              from("timer://foo?fixedRate=true&period=1000")//
                      .setBody().simple("<ex:getExampleResponse xmlns:ex=\"http://example.com/\">" //
                              + "       <id>1</id>" //
                              + "     </ex:getExampleResponse>")//
                      .to("spring-ws:http://localhost:9000/Example")//
                      .to("file://responses");
      

      In the example above I would expect the WS-response written to the files in the responses directory. Currently (since 2.7.3) the IN message is written to the files.
      This is caused by SpringWebserviceProducer#process because it only sets headers and body for the OUT-message if isOutCapable is true.

      Workaround (maybe this has side effects!):

      ExampleRoute
                      from("timer://foo?fixedRate=true&period=1000")//
                      .setExchangePattern(ExchangePattern.InOut) // <-- Override with InOut Pattern
                      .setBody().simple("<ex:getExampleResponse xmlns:ex=\"http://example.com/\">" //
                              + "       <id>1</id>" //
                              + "     </ex:getExampleResponse>")//
                      .to("spring-ws:http://localhost:9000/Example")//
                      .to("file://responses");
      

      This behavior has been implemented to fix CAMEL-3974. From my point of view its counter intuitive since other processing-steps don't check the exchange's outCapability.
      It took me several hours to find out why I always got the IN message back, although the webservice was called correctly and returned correct results.
      Maybe an option should be provided to control this behavior. At least a log-message should be written to explain, that the webservice-reponse is thrown away.

        Activity

        Hide
        Babak Vahdat added a comment -

        This behavior is intended and not a bug!

        So that if you need an InOut Exchange-Pattern then just say it using the DSL, that's instead of:

        to("spring-ws:http://...")...
        

        you could do:

        ...inOut("spring-ws:http://...")....
        

        See also http://camel.465427.n5.nabble.com/VOTE-Release-Apache-Camel-2-8-0-td4584312i20.html#a4593321

        Show
        Babak Vahdat added a comment - This behavior is intended and not a bug! So that if you need an InOut Exchange-Pattern then just say it using the DSL, that's instead of: to( "spring-ws:http: //..." )... you could do: ...inOut( "spring-ws:http: //..." ).... See also http://camel.465427.n5.nabble.com/VOTE-Release-Apache-Camel-2-8-0-td4584312i20.html#a4593321
        Hide
        Babak Vahdat added a comment -

        BTW as in the meanwhile inOut() has been already deprecated, then better make use of setExchangePattern(exchangePattern) API.
        See the Javadoc of inOut() for more details.

        Show
        Babak Vahdat added a comment - BTW as in the meanwhile inOut() has been already deprecated, then better make use of setExchangePattern(exchangePattern) API. See the Javadoc of inOut() for more details.
        Hide
        Babak Vahdat added a comment -

        Just realized that you have already made use of setExchangePattern(ExchangePattern.InOut) API.

        I do agree to put a log-message to warn that the webservice-response will be thrown away. Do you have any suggestion for a meaningful and well-understandable log message to be used here?

        Show
        Babak Vahdat added a comment - Just realized that you have already made use of setExchangePattern(ExchangePattern.InOut) API. I do agree to put a log-message to warn that the webservice-response will be thrown away. Do you have any suggestion for a meaningful and well-understandable log message to be used here?
        Hide
        Benjamin Gniza added a comment - - edited

        Regarding your linked post:
        Didn't you say there that this seems API-breaking for you? Providing such a change in a patch version shouldn't be done. (This behavior was introduced from 2.7.2 to 2.7.3).

        Anyway, I think this may be intentional but is very confusing. Using the restlet-component (http://camel.apache.org/restlet.html) you don't have to change the Exchange-Pattern but can go with the following example (which is similiar to my first spring-ws example):

        Restlet Example
        from("timer://foo?fixedRate=true&period=1000")//
                        .setHeader("id", new SimpleExpression("1"))//
                        .to("restlet:http://localhost:9000/Example/{id}")//
                        .to("file://responses");
        

        I think we agree that this inconsitent component behavior may confuse a lot of people.

        Show
        Benjamin Gniza added a comment - - edited Regarding your linked post: Didn't you say there that this seems API-breaking for you? Providing such a change in a patch version shouldn't be done. (This behavior was introduced from 2.7.2 to 2.7.3). Anyway, I think this may be intentional but is very confusing. Using the restlet-component ( http://camel.apache.org/restlet.html ) you don't have to change the Exchange-Pattern but can go with the following example (which is similiar to my first spring-ws example): Restlet Example from( "timer: //foo?fixedRate= true &period=1000" )// .setHeader( "id" , new SimpleExpression( "1" )) // .to( "restlet:http: //localhost:9000/Example/{id}" )// .to( "file: //responses" ); I think we agree that this inconsitent component behavior may confuse a lot of people.
        Hide
        Babak Vahdat added a comment -

        Yes at that time it seemed / was API breaking to me as it happened in a patch version. And do agree that this could be confusing for people trying to upgrade.

        I will try to get in touch with Richard Kettelerij who has denoted this component. Just wonder what he thinks about this.

        Show
        Babak Vahdat added a comment - Yes at that time it seemed / was API breaking to me as it happened in a patch version. And do agree that this could be confusing for people trying to upgrade. I will try to get in touch with Richard Kettelerij who has denoted this component. Just wonder what he thinks about this.
        Hide
        Claus Ibsen added a comment -

        Yes the response from Spring-WS should be used regardless of the MEP pattern. Only if the actual invoked web service method is a OneWay web service, then it should not use the response from the WS. eg bottom line its the nature of the WS method that dictates this, not the MEP flag in Camel.

        Show
        Claus Ibsen added a comment - Yes the response from Spring-WS should be used regardless of the MEP pattern. Only if the actual invoked web service method is a OneWay web service, then it should not use the response from the WS. eg bottom line its the nature of the WS method that dictates this, not the MEP flag in Camel.
        Hide
        Christian Müller added a comment -

        This means if the MEP is inOnly and the web service returns a response, we should put this into the in message (body and headers) after cleaning it from the request body and headers, right?

        Show
        Christian Müller added a comment - This means if the MEP is inOnly and the web service returns a response, we should put this into the in message (body and headers) after cleaning it from the request body and headers, right?
        Hide
        Claus Ibsen added a comment -

        Yes.

        Normally the response is set on the IN message if its NOT out capable.

        if OUT capable
        set response OUT
        else
        set response IN

        But in the world of WS you can have OneWay which is a bit special WS. Normally they are request/reply over WS.

        Show
        Claus Ibsen added a comment - Yes. Normally the response is set on the IN message if its NOT out capable. if OUT capable set response OUT else set response IN But in the world of WS you can have OneWay which is a bit special WS. Normally they are request/reply over WS.
        Hide
        Babak Vahdat added a comment - - edited

        Now I'm a bit confused
        Currently we have the following by SpringWebserviceProducer

        if (ExchangeHelper.isOutCapable(exchange)) {
            exchange.getOut().copyFrom(exchange.getIn());
            exchange.getOut().setBody(body);
        }
        

        Now do you mean we should change this to

        if (ExchangeHelper.isOutCapable(exchange)) {
            exchange.getOut().copyFrom(exchange.getIn());
            exchange.getOut().setBody(body);
        } else {
            exchange.getIn().setBody(body);
        }
        

        And what about camel-restlet? Seems it doesn't care about MEP:
        https://fisheye6.atlassian.com/browse/~br=trunk/camel/trunk/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java?hb=true#to266

        Also do we maybe have a documentation about these MEP rules somewhere where I can learn it from?

        Show
        Babak Vahdat added a comment - - edited Now I'm a bit confused Currently we have the following by SpringWebserviceProducer if (ExchangeHelper.isOutCapable(exchange)) { exchange.getOut().copyFrom(exchange.getIn()); exchange.getOut().setBody(body); } Now do you mean we should change this to if (ExchangeHelper.isOutCapable(exchange)) { exchange.getOut().copyFrom(exchange.getIn()); exchange.getOut().setBody(body); } else { exchange.getIn().setBody(body); } And what about camel-restlet? Seems it doesn't care about MEP: https://fisheye6.atlassian.com/browse/~br=trunk/camel/trunk/components/camel-restlet/src/main/java/org/apache/camel/component/restlet/DefaultRestletBinding.java?hb=true#to266 Also do we maybe have a documentation about these MEP rules somewhere where I can learn it from?
        Hide
        Babak Vahdat added a comment -

        Also looking at camel-cxf it does the same way as camel-spring-ws (which is a different behaviour than camel-restlet ):

        https://fisheye6.atlassian.com/browse/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java?hb=true#to183

        Show
        Babak Vahdat added a comment - Also looking at camel-cxf it does the same way as camel-spring-ws (which is a different behaviour than camel-restlet ): https://fisheye6.atlassian.com/browse/camel/trunk/components/camel-cxf/src/main/java/org/apache/camel/component/cxf/jaxrs/CxfRsProducer.java?hb=true#to183
        Hide
        Christian Müller added a comment -

        Babak, could you please start a general discussion about this on dev@.
        My understanding is the following:
        If a component provides integration for e.g. spring-ws and execute a request which will receive a respone, this component should check the MEP and put the respone into the out message if the MEP is "put capable" or replace the in message if not (and also the headers and attachments of course).

        Show
        Christian Müller added a comment - Babak, could you please start a general discussion about this on dev@. My understanding is the following: If a component provides integration for e.g. spring-ws and execute a request which will receive a respone, this component should check the MEP and put the respone into the out message if the MEP is "put capable" or replace the in message if not (and also the headers and attachments of course).
        Show
        Babak Vahdat added a comment - Done: http://camel.465427.n5.nabble.com/About-what-to-do-with-the-Response-retrieved-through-a-Producer-when-the-Exchange-is-NOT-out-capable-td5713946.html
        Hide
        Babak Vahdat added a comment -

        A potential patch for the review.

        Show
        Babak Vahdat added a comment - A potential patch for the review.
        Hide
        Claus Ibsen added a comment -

        The patch seems fine

        Show
        Claus Ibsen added a comment - The patch seems fine
        Hide
        Christian Müller added a comment -

        Looks good for me too.

        Show
        Christian Müller added a comment - Looks good for me too.

          People

          • Assignee:
            Babak Vahdat
            Reporter:
            Benjamin Gniza
          • Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development