Announcement Announcement Module
Collapse
No announcement yet.
Autowiring MarshallingWebServiceOutboundGateway In Test Class Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Autowiring MarshallingWebServiceOutboundGateway In Test Class

    I have this MarshallingWebServiceOutboundGateway configured in a chain:
    Code:
    <int-ws:outbound-gateway id="our.OutboundGateway"
                                 interceptors="our.Interceptors"
                                 destination-provider="our.DestinationProvider"
                                 unmarshaller="our.Marshaller"
                                 marshaller="our.Marshaller"
                                 fault-message-resolver="our.SoapFaultMessageResolver"
                                 message-sender="our.HttpSender"
                                 message-factory="our.SaajMessageFactory"/>
    I think that if I can get a reference to it that I could attach it to a org.springframework.ws.test.server.MockWebServiceC lient by creating the mock server with the WebServiceTemplate from the gateway.
    In my test code I have:
    Code:
    @RunWith( SpringJUnit4ClassRunner.class )
    @ContextConfiguration( { applicationContext-integration.xml"
                           } )
    public class MyTest {
      @Autowired @Qualifier("our.OutboundGateway")
     private org.springframework.integration.ws.MarshallingWebServiceOutboundGateway _wsOutboundGateway
    It fails with a BeanCreationException. I cranked up the logging, and I've extracted the pertinent bits.
    Code:
    2013-04-12 13:32:50,221 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Creating instance of bean 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7'
    2013-04-12 13:32:52,252 [main] TRACE org.springframework.beans.factory.support.DefaultListableBeanFactory - Ignoring constructor [public org.springframework.integration.ws.MarshallingWebServiceOutboundGateway(java.lang.String,org.springframework.oxm.Marshaller,org.springframework.oxm.Unmarshaller,org.springframework.ws.WebServiceMessageFactory)] of bean 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7': org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7': Unsatisfied dependency expressed through constructor argument with index 0 of type [java.lang.String]: Could not convert constructor argument value of type [org.xyz.WsClientDestinationProvider] to required type [java.lang.String]: Failed to convert value of type 'org.xyz.WsClientDestinationProvider' to required type 'java.lang.String'; nested exception is java.lang.IllegalStateException: Cannot convert value of type [org.xyz.WsClientDestinationProvider] to required type [java.lang.String]: no matching editors or conversion strategy found
    2013-04-12 13:32:52,268 [main] TRACE org.springframework.beans.CachedIntrospectionResults - Getting BeanInfo for class [org.springframework.integration.ws.MarshallingWebServiceOutboundGateway]
    2013-04-12 13:32:52,268 [main] TRACE org.springframework.beans.CachedIntrospectionResults - Caching PropertyDescriptors for class [org.springframework.integration.ws.MarshallingWebServiceOutboundGateway]
    2013-04-12 13:32:52,611 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Invoking afterPropertiesSet() on bean with name 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7'
    2013-04-12 13:32:52,611 [main] DEBUG org.springframework.integration.ws.MarshallingWebServiceOutboundGateway - Unable to attempt conversion of Message payload types. Component 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7' has no explicit ConversionService reference, and there is no 'integrationConversionService' bean within the context.
    2013-04-12 13:32:52,611 [main] DEBUG org.springframework.beans.factory.support.DefaultListableBeanFactory - Finished creating instance of bean 'org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#11381e7'
    2013-04-12 13:32:53,127 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Found injected element on class [org.xyz..MyTest]: AutowiredFieldElement for private org.springframework.integration.ws.MarshallingWebServiceOutboundGateway org.xyz..MyTest._wsOutboundGateway
    2013-04-12 13:32:53,205 [main] DEBUG org.springframework.beans.factory.annotation.InjectionMetadata - Processing injected method of bean 'org.xyz..MyTest': AutowiredFieldElement for private org.springframework.integration.ws.MarshallingWebServiceOutboundGateway org.xyz..MyTest._wsOutboundGateway
    
    org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'org.xyz..MyTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.integration.ws.MarshallingWebServiceOutboundGateway org.xyz..MyTest._wsOutboundGateway; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.integration.ws.MarshallingWebServiceOutboundGateway] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=our.OutboundGateway)}
    Why does the log say "DEBUG org.springframework.beans.factory.annotation.Injec tionMetadata - Processing injected method of bean 'org.xyz..MyTest': AutowiredFieldElement for private org.springframework.integration.ws.MarshallingWebS erviceOutboundGateway org.xyz..MyTest._wsOutboundGateway", and I still get a BeanCreationException?

  • #2
    The bean with the name "our.OutboundGateway" is actually a consumer (either an EventDrivenConsumer or a PollingConsumer - depending on the type of the request channel).

    The actual bean name of the gateway is automatically generated; however, since 2.2, you can now get a reference to the handler (within an endpoint) via the alias "beanName.handler". So, in your case, it would be "our.OutboundGateway.handler".

    Comment


    • #3
      I don't know how to write that expression. In case it makes any difference, the "our" is just part of the name.

      I've tried
      Code:
      @Autowired @Qualifier("our.OutboundGateway.handler")
      private Object _wsOutboundGateway; // Using object out of desperation
      I've tried some stuff I found on StackOverflow using #this.getObject and #{byId()}. (I wouldn't ever know where to look those up in the documentation.

      So could you write the exact expression including if I should use the @Autowired @Qualifer combination or @Value?

      To say that I don't know what I'm doing with SpEL is accurate. I find SpEL to be a poorly documented subject.

      Comment


      • #4
        This has nothing to do with SpEL; it's simply a bean name.

        However, I just noticed you have no channels defined on the gateway. This implies it's inside a <chain/>. I now see you said that in your initial post, which I missed.

        Currently beans inside the chain (even with an ID) don't get registered as beans with the context - this is consistent with most inner beans.

        If you move it outside the chain, you should be able to get it with "our.OutboundGateway.handler".

        There is some work underway to change this, but it won't be available until 3.0.

        Comment


        • #5
          I can get the org.springframework.integration.endpoint.EventDriv enConsumer with @Value("#{@'our.OutboundGateway'}").

          When I try @Value("#{@'our.OutboundGateway'.handler}") I get an error because there is no getHandler method.

          I've split the int-ws:outbound-gateway out of the chain, but I still haven't figured out how to attach it to a the mock server provided by Spring-WS.

          Comment


          • #6
            When I try @Value("#{@'our.OutboundGateway'.handler}") I get an error because there is no getHandler method.
            Make it like this
            Code:
            @Value("#{@'our.OutboundGateway.handler'}")
            our.OutboundGateway.handler - is an alias to the endpoint's MessageHandler

            From other side why don't like this:
            Code:
            @Autowire
            @Qualifier("our.OutboundGateway.handler")
            ?

            -Artem

            P.S. Nevermind, I see what do you mean. I'll look at this, but my first suggestion should work.

            Comment


            • #7
              I still don't understand the issue; this works fine for me...

              Code:
              @ContextConfiguration("/META-INF/spring/integration/temperatureConversion.xml")
              @RunWith(SpringJUnit4ClassRunner.class)
              public class Foo {
              
              	@Autowired @Qualifier("foo.bar.handler")
              	private SimpleWebServiceOutboundGateway gateway;
              
              ...
              
              }
              	<ws:outbound-gateway id="foo.bar"
              		request-channel="celsiusChannel" reply-channel="celsiusChannel"
              		uri="http://www.w3schools.com/webservices/tempconvert.asmx"/>

              Comment


              • #8
                Code:
                @RunWith( SpringJUnit4ClassRunner.class )
                @ContextConfiguration( { ... the usual suspects ...} )
                  @Autowired
                  @Qualifier("our.OutboundGateway.handler")
                  private SimpleWebServiceOutboundGateway_outboundGateway;
                
                ...
                    <int-ws:outbound-gateway id="our.OutboundGateway"
                                             interceptors="our.Interceptors"
                                             destination-provider="our.DestinationProvider"
                                             unmarshaller="our..Marshaller"
                                             marshaller="our.Marshaller"
                                             fault-message-resolver="our.SoapFaultMessageResolver"
                                             message-sender="our.HttpSender"
                                             message-factory="our.SaajMessageFactory"
                                             request-channel="our.IntoWS"
                                             reply-channel="our.IntoChain"/>
                Gives me
                Code:
                org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'x.y.z.SomeTest': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private org.springframework.integration.ws.SimpleWebServiceOutboundGateway x.y.z.SomeTest._outboundGateway; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No matching bean of type [org.springframework.integration.ws.SimpleWebServiceOutboundGateway] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=our.OutboundGateway.handler)}
                To see if I can even get the bean I've tried
                Code:
                  @Autowired @Qualifier("our.OutboundGateway")
                  private EventDrivenConsumer _outboundGateway;
                And it finds it fine.

                Where is it documented that handler is an alias to the endpoint's MessageHandler. Couldn't find that in the Reference Manual or JavaDoc.

                Comment


                • #9
                  Well, I posted that as an example; in your case, you need to @Autowire a MarshallingWebServiceOutboundGateway not a SimpleWebServiceOutboundGateway.

                  We recently added the "....handler" alias as a convenience, because the generated names are brittle (they depend on the order in which they are parsed).

                  We should add a note to the documentation, feel free to open a Documentation JIRA.

                  Comment


                  • #10
                    I resorted to monkey-see-monkey-do code since it didn't even find it when I used Object. I've now tried the MarshallingWebServiceOutboundGateway, but get
                    Code:
                    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: 
                    No matching bean of type [org.springframework.integration.ws.MarshallingWebServiceOutboundGateway] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true), @org.springframework.beans.factory.annotation.Qualifier(value=our.OutboundGateway.handler)}
                    I which version of Spring Integration was the alias added? I'm using 2.1.3.

                    P.S. I'll be sure to jira the handler alias.

                    Comment


                    • #11
                      Sorry, I should have made that clear; this was added in 2.2.0

                      https://jira.springsource.org/browse/INT-2417

                      If you have to stick with 2.1.x (2.1.5 is the latest), you can use the generated bean name but, as I said, it's a little brittle - that's why we added the alias.

                      The bean name is the fully qualified class name followed by '#n' where n is the parse order.

                      So, if you only have one gateway, you can use "org.springframework.integration.ws.MarshallingWeb ServiceOutboundGateway#0" as the @Qualifier.
                      Last edited by Gary Russell; Apr 17th, 2013, 03:43 PM.

                      Comment


                      • #12
                        Problem solved. It's ugly but it works
                        Code:
                          @Autowired @Qualifier("org.springframework.integration.ws.MarshallingWebServiceOutboundGateway#0")
                          private MarshallingWebServiceOutboundGateway _outboundGateway;
                        Thanks much.

                        Comment


                        • #13
                          It's ugly but it works
                          Agreed - that's why we added the alias :-)

                          BTW, I mis-spoke, 2.1.5 is latest 2.1.x.

                          Comment

                          Working...
                          X