title: Spring WS interceptors with injected DAO's @Transactional not working
body: <p>We have a legacy XML based configuration spring-ws application that contains endpointInterceptors that have DAOs injected to obtain configuration from the database. These DAOs have the hibernate sessionFactory injected.</p>
  
  <p>When we have upgraded to spring 4.2.0.RELEASE (from spring 3.2.5.RELEASE) and spring-ws 2.2.1.RELEASE (from spring-ws 2.1.4.RELEASE) I noticed that the DAO was not a proxy object and it seemed that the intercetor was going to the 
  AnnotationActionEndpointMapping class instead of the PayloadRootAnnotationMethodEndpointMapping class.</p>
  
  <p>I therefore created a spring-boot version 1.3.0.RELEASE based example that outlines our legacy application and the problem is evident in both XML base configuration and annotation based configuration. Please note that 
  annotation @EnableTransactionManagement exists within the example and that  exists within the legacy application.</p>
  
  <p>If you commented out the  from the application context or @EnableWS from the @Congiuration object then the DAO was a proxy object, the interceptor seemed to be going to the correct endpoing (i.e PayloadRootAnnotationMethodEndpointMapping) and the unit test worked with no transaction error.</p>
  
  <p>StackTrace when  or EnableWS is not commented out.</p>
  
  <pre class="lang-none prettyprint-override"><code>org.springframework.ws.soap.client.SoapFaultClientException: Could not obtain transaction-synchronized Session for current thread
      at org.springframework.ws.soap.client.core.SoapFaultMessageResolver.resolveFault(SoapFaultMessageResolver.java:38)
      at org.springframework.ws.client.core.WebServiceTemplate.handleFault(WebServiceTemplate.java:830)
      at org.springframework.ws.client.core.WebServiceTemplate.doSendAndReceive(WebServiceTemplate.java:624)
      at org.springframework.ws.client.core.WebServiceTemplate.sendAndReceive(WebServiceTemplate.java:555)
      at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:390)
      at org.springframework.ws.client.core.WebServiceTemplate.marshalSendAndReceive(WebServiceTemplate.java:378)
      at hello.ApplicationTests.testSendAndReceive(ApplicationTests.java:61)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
      at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
      at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
      at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
      at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
      at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
      at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
      at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
      at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:254)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:89)
      at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
      at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
      at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
      at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
      at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
      at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
      at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
      at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
      at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:193)
      at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
      at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:78)
      at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:212)
      at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:68)
      at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
      at com.intellij.rt.execution.application.AppMain.main(AppMain.java:140)
  </code></pre>
  
  <p>Extract of the XML configuration that causes the above exception :</p>
  
  <pre class="lang-xml prettyprint-override"><code>    &lt;sws:annotation-driven&gt;
      &lt;sws:interceptors&gt;
             &lt;ref bean="loggingInterceptorAU"/&gt;
      &lt;/sws:interceptors&gt;
  
  
  &lt;bean id="loggingInterceptorAU" class="hello.interceptor.LoggingEndpointInterceptor"/&gt;
  </code></pre>
  
  <p>Extract of the annotation configuration that causes the above exception :</p>
  
  <pre><code>@EnableWs
  @Configuration
  public class WebServiceConfig extends WsConfigurerAdapter {
  
      @Bean
      public ServletRegistrationBean messageDispatcherServlet(ApplicationContext applicationContext) {
          MessageDispatcherServlet servlet = new MessageDispatcherServlet();
          servlet.setApplicationContext(applicationContext);
          servlet.setTransformWsdlLocations(true);
          return new ServletRegistrationBean(servlet, "/ws/*");
      }
  
      @Bean(name = "countries")
      public DefaultWsdl11Definition defaultWsdl11Definition(XsdSchema countriesSchema) {
          DefaultWsdl11Definition wsdl11Definition = new DefaultWsdl11Definition();
          wsdl11Definition.setPortTypeName("CountriesPort");
          wsdl11Definition.setLocationUri("/ws");
          wsdl11Definition.setTargetNamespace("http://spring.io/guides/gs-producing-web-service");
          wsdl11Definition.setSchema(countriesSchema);
          return wsdl11Definition;
      }
  
      @Bean
      public XsdSchema countriesSchema() {
          return new SimpleXsdSchema(new ClassPathResource("countries.xsd"));
      }
  
      /**
       * Declaring the loggingInterceptor.
       * @return the new logging interceptor.
       */
      @Bean
      public LoggingEndpointInterceptor loggingInterceptor() {
          LoggingEndpointInterceptor loggingEndpointInterceptor = new LoggingEndpointInterceptor();
          return loggingEndpointInterceptor;
      }
  
      /**
       * Adds interceptors.
       * @param interceptors
       */
      @Override
      public void addInterceptors(List&lt;EndpointInterceptor&gt; interceptors) {
            // if these rows are uncommented
            // and payloadRootAnnotationMethodEndpointMapping method is commented you get
            // Error: SoapFaultClientException: Could not obtain transaction-synchronized Session for current thread
            interceptors.add(loggingInterceptor());
            super.addInterceptors(interceptors);
      }
  
  
      /**
       * Spring Boot with Plain Hibernate
       * @see {https://github.com/mdeinum/samples/tree/master/spring-boot-plain-hibernate}
       *
       * Need to also set within application.properties.
       * spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
       * @return
       */
      @Bean(name="sessionFactory")
      public HibernateJpaSessionFactoryBean sessionFactory() {
          return new HibernateJpaSessionFactoryBean();
      }
  }
  </code></pre>
  
  <p>After a closer inspection of the makeup of AnnotationActionEndpointMapping i have noticed that it implements BeanPostProcessor. The spring doco <a href="http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html" rel="nofollow noreferrer">http://docs.spring.io/spring/docs/current/spring-framework-reference/html/beans.html</a>  suggests that “... Because AOP auto-proxying is implemented as a BeanPostProcessor itself, neither BeanPostProcessors nor the beans they reference directly are eligible for auto-proxying, and thus do not have aspects woven into them.”
  and therefore I understand that @Transactional will not work.</p>
  
  <pre><code>public class AnnotationActionEndpointMapping extends AbstractActionMethodEndpointMapping implements BeanPostProcessor
  </code></pre>
  
  <p>My questions are :
  *what has changed that has caused spring-ws interceptors to be mapped by default to the AnnotationActionEndpointMapping class? 
  * As per Spring documentation it is suggested that both  and  or @EnableWs and method addInterceptors are requred. Is there any impact if  is commented out in our legacy application? </p>
  
  <p>Please note we have interceptors that are only invoked for certain requests using the following and we do not want to specicially create a PayloadRootAnnotationMethodEndpointMapping bean with the list of interceptors to overcome this problem:</p>
  
  <pre class="lang-xml prettyprint-override"><code>&lt;sws:interceptors&gt;
   &lt;sws:payloadRoot localPart="TestRequest" namespaceUri="http://www.test.com/test/request/1.0"&gt;
  ...
  </code></pre>