Announcement Announcement Module
Collapse
No announcement yet.
Spring and JAXWS: No mixing of @Webmethod and @Transactional Annotations allowed Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring and JAXWS: No mixing of @Webmethod and @Transactional Annotations allowed

    Hello,
    we discovered a problem today. We use the Spring integration of the JAX-WS webservice and this was working pretty fine so far.

    An example of how our Webservice looks like can be found here, as it is pretty similar:
    http://www.tutego.com/blog/javainsel/labels/Java.html

    Today we started to add the @Transactional annotations to some methods. Suddenly we got the following exceptions:

    Code:
    org.springframework.beans.factory.BeanCreationException: Error creating
    bean with name 'jax-ws.http' defined in file
    [C:\Dev\workspace\myProjectDomain\src\web\WEB-INF\myProjectDomain-webServices.xml]:
    Cannot create inner bean 'wss:binding#11c2b67' of type
    [com.sun.xml.ws.transport.http.servlet.SpringBinding] while setting bean
    property 'bindings' with key [0]; nested exception is
    org.springframework.beans.factory.BeanCreationException: Error creating
    bean with name 'wss:binding#11c2b67' defined in file
    [C:\Dev\workspace\myProjectDomain\src\web\WEB-INF\myProjectDomain-webServices.xml]:
    Cannot create inner bean '(inner bean)' of type
    [org.jvnet.jax_ws_commons.spring.SpringService] while setting bean
    property 'service'; nested exception is
    org.springframework.beans.factory.BeanCreationException: Error creating
    bean with name '(inner bean)#1': FactoryBean threw exception on object
    creation; nested exception is java.lang.IllegalArgumentException: class
    de.myCompany.myProject.services.lager.LagerService$$EnhancerByCGLIB$$35598ee0
    has neither @WebSerivce nor @WebServiceProvider annotation
    Caused by: org.springframework.beans.factory.BeanCreationException:
    Error creating bean with name 'wss:binding#11c2b67' defined in file
    [C:\Dev\workspace\myProjectDomain\src\web\WEB-INF\myProjectDomain-webServices.xml]:
    Cannot create inner bean '(inner bean)' of type
    [org.jvnet.jax_ws_commons.spring.SpringService] while setting bean
    property 'service'; nested exception is
    org.springframework.beans.factory.BeanCreationException: Error creating
    bean with name '(inner bean)#1': FactoryBean threw exception on object
    creation; nested exception is java.lang.IllegalArgumentException: class
    de.myCompany.myProject.services.lager.LagerService$$EnhancerByCGLIB$$35598ee0
    has neither @WebSerivce nor @WebServiceProvider annotation
    Caused by: org.springframework.beans.factory.BeanCreationException:
    Error creating bean with name '(inner bean)#1': FactoryBean threw
    exception on object creation; nested exception is
    java.lang.IllegalArgumentException: class
    de.myCompany.myProject.services.lager.LagerService$$EnhancerByCGLIB$$35598ee0
    has neither @WebSerivce nor @WebServiceProvider annotation
    Caused by: java.lang.IllegalArgumentException: class
    de.myCompany.myProject.services.lager.LagerService$$EnhancerByCGLIB$$35598ee0
    has neither @WebSerivce nor @WebServiceProvider annotation
        at
    com.sun.xml.ws.server.EndpointFactory.verifyImplementorClass(EndpointFactory.java:273)
        at
    org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:311)
        at
    org.jvnet.jax_ws_commons.spring.SpringService.getObject(SpringService.java:44)

    I had a look into the sourcecode of the place where the exception is thrown, which can be found here:

    http://fisheye5.cenqua.com/browse/ja...ava?r=1.4#l273

    Code:
    /**
    273 	     * Verifies if the endpoint implementor class has @WebService or @WebServiceProvider
    274 	     * annotation
    275 	     *
    276 	     * @return
    277 	     *       true if it is a Provider or AsyncProvider endpoint
    278 	     *       false otherwise
    279 	     * @throws java.lang.IllegalArgumentException
    280 	     *      If it doesn't have any one of @WebService or @WebServiceProvider
    281 	     *      If it has both @WebService and @WebServiceProvider annotations
    282 	     */
    283 	    public static boolean verifyImplementorClass(Class<?> clz) {
    284 	        WebServiceProvider wsProvider = clz.getAnnotation(WebServiceProvider.class);
    285 	        WebService ws = clz.getAnnotation(WebService.class);
    286 	        if (wsProvider == null && ws == null) {
    287 	            throw new IllegalArgumentException(clz +" has neither @WebSerivce nor @WebServiceProvider annotation");
    288 	        }
    289 	        if (wsProvider != null && ws != null) {
    290 	            throw new IllegalArgumentException(clz +" has both @WebSerivce and @WebServiceProvider annotations");
    291 	        }
    292 	        if (wsProvider != null) {
    293 	            if (Provider.class.isAssignableFrom(clz) || AsyncProvider.class.isAssignableFrom(clz)) {
    294 	                return true;
    295 	            }
    296 	            throw new IllegalArgumentException(clz +" doesn't implement Provider or AsyncProvider interface");
    297 	        }
    298 	        return false;
    299 	    }
    It looks like clz.getAnnotation(WebService.class); doesn't find the right annotation when there are other annotations present.

    After we removed ALL @Transactional annotations it worked pretty fine again. FYI: Annotation driven Transaction handling is properly configured in Spring context and already working in other class which are NO webservices. Only in JAXWS Webservice annotated classes we get these problems.

    We will try now to use Spring's TransactionTemplate to circumvent this problem and get Transaction handling but annotations would be much better.

    Does anybody have an explanation for this problem or a solution?


    Thanks
    Christoph

  • #2
    Hi.

    I've got the same problem but with other annotations - not @Transactional but AOP annotations like @Before, @AfterReturning etc.

    Seems this is a problem of the JAX-WS implemenation not able to handle other annotations?

    (How)Did you solve your problem?

    Comment


    • #3
      JAXWS Spring @WebService

      Hi ,

      I am experiencing similar issue while using MethodInterceptor for authorization of web services method for Acegi.

      org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'com.sun.xml
      .ws.transport.http.servlet.SpringBinding' defined in ServletContext resource [/WEB-INF/applicationC
      ontext.xml]: Cannot create inner bean '(inner bean)' while setting bean property 'service'; nested
      exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name
      '(inner bean)': FactoryBean threw exception on object creation; nested exception is java.lang.Ille
      galArgumentException: class CustProdServiceImpl$$EnhancerByCGLIB$
      $e133575d has neither @WebSerivce nor @WebServiceProvider annotation
      Caused by:
      org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name '(inner bean
      )': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentEx
      ception: class CustProdServiceImpl$$EnhancerByCGLIB$$e133575d has
      neither @WebSerivce nor @WebServiceProvider annotation
      Caused by:
      java.lang.IllegalArgumentException: class CustProdServiceImpl$$En
      hancerByCGLIB$$e133575d has neither @WebSerivce nor @WebServiceProvider annotation
      at com.sun.xml.ws.server.EndpointFactory.verifyImplem entorClass(EndpointFactory.java:273)
      at org.jvnet.jax_ws_commons.spring.SpringService.getO bject(SpringService.java:311)
      at org.jvnet.jax_ws_commons.spring.SpringService.getO bject(SpringService.java:44)
      at org.springframework.beans.factory.support.Abstract BeanFactory.getObjectFromFactoryBean(A

      My Class implements an interface still It needs CGLIB, couldnt understand
      Is it something like the the spring web services binding is happening on the generated proxy ??

      Any ideas..

      Thanks

      Comment


      • #4
        Meanwhile I read a bit further about annotations. Seems that per default annotations aren't inherited to subclasses per default. It must be explicitly specified by the annotation itself (e.g. @WebService). Since @WebService doesn't have the @inherited annotation, it won't be inherited to the proxy I guess. So I think it won't be too easy to publish the annotations from the WebService to the proxy. But perhaps I'm totally wrong. I don't know if the proxy could be enhanced to delegate annotation requests to the superclass somehow.

        I think that JAX-WS/jax-ws-commons should be enhanced to look for annotations up the hierarchy if it doesn't find one on the class/identified proxy.

        I created an issue at the jax-ws-commons issue tracker.

        Regards,
        Veit

        Comment


        • #5
          I guess, you may try 2 follwing approaches to overcome this limitation
          1. Try to use CGLIB proxies instead of standard Java proxies. BTW, standard Java proxies proxy not class but interface so even @inherited will not help.
          2. Try to use AspectJ instead of proxy-based AOP.

          Regards,
          Oleksandr

          Originally posted by vguna View Post
          Meanwhile I read a bit further about annotations. Seems that per default annotations aren't inherited to subclasses per default. It must be explicitly specified by the annotation itself (e.g. @WebService). Since @WebService doesn't have the @inherited annotation, it won't be inherited to the proxy I guess. So I think it won't be too easy to publish the annotations from the WebService to the proxy. But perhaps I'm totally wrong. I don't know if the proxy could be enhanced to delegate annotation requests to the superclass somehow.

          I think that JAX-WS/jax-ws-commons should be enhanced to look for annotations up the hierarchy if it doesn't find one on the class/identified proxy.

          I created an issue at the jax-ws-commons issue tracker.

          Regards,
          Veit

          Comment


          • #6
            Hi Oleksandr.

            Originally posted by al0 View Post
            I guess, you may try 2 follwing approaches to overcome this limitation
            1. Try to use CGLIB proxies instead of standard Java proxies. BTW, standard Java proxies proxy not class but interface so even @inherited will not help.
            2. Try to use AspectJ instead of proxy-based AOP.

            Regards,
            Oleksandr
            Since my WebService HAS an interface (endpoint interface) with annotations standard JDK proxy should work, shouldn't it?
            Nevertheless I tried CGLIB already - same effect . Thought about using AspectJ as an alternative - not tried yet. Couldn't find anything in google concerning AspectJ and inherited annotations so I hadn't much hope. But I will try it as you suggest. Thanks.

            Comment


            • #7
              Originally posted by vguna View Post
              Hi Oleksandr.



              Since my WebService HAS an interface (endpoint interface) with annotations standard JDK proxy should work, shouldn't it?
              Nevertheless I tried CGLIB already - same effect . Thought about using AspectJ as an alternative - not tried yet. Couldn't find anything in google concerning AspectJ and inherited annotations so I hadn't much hope. But I will try it as you suggest. Thanks.
              No they should not, way in which annotation are defined in Java language spec is one big mess

              Class posesses no direct knowledge about annotations that are defined on the implemented interfaces. Sure, it is possible to obtain a list of implemented interfaces (via getIntefaces()), but this should be done not in your code, but in the code that processes annotations, see SPR-2522, SPR-2521 and SPR-2514 for some more discussion.

              Comment


              • #8
                @WebServices BeanNameAutoProxyCreator

                Is this a known limitation and if its ,are their any plans to address this.

                TIA

                Comment


                • #9
                  Hey all - I ran into this problem too. I got around it by using a @WebService class that implemented the service endpoint interface by forwarding requests to a @Transactional bean that actually did all the work. Then hooked them together using Spring. Effectively it split up the annotations.

                  Hopefully there's a better solution out there, but for my small project it wasn't a problem...

                  Originally posted by vguna View Post
                  Hi Oleksandr.



                  Since my WebService HAS an interface (endpoint interface) with annotations standard JDK proxy should work, shouldn't it?
                  Nevertheless I tried CGLIB already - same effect . Thought about using AspectJ as an alternative - not tried yet. Couldn't find anything in google concerning AspectJ and inherited annotations so I hadn't much hope. But I will try it as you suggest. Thanks.

                  Comment


                  • #10
                    Originally posted by eldaaran View Post
                    Hey all - I ran into this problem too. I got around it by using a @WebService class that implemented the service endpoint interface by forwarding requests to a @Transactional bean that actually did all the work. Then hooked them together using Spring. Effectively it split up the annotations.

                    Hopefully there's a better solution out there, but for my small project it wasn't a problem...

                    Hi, we are facing same problem here .. Can you detail out your workaround please..

                    Comment


                    • #11
                      Breaking up the annotations worked for me with a relatively simple web service. I imagine this would be unwieldy with a big project though.

                      Take the following interface:

                      Code:
                      public interface ICalculator {
                      
                      	int add(int a, int b);
                      }
                      Implement it using declarative transactions:

                      Code:
                      public class CalculatorImpl implements ICalculator {
                      
                      	@Transactional
                      	public int add(int a, int b) {
                      		//do some database stuff requiring the transaction
                      		return a + b;
                      	}
                      }
                      Create the web service implementation you want to expose and use Spring to inject CalculatorImpl:

                      Code:
                      @WebService
                      public class CalculatorService implements ICalculator {
                      	private ICalculator impl; 
                      	
                      	public void setICalculator(ICalculator impl) {
                      		this.impl = impl;
                      	}
                      
                      	@WebMethod
                      	public int add(int a, int b) {
                      		return impl.add(a, b);
                      	}
                      }

                      Comment


                      • #12
                        The solution is given here (add impl to service declaration):

                        Code:
                        <wss:binding url="/services/greeterService">
                           <wss:service>
                              <ws:service bean="#greeter" impl="org.codehut.Greeter" />
                           </wss:service>
                        </wss:binding>

                        Comment


                        • #13
                          Using SimpleJaxWsServiceExporter and AOP...

                          I am exposing my standalone web service using org.springframework.remoting.jaxws.SimpleJaxWsServ iceExporter . I am running into the same issue: class $Proxy11 has neither @WebSerivce nor @WebServiceProvider annotation

                          Any ideas how I can resolve this?

                          Comment


                          • #14
                            I guess that switching to AspectJ LTW (from proxy-based AOP) would solve your problem.

                            Comment


                            • #15
                              I have the same problem and got class $Proxy45 has neither @WebSerivce nor @WebServiceProvider annotation
                              I break up the annotations followed the example by eldaaran. My config file is as following:

                              <bean id="psecService" class="com.pyramis.security.service.PSECServicesBe an" init-method="init" destroy-method="destroy">
                              </bean>
                              <wss:binding url="/services/FSECWebService">
                              <wss:service>
                              <ws:service bean="#FSECWebService" />
                              </wss:service>
                              </wss:binding>
                              <bean id="FSECWebService" class="fmtc.security.ws.FSECWebService" init-method="init" destroy-method="destroy">
                              <property name="psecService" ref="psecService" />
                              </bean>

                              Here is the exception I got:
                              Feb 3, 2013 10:14:26 PM org.apache.catalina.core.StandardContext listenerStart
                              SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListe ner
                              org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name 'com.sun.xml.ws.transport.http.servlet.SpringBindi ng' defined in file [C:\Apps\workspace\.metadata\.plugins\org.eclipse.w st.server.core\tmp0\wtpwebapps\PSecServiceWeb\WEB-INF\classes\spring\serviceContext.xml]: Cannot create inner bean '(inner bean)' while setting bean property 'service'; nested exception is org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name '(inner bean)#1': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: class $Proxy45 has neither @WebSerivce nor @WebServiceProvider annotation
                              Caused by: org.springframework.beans.factory.BeanCreationExce ption: Error creating bean with name '(inner bean)#1': FactoryBean threw exception on object creation; nested exception is java.lang.IllegalArgumentException: class $Proxy45 has neither @WebSerivce nor @WebServiceProvider annotation
                              Caused by: java.lang.IllegalArgumentException: class $Proxy45 has neither @WebSerivce nor @WebServiceProvider annotation
                              at com.sun.xml.ws.server.EndpointFactory.verifyImplem entorClass(EndpointFactory.java:287)
                              at org.jvnet.jax_ws_commons.spring.SpringService.getO bject(SpringService.java:317)
                              at org.jvnet.jax_ws_commons.spring.SpringService.getO bject(SpringService.java:45)
                              at org.springframework.beans.factory.support.Abstract BeanFactory.getObjectFromFactoryBean(AbstractBeanF actory.java:994)
                              at org.springframework.beans.factory.support.Abstract BeanFactory.getObjectForBeanInstance(AbstractBeanF actory.java:960)
                              at org.springframework.beans.factory.support.BeanDefi nitionValueResolver.resolveInnerBeanDefinition(Bea nDefinitionValueResolver.java:202)
                              at org.springframework.beans.factory.support.BeanDefi nitionValueResolver.resolveValueIfNecessary(BeanDe finitionValueResolver.java:116)
                              at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.applyPropertyValues(Abs tractAutowireCapableBeanFactory.java:955)
                              at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.populateBean(AbstractAu towireCapableBeanFactory.java:729)
                              at org.springframework.beans.factory.support.Abstract AutowireCapableBeanFactory.createBean(AbstractAuto wireCapableBeanFactory.java:416)
                              at org.springframework.beans.factory.support.Abstract BeanFactory$1.getObject(AbstractBeanFactory.java:2 45)
                              at org.springframework.beans.factory.support.DefaultS ingletonBeanRegistry.getSingleton(DefaultSingleton BeanRegistry.java:141)
                              at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:242)
                              at org.springframework.beans.factory.support.Abstract BeanFactory.getBean(AbstractBeanFactory.java:156)
                              at org.springframework.beans.factory.support.DefaultL istableBeanFactory.preInstantiateSingletons(Defaul tListableBeanFactory.java:290)
                              at org.springframework.context.support.AbstractApplic ationContext.refresh(AbstractApplicationContext.ja va:348)
                              at org.springframework.web.context.support.AbstractRe freshableWebApplicationContext.refresh(AbstractRef reshableWebApplicationContext.java:156)
                              at org.springframework.web.context.ContextLoader.crea teWebApplicationContext(ContextLoader.java:246)
                              at org.springframework.web.context.ContextLoader.init WebApplicationContext(ContextLoader.java:184)
                              at org.springframework.web.context.ContextLoaderListe ner.contextInitialized(ContextLoaderListener.java: 49)
                              at org.apache.catalina.core.StandardContext.listenerS tart(StandardContext.java:4206)
                              at org.apache.catalina.core.StandardContext.start(Sta ndardContext.java:4705)
                              at org.apache.catalina.core.ContainerBase.start(Conta inerBase.java:1057)
                              at org.apache.catalina.core.StandardHost.start(Standa rdHost.java:840)
                              at org.apache.catalina.core.ContainerBase.start(Conta inerBase.java:1057)
                              at org.apache.catalina.core.StandardEngine.start(Stan dardEngine.java:463)
                              at org.apache.catalina.core.StandardService.start(Sta ndardService.java:525)
                              at org.apache.catalina.core.StandardServer.start(Stan dardServer.java:754)
                              at org.apache.catalina.startup.Catalina.start(Catalin a.java:595)
                              at sun.reflect.NativeMethodAccessorImpl.invoke0(Nativ e Method)
                              at sun.reflect.NativeMethodAccessorImpl.invoke(Native MethodAccessorImpl.java:39)
                              at sun.reflect.DelegatingMethodAccessorImpl.invoke(De legatingMethodAccessorImpl.java:25)
                              at java.lang.reflect.Method.invoke(Method.java:597)
                              at org.apache.catalina.startup.Bootstrap.start(Bootst rap.java:289)
                              at org.apache.catalina.startup.Bootstrap.main(Bootstr ap.java:414)
                              Feb 3, 2013 10:14:26 PM org.apache.catalina.core.StandardContext start
                              SEVERE: Error listenerStart

                              Any help will be appreciated.

                              Comment

                              Working...
                              X