Announcement Announcement Module
Collapse
No announcement yet.
Spring + Axis + Ant Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring + Axis + Ant

    I am trying to automate the process of generating Axis proxies that expose Spring beans as webservices as part of my build process. Since the Axis proxies delegate to Spring beans, they are all very similar. I would also like to automate generation of the wsdd that references the appropriate endpoint rather than the default stub implementation that wsdl2java generates. Does anyone have any experience doing this as part of the build process?

    Thanks,
    Anthony

  • #2
    Delete the generated stub and write it yourself, using the same name.

    Comment


    • #3
      how Axis works in spring projects ? (concerns on axis handling elements as interface)

      Hi,

      I have some concerns about Spring Jax-Rpc remoting capabilities, though I think I have understood all the requirement to wrapp a spring service using Axis, as in fact I manage to deploy sucessfully my project, the WS seemed to be running fine on server-side (tomcat 5.5.15) at least (I would still need to test more using a spring Jax-Rpc client ..)


      To be clear my concern is rather on how Axis works in spring projects, assuming the following Service Endpoint Interface:

      Code:
      public interface EmployeeService {
      
          public Employee createEmployee(Employee employee);
          
          public Employee updateEmployee(Employee employee);
          
          public void deleteEmployee(Employee employee);
          
      /*    public Employee[]  findAllEmployees();
      
          public Employee[] findEmployeesByDept(Dept dept);
      */    
      }
      I would first remind that in my use case, I started with my existing spring service, trying to Java 2 WSDL (WSDL2Java is usually best) to wrap it as a WS; so the first problem I see is that Employee is an interface and not a class or as far as I have understood when getting a few axis stack traces http://forum.springframework.org/images/icons/icon7.gif , Axis will try to invoke the constuctor of that object to serialize/deserialize the input/output messages of the service, so if Axis really proper JavaBeans classes (with constructor, getters and setters...), I do not see how is it possible to use my spring interface as is (using Ant or not in fact) ?

      First may I give the details of my packages organization, using separate package for the interface and its impl class :
      • for the domain objects
        • demo.spring.live.domain.employee.Employee
        • demo.spring.live.domain.employee.impl.EmployeeImpl
        • demo.spring.live.domain.employee.impl.base.BaseEmp loyeeImpl
      • for the service
        • demo.spring.live.service.employee.EmployeeService
        • demo.spring.live.service.employee.impl.EmployeeSer viceImpl
      Please note as well I am using Hibernate with HibernateSynchonizer Eclipse plugin, as a consequence I get the hereunder inheritance:
      • public class EmployeeImpl extends BaseEmployeeImpl
      • public abstract class BaseEmployeeImpl implements Employee
      To bypass the Axis constraint on iterfaces, I did a Java2WSDL with Ant and had a look at the WSDL, then chnage the name of the elements Dept by DeptImpl , Employee by EmployeeImpl. I was so far quite happy, as my WSDL was cleaned (proper names and only 2 namespaces, 1 for the service, 1 for the transfer objects, in fact the domains ones) and with comments ...

      Then Doing a WSDL 2 Java mapping the namespaces of those elements to the package of my domain objects impl : demo.spring.live.domain.employee.impl

      I then laucnhed ant Ant Axis-Admin Task to deploy that service, it was OK, but ... when calling the WS URL http://localhost:8080/rrtSpringLive/...eeService?WSDL
      clearly the WSDL was uglyhttp://forum.springframework.org/images/icons/icon9.gif , as anyway I guess it is rebuilt from the class hierrachy, I think especially of a new namespace as Axis did resolve a kind of inheritance from BaseEmployeeImpl as a result, a new namespace was created , but the WSDL was almost not as clear as the one I did modified. Moreover the main point is that the EmployeeAxisPort & EmployeeAxisBindingSkeleton now do NOT follow my initial contract as my spring interface did use the Employee interface whereas Axis now uses its implementation class !

      After what I updated the server-config.wsdd to replace the endPoint class Name from demo.spring.live.service.employee.impl.EmployeeAxi sBindingSkeleton to demo.spring.live.service.employee.impl.EmployeeSer viceEndPoint as such

      Code:
      public class EmployeeServiceEndPoint extends ServletEndpointSupport implements RemoteEmployeeService {
          protected Log logger = LogFactory.getLog(EmployeeServiceEndPoint.class.getName());
          
          private EmployeeService employeeService;
      
          protected void onInit() {
              logger.debug("onInit");
              this.employeeService = (EmployeeService) getWebApplicationContext().getBean("rrt-employeeService");
          }
      
          
          public void setEmployeeService(EmployeeService employeeService) {
              this.employeeService = employeeService;
          }
          
          public Employee createEmployee(Employee employee){
              logger.debug("createEmployee");
              return employeeService.createEmployee(employee);
          }
          
          public Employee updateEmployee(Employee employee){
              logger.debug("updateEmployee");
              return employeeService.updateEmployee(employee);
          }
          
          public void deleteEmployee(Employee employee){
              logger.debug("deleteEmployee");
              employeeService.deleteEmployee(employee);
          }
          
      /*    public Employee[] findAllEmployees(){
              logger.debug("findAllEmployees");
              return employeeService.findAllEmployees();
          }    
      
          public Employee[] findEmployeesByDept(Dept dept){
              logger.debug("findEmployeesByDept");
              return employeeService.findEmployeesByDept(dept);
          }
      */
      }
      Axis server-config.wsdd
      Code:
        <service name="EmployeeServicePort" provider="java:RPC" style="document" use="literal">
        <parameter name="wsdlServicePort" value="EmployeeServicePort"/>
        <parameter name="schemaQualified" value="http://www.spring.com/RRT/Spring/EmployeeService"/>
        <parameter name="className" value="demo.spring.live.service.employee.impl.EmployeeServiceEndPoint"/>
        <parameter name="allowedMethods" value="*"/>
        <parameter name="typeMappingVersion" value="1.2"/>
        <parameter name="wsdlServiceElement" value="EmployeeService"/>
        <parameter name="wsdlTargetNamespace" value="http://www.spring.com/RRT/Spring/EmployeeService"/>
        <parameter name="wsdlPortType" value="EmployeePort"/>
        <parameter name="scope" value="Application"/>
        <parameter name="schemaUnqualified" value="http://www.spring.com/RRT/Spring/TO"/>
        <typeMapping deserializer="org.apache.axis.encoding.ser.BeanDeserializerFactory" encodingStyle="" qname="ns1:EmployeeImpl" serializer="org.apache.axis.encoding.ser.BeanSerializerFactory" type="java:demo.spring.live.domain.employee.impl.EmployeeImpl" xmlns:ns1="http://www.spring.com/RRT/Spring/TO"/>
       </service>
      I can reach the URL http://localhost:8080/rrtSpringLive/...rvicePort?WSDL ,

      I follow this post by a next one as it is becoming too long

      Comment


      • #4
        client-side config and results ...

        Now my client config is as such :
        Code:
        <beans>
            <bean id="testBeanFactory" class="org.springframework.context.support.ClassPathXmlApplicationContext">
                <constructor-arg>
                    <list>               <value>demo/spring/live/service/employee/impl/beanRef-jaxrpc.xml</value>
                     </list>
                </constructor-arg>
            </bean>
        </beans>
        where beanRef-jaxrpc.xml is set as :
        Code:
        <beans>
            <!--
                JAX-RPC wrapper uses default class="org.springframework.remoting.jaxrpc.JaxRpcPortProxyFactoryBean"    
            -->
            <bean id="rrt-employeeAxisWebServiceProxy"
                class="demo.spring.live.service.employee.impl.AxisPortProxyFactoryBean">
                <property name="serviceFactoryClass">
                    <value>org.apache.axis.client.ServiceFactory</value>
                </property>        
                <property name="serviceInterface">
                    <value>demo.spring.live.service.employee.RemoteEmployeeService</value>
                </property>
                <property name="wsdlDocumentUrl">
                    <value>file:///C:/eclipse/workspace/RRT_Spring_Live/ant/caller/EmployeeService.wsdl</value>
                </property>
                <property name="namespaceUri">
                    <value>http://www.spring.com/RRT/Spring/EmployeeService</value>
                </property>
                <property name="serviceName">
                    <value>EmployeeService</value>
                </property>
                <property name="portName">
                    <value>EmployeeServicePort</value>
                </property>
            </bean>
        Code:
        public class AxisPortProxyFactoryBean extends JaxRpcPortProxyFactoryBean {
            protected Log logger = LogFactory.getLog(AxisPortProxyFactoryBean.class.getName());
        
            protected void postProcessJaxRpcService(Service service) {
                logger.debug("postProcessJaxRpcService");
                TypeMappingRegistry registry = service.getTypeMappingRegistry();
                TypeMapping mapping = registry.createTypeMapping();
                registerBeanMapping(mapping, EmployeeImpl.class, "EmployeeImpl");
                registry.register("http://schemas.xmlsoap.org/soap/encoding/", mapping);
            }
        
            protected void registerBeanMapping(TypeMapping mapping, Class type, String name) {
                logger.debug("registerBeanMapping");
        
                QName serializerQName = new QName("http://www.sun.com/RRT/Spring/EmployeeService", name);
                //QName serializerQName = new QName("http://www.sun.com/RRT/Spring/TO", name);
                // QName qName = new QName("http://localhost:8080/rrtSpringLive/services/EmployeeService", name);
                mapping.register(type, serializerQName, new BeanSerializerFactory(type, serializerQName), new BeanDeserializerFactory(type, serializerQName));
                        
            }
        }
        The eclipse console shows I really did invoke AxisPortProxyFactoryBean
        Code:
        07/07/2006 16:03:45 DEBUG [main] demo.spring.live.service.employee.impl.AxisPortProxyFactoryBean.postProcessJaxRpcService(AxisPortProxyFactoryBean.java:45)  - postProcessJaxRpcService
        07/07/2006 16:03:45 DEBUG [main] demo.spring.live.service.employee.impl.AxisPortProxyFactoryBean.registerBeanMapping(AxisPortProxyFactoryBean.java:78)  - registerBeanMapping
        07/07/2006 16:03:45 INFO  [main] org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.prepare(JaxRpcPortClientInterceptor.java:325)  - Creating JAX-RPC proxy for JAX-RPC port [{http://www.spring.com/RRT/Spring/EmployeeService}EmployeeServicePort], using port interface [demo.spring.live.service.employee.RemoteEmployeeService]
        07/07/2006 16:03:45 INFO  [main] org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.prepare(JaxRpcPortClientInterceptor.java:333)  - Using service interface [demo.spring.live.service.employee.RemoteEmployeeService] for JAX-RPC port [{http://www.spring.com/RRT/Spring/EmployeeService}EmployeeServicePort] -  directly implemented
        07/07/2006 16:03:45 DEBUG [main] demo.spring.live.service.employee.impl.RemoteEmployeeServiceJaxRpcClientSpringTestCase.testCreateEmployee(RemoteEmployeeServiceJaxRpcClientSpringTestCase.java:120)  - testCreateEmployee
        07/07/2006 16:03:45 DEBUG [main] demo.spring.live.service.employee.impl.RemoteEmployeeServiceJaxRpcClient.createEmployee(RemoteEmployeeServiceJaxRpcClient.java:43)  - createEmployee
        07/07/2006 16:03:45 DEBUG [main] org.springframework.remoting.jaxrpc.JaxRpcPortClientInterceptor.invoke(JaxRpcPortClientInterceptor.java:495)  - Invoking operation 'createEmployee' on JAX-RPC port stub
        Tomcat console shows I have reached EmployeeServiceEndPoint.onInit but not not the expected method (createEmployee)

        JUnit stack trace error displays :
        java.lang.reflect.UndeclaredThrowableException
        ...
        Caused by: No such operation 'employee'

        Last point is the same as seen at http://forum.springframework.org/showthread.php?t=13335 , I had to set up the WSDL URL with file://, as an HTTP URL caused an error when I set the default generated EmployeeAxisBindingSkeleton in server-config.wsdd, now that server-config.wsdd is set with EmployeeServiceEndPoint, on the client-side I can set the WSDL URL with HTTP but got an error :
        Code:
        org.springframework.beans.factory.access.BootstrapException: Unable to initialize group definition. Group resource name [classpath*:demo/spring/live/service/employee/impl/beanRefFactory.xml], factory key [testBeanFactory]; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testBeanFactory' defined in URL [file:/C:/eclipse/workspace/RRT_Spring_Live/bin/demo/spring/live/service/employee/impl/beanRefFactory.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rrt-employeeAxisWebServiceProxy' defined in class path resource [demo/spring/live/service/employee/impl/beanRef-jaxrpc.xml]: Initialization of bean failed; nested exception is javax.xml.rpc.ServiceException: Error processing WSDL document:  
        java.io.IOException: Type {http://employee.domain.live.spring.demo}Employee is referenced but not defined.
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'testBeanFactory' defined in URL [file:/C:/eclipse/workspace/RRT_Spring_Live/bin/demo/spring/live/service/employee/impl/beanRefFactory.xml]: Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rrt-employeeAxisWebServiceProxy' defined in class path resource [demo/spring/live/service/employee/impl/beanRef-jaxrpc.xml]: Initialization of bean failed; nested exception is javax.xml.rpc.ServiceException: Error processing WSDL document:  
        java.io.IOException: Type {http://employee.domain.live.spring.demo}Employee is referenced but not defined.
        org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [org.springframework.context.support.ClassPathXmlApplicationContext]: Constructor threw exception; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rrt-employeeAxisWebServiceProxy' defined in class path resource [demo/spring/live/service/employee/impl/beanRef-jaxrpc.xml]: Initialization of bean failed; nested exception is javax.xml.rpc.ServiceException: Error processing WSDL document:  
        java.io.IOException: Type {http://employee.domain.live.spring.demo}Employee is referenced but not defined.
        org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rrt-employeeAxisWebServiceProxy' defined in class path resource [demo/spring/live/service/employee/impl/beanRef-jaxrpc.xml]: Initialization of bean failed; nested exception is javax.xml.rpc.ServiceException: Error processing WSDL document:  
        java.io.IOException: Type {http://employee.domain.live.spring.demo}Employee is referenced but not defined.
        javax.xml.rpc.ServiceException: Error processing WSDL document:  
        java.io.IOException: Type {http://employee.domain.live.spring.demo}Employee is referenced but not defined.
            at org.apache.axis.client.Service.initService(Service.java:250)
            at org.apache.axis.client.Service.<init>(Service.java:165)
        Tomcat server console displays :
        Code:
        07/07/2006 16:23:54 WARN  [http-8080-Processor25] org.apache.axis.wsdl.fromJava.Emitter.writePartToMessage(Emitter.java:1907)  - Please register a typemapping/b
        eanmapping for 'demo.spring.live.domain.employee.Employee'
        07/07/2006 16:23:54 WARN  [http-8080-Processor25] org.apache.axis.wsdl.fromJava.Types.isBeanCompatible(Types.java:1704)  - The class demo.spring.live.domain.employee.Employee does not contain a default constructor, which is a requirement for a bean class.  The class cannot be converted into an xml schema ty
        pe.  An xml schema anyType will be used to define this class in the wsdl file.
        07/07/2006 16:23:54 WARN  [http-8080-Processor25] org.apache.axis.wsdl.fromJava.Emitter.writePartToMessage(Emitter.java:1907)  - Please register a typemapping/b
        eanmapping for 'demo.spring.live.domain.employee.Employee'
        Any Gotcha else to know ?

        Many thanks

        Comment


        • #5
          The WSDL available through the server is not valid

          I attached the WSDL (see EmployeeServicePort.txt ) , which is not validated neither by XML Spy, neither by SOAP scope, as there is an "import namespace" which can not be resolved. This WSDL generated by Axis (or spring ?) looks quite different from the One I did use, again this issue seems to be related to the usage of interface when defining the input and the ouput of the methods in the SEI .

          Thanks for your feedback,

          Steve

          Comment

          Working...
          X