6 Replies Latest reply on Aug 5, 2005 12:15 AM by thomas.diesler

    JbossWS and polymorphism?

    dpocock

      The forum software messed up the tags, here is the example again:

      <ns1:getAgentOptionsResponse xmlns:ns1="http://www.uecommerce.com/telacct">
      < getAgentOptionsReturn>
      < agentId>10223< /agentId>
      < apso >
      < null xsi:nil="1"/>
      < callBackPw>xxxxx< /callBackPw>
      < instId>12345< /instId>

        • 1. Re: JbossWS and polymorphism?
          thomas.diesler

          The contract is defined by wsdl and schema, not by java. The way you should examine this, is:

          1) look at the wsdl to see what schema type is used for the return
          2) look at jaxrpc-mapping to see waht java type this maps to

          If that is the base type, then only the SOAP representation of the base type will be put on the wire and the client will get the base type regardless of whether you returned the sub type from your endpoint.

          If wsdl, schema and mapping use the sub type instead of the basetype, we have a bug need to create a jira issue for it.

          • 2. Re: JbossWS and polymorphism?
            dpocock

            The WSDL defines the return type as `AgentOptions', which is defined:

            < complexType name="AgentOptions">
            < sequence>
            < element name="agentId" type="xsd:int"/>
            < element name="apso" nillable="true" type="impl:AgentPaymentSchemeOptions"/>
            < element name="defaultTariff" type="xsd:int"/>
            < element name="logoURL" nillable="true" type="soapenc:string"/>
            < element name="profitAccount" type="xsd:int"/>
            < element name="tariffMargin" type="xsd:double"/>
            < /sequence>
            < /complexType>

            The `apso' element can contain an instance of either of the following two types, also defined in the WSDL (notice that the second type extends the first):


            < sequence>
            < element name="null" nillable="true" type="soapenc:string"/>
            < /sequence>
            < /complexType>

            < complexType name="WPPaymentSchemeOptions">
            < complexContent>
            < extension base="impl:AgentPaymentSchemeOptions">
            < sequence>
            < element name="callBackPw" nillable="true" type="soapenc:string"/>
            < element name="instId" type="xsd:int"/>
            < element name="md5Secret" nillable="true" type="soapenc:string"/>
            < element name="minimumPayment" type="xsd:int"/>
            < element name="pageFooter" nillable="true" type="soapenc:string"/>
            < element name="pageHeader" nillable="true" type="soapenc:string"/>
            < element name="paymentsAccount" type="xsd:int"/>
            < element name="siteCode" nillable="true" type="soapenc:string"/>
            < /sequence>
            < /extension>
            < /complexContent>
            < /complexType>

            • 3. Re: JbossWS and polymorphism?
              dpocock

              These are from the jaxrpc-mapping.xml file, both types appear to be mapped correctly. By the way, how do I make the forum display XML correctly?

              < java-xml-type-mapping>
              < java-type>com.uecommerce.telacct.ws.AgentPaymentSchemeOptions< /java-type>
              < root-type-qname xmlns:typeNS="http://www.uecommerce.com/telacct">typeNS:AgentPaymentSchemeOptions< /root-type-qname>
              < qname-scope>complexType< /qname-scope>


              < java-xml-type-mapping>
              < java-type>com.uecommerce.telacct.ws.WPPaymentSchemeOptions< /java-type>
              < root-type-qname xmlns:typeNS="http://www.uecommerce.com/telacct">typeNS:WPPaymentSchemeOptions< /root-type-qname>
              < qname-scope>complexType< /qname-scope>


              • 4. Re: JbossWS and polymorphism?
                thomas.diesler

                You can use the 'code' marker


                 <some-element>text</some-element>
                


                Please paste, your wsdl again and the other relevant parts again.

                • 5. Re: JbossWS and polymorphism?
                  keenan

                  I'm not the original author, but I'm having the same problem:

                  In responses generated by JBoss hosted web services, the returned document does not properly identify the derived type with an xsi:type attribute when the service is defined to return an instance of the super type.

                  Thomas, I've checked and included everything you asked the original poster for, and using your criteria, must conclude this is a JBoss bug.

                  Environment: JBoss 4.0.2, Windows XP, Doc-Literal, JWSDP 1.6, top-down development, one part per message

                  Below I give an example of the incorrect instance doc returned by JBoss, my WSDL, fragments of the type mapping, the SEI and the SEI implementation.

                   <?xml version="1.0" encoding="UTF-8"?>
                   <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                   <soapenv:Body>
                   <ns1:result xmlns:ns1="http://siterefresh.refreshsoftware.com/types">
                   <id>4FDB5C620016F617010582DF2C9A47A4</id>
                   </ns1:result>
                   </soapenv:Body>
                   </soapenv:Envelope>
                  


                  Notice that in the above, I would expect the ns1:result element to contain an attribute specifying xsi:type="ns1:assetCreateResult", especially since result is marked as abstract in the schema.

                  Here is the WSDL. Note that BOTH the input and output parameters to the operation are polymorphic types. Input is handled correctly, and the JWSDP generated stubs for the client correctly put the instance type on the input documents.

                  <definitions
                   targetNamespace="http://siterefresh.refreshsoftware.com/wsdl/services"
                   xmlns:tns="http://siterefresh.refreshsoftware.com/wsdl/services"
                   xmlns:srt="http://siterefresh.refreshsoftware.com/types"
                   xmlns="http://schemas.xmlsoap.org/wsdl/"
                   xmlns:soapbind="http://schemas.xmlsoap.org/wsdl/soap/"
                   name="SiteRefreshSoapServices">
                  
                   <types>
                   <schema
                   targetNamespace="http://siterefresh.refreshsoftware.com/types"
                   xmlns="http://www.w3.org/2001/XMLSchema"
                   xmlns:srt="http://siterefresh.refreshsoftware.com/types">
                  
                   <element name="event" type="srt:Event" />
                   <element name="eventException" type="srt:EventException" />
                   <element name="result" type="srt:Result" />
                  
                   <complexType name="Event" abstract="true">
                   <sequence>
                   <element name="id" type="string" minOccurs="0" />
                   </sequence>
                   </complexType>
                  
                   <complexType name="AssetRead">
                   <complexContent>
                   <extension base="srt:Event" />
                   </complexContent>
                   </complexType>
                  
                   <complexType name="AssetCreate">
                   <complexContent>
                   <extension base="srt:Event">
                   <sequence>
                   <element name="nextStep" type="int" />
                   <element name="template" type="string" />
                   </sequence>
                   </extension>
                   </complexContent>
                   </complexType>
                  
                   <complexType name="Result" abstract="true"></complexType>
                  
                   <complexType name="AssetCreateResult">
                   <complexContent>
                   <extension base="srt:Result">
                   <sequence>
                   <element name="id" type="string" />
                   </sequence>
                   </extension>
                   </complexContent>
                   </complexType>
                  
                   <complexType name="AssetReadResult">
                   <complexContent>
                   <extension base="srt:Result">
                   <sequence>
                   <element name="id" type="string" />
                   <element name="body" type="string" />
                   </sequence>
                   </extension>
                   </complexContent>
                   </complexType>
                  
                   <complexType name="EventException">
                   <sequence>
                   <element name="message" type="string" />
                   </sequence>
                   </complexType>
                  
                   </schema>
                   </types>
                  
                   <message name="processEventResponse">
                   <part name="processEventResponse" element="srt:result" />
                   </message>
                   <message name="processEventRequest">
                   <part name="processEventRequest" element="srt:event" />
                   </message>
                   <message name="processEventException">
                   <part name="processEventException" element="srt:eventException" />
                   </message>
                  
                   <portType name="ServiceFacadeEndpoint">
                   <operation name="processEvent">
                   <input message="tns:processEventRequest"
                   name="processEventRequest" />
                   <output message="tns:processEventResponse"
                   name="processEventResponse" />
                   <fault message="tns:processEventException"
                   name="processEventException" />
                   </operation>
                   </portType>
                  
                   <binding name="ServiceFacadeSoapBinding"
                   type="tns:ServiceFacadeEndpoint">
                   <soapbind:binding style="document"
                   transport="http://schemas.xmlsoap.org/soap/http" />
                  
                   <operation name="processEvent">
                   <soapbind:operation soapAction="" />
                   <input name="processEventRequest">
                   <soapbind:body use="literal" />
                   </input>
                   <output name="processEventResponse">
                   <soapbind:body use="literal" />
                   </output>
                   <fault name="processEventException">
                   <soapbind:fault name="processEventException"
                   use="literal" />
                   </fault>
                   </operation>
                   </binding>
                  
                   <service name="ServiceFacade">
                   <port binding="tns:ServiceFacadeSoapBinding"
                   name="ServiceFacadePort">
                   <soapbind:address location="http://dummy-location" />
                   </port>
                   </service>
                  
                  </definitions>
                  


                  Here is relevant parts of the type mapping:
                  <?xml version="1.0" encoding="UTF-8"?>
                  <java-wsdl-mapping xmlns="http://java.sun.com/xml/ns/j2ee"
                   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.1"
                   xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://www.ibm.com/webservices/xsd/j2ee_jaxrpc_mapping_1_1.xsd">
                   <package-mapping>
                   <package-type>
                   com.refreshsoftware.siterefresh.services.documents
                   </package-type>
                   <namespaceURI>
                   http://siterefresh.refreshsoftware.com/wsdl/services
                   </namespaceURI>
                   </package-mapping>
                   <package-mapping>
                   <package-type>
                   com.refreshsoftware.siterefresh.services.documents
                   </package-type>
                   <namespaceURI>
                   http://siterefresh.refreshsoftware.com/types
                   </namespaceURI>
                   </package-mapping>
                  
                   <java-xml-type-mapping>
                   <java-type>
                   com.refreshsoftware.siterefresh.services.documents.Event
                   </java-type>
                   <root-type-qname
                   xmlns:typeNS="http://siterefresh.refreshsoftware.com/types">
                   typeNS:Event
                   </root-type-qname>
                   <qname-scope>complexType</qname-scope>
                   <variable-mapping>
                   <java-variable-name>id</java-variable-name>
                   <xml-element-name>id</xml-element-name>
                   </variable-mapping>
                   </java-xml-type-mapping>
                  
                   <java-xml-type-mapping>
                   <java-type>
                   com.refreshsoftware.siterefresh.services.documents.AssetCreate
                   </java-type>
                   <root-type-qname
                   xmlns:typeNS="http://siterefresh.refreshsoftware.com/types">
                   typeNS:AssetCreate
                   </root-type-qname>
                   <qname-scope>complexType</qname-scope>
                   <variable-mapping>
                   <java-variable-name>nextStep</java-variable-name>
                   <xml-element-name>nextStep</xml-element-name>
                   </variable-mapping>
                   <variable-mapping>
                   <java-variable-name>template</java-variable-name>
                   <xml-element-name>template</xml-element-name>
                   </variable-mapping>
                   </java-xml-type-mapping>
                  
                   <java-xml-type-mapping>
                   <java-type>
                   com.refreshsoftware.siterefresh.services.documents.Result
                   </java-type>
                   <root-type-qname
                   xmlns:typeNS="http://siterefresh.refreshsoftware.com/types">
                   typeNS:Result
                   </root-type-qname>
                   <qname-scope>complexType</qname-scope>
                   </java-xml-type-mapping>
                  
                   <java-xml-type-mapping>
                   <java-type>
                   com.refreshsoftware.siterefresh.services.documents.AssetCreateResult
                   </java-type>
                   <root-type-qname
                   xmlns:typeNS="http://siterefresh.refreshsoftware.com/types">
                   typeNS:AssetCreateResult
                   </root-type-qname>
                   <qname-scope>complexType</qname-scope>
                   <variable-mapping>
                   <java-variable-name>id</java-variable-name>
                   <xml-element-name>id</xml-element-name>
                   </variable-mapping>
                   </java-xml-type-mapping>
                  
                   <java-xml-type-mapping>
                   <java-type>
                   com.refreshsoftware.siterefresh.services.documents.EventException_Exception
                   </java-type>
                   <root-type-qname
                   xmlns:typeNS="http://siterefresh.refreshsoftware.com/types">
                   typeNS:EventException
                   </root-type-qname>
                   <qname-scope>complexType</qname-scope>
                   <variable-mapping>
                   <java-variable-name>message</java-variable-name>
                   <xml-element-name>message</xml-element-name>
                   </variable-mapping>
                   </java-xml-type-mapping>
                   <exception-mapping>
                   <exception-type>
                   com.refreshsoftware.siterefresh.services.documents.EventException_Exception
                   </exception-type>
                   <wsdl-message
                   xmlns:exMsgNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   exMsgNS:processEventException
                   </wsdl-message>
                   <constructor-parameter-order>
                   <element-name>message</element-name>
                   </constructor-parameter-order>
                   </exception-mapping>
                  
                   <service-interface-mapping>
                   <service-interface>
                   com.refreshsoftware.siterefresh.services.documents.ServiceFacade
                   </service-interface>
                   <wsdl-service-name
                   xmlns:serviceNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   serviceNS:ServiceFacade
                   </wsdl-service-name>
                   <port-mapping>
                   <port-name>ServiceFacadePort</port-name>
                   <java-port-name>ServiceFacadePort</java-port-name>
                   </port-mapping>
                   </service-interface-mapping>
                  
                   <service-endpoint-interface-mapping>
                   <service-endpoint-interface>
                   com.refreshsoftware.siterefresh.services.documents.ServiceFacadeEndpoint
                   </service-endpoint-interface>
                   <wsdl-port-type
                   xmlns:portTypeNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   portTypeNS:ServiceFacadeEndpoint
                   </wsdl-port-type>
                   <wsdl-binding
                   xmlns:bindingNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   bindingNS:ServiceFacadeSoapBinding
                   </wsdl-binding>
                   <service-endpoint-method-mapping>
                   <java-method-name>processEvent</java-method-name>
                   <wsdl-operation>processEvent</wsdl-operation>
                   <method-param-parts-mapping>
                   <param-position>0</param-position>
                   <param-type>
                   com.refreshsoftware.siterefresh.services.documents.Event
                   </param-type>
                   <wsdl-message-mapping>
                   <wsdl-message
                   xmlns:wsdlMsgNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   wsdlMsgNS:processEventRequest
                   </wsdl-message>
                   <wsdl-message-part-name>
                   processEventRequest
                   </wsdl-message-part-name>
                   <parameter-mode>IN</parameter-mode>
                   </wsdl-message-mapping>
                   </method-param-parts-mapping>
                   <wsdl-return-value-mapping>
                   <method-return-value>
                   com.refreshsoftware.siterefresh.services.documents.Result
                   </method-return-value>
                   <wsdl-message
                   xmlns:wsdlMsgNS="http://siterefresh.refreshsoftware.com/wsdl/services">
                   wsdlMsgNS:processEventResponse
                   </wsdl-message>
                   <wsdl-message-part-name>
                   processEventResponse
                   </wsdl-message-part-name>
                   </wsdl-return-value-mapping>
                   </service-endpoint-method-mapping>
                   </service-endpoint-interface-mapping>
                  </java-wsdl-mapping>
                  


                  Now for the SEI:
                  public interface ServiceFacadeEndpoint extends Remote {
                   Result processEvent(Event event) throws EventException_Exception, java.rmi.RemoteException;
                  }
                  


                  And its implementation (by a stateless session bean):
                   public Result processEvent(Event event) throws EventException_Exception {
                  
                   Result res = null;
                  
                   log.info("got an event: " + event.getClass().getName());
                  
                   if (event instanceof AssetCreate) {
                   res = new AssetCreateResult();
                   ((AssetCreateResult)res).setId("123");
                   }
                  
                   return res;
                   }
                  


                  I'd appciate any workaround, a note saying it is fixed in 4.0.3 or the JbossWS early access release, or even just that a bug report has been filed. Thanks,
                  --keenan


                  • 6. Re: JbossWS and polymorphism?
                    thomas.diesler