Announcement Announcement Module
Collapse
No announcement yet.
XML Schema: complexContent/extension Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • XML Schema: complexContent/extension

    Hi!
    i want to define a base type (CasDataType) and then "subclass" it.
    I found the XML Schema element complexContent+extension which seems to fit for my needs.
    Please look at my XML Schema snippet.
    Code:
    <complexType name="CasDataType">
      <sequence>
        <element name="key"  type="long"  nillable="false  minOccurs="1" maxOccurs="1"/>
      </sequence>
    </complexType>
    
    <complexType name="AddressDataType">
      <complexContent>
        <extension base="tns:CasDataType">
          <sequence>
            <element name="FirstName"  nillable="true" minOccurs="0" type="string"/>
            <element name="LastName"  nillable="true" minOccurs="0" type="string"/>
          </sequence>
        </extension>
      </complexContent>
    </complexType>
    	
    <complexType name="ArrayOfCasDataTypes">
      <sequence>
        <element name="casDataTypes"  type="tns:CasDataType"	nillable="false" minOccurs="1" maxOccurs="unbounded"/>
      </sequence>
    </complexType>
    	
    <element name="createDataTypesRequest"  type="tns:ArrayOfCasDataTypes"/>
    	
    <element name="createDataTypesResponse" type="tns:ArrayOfCasDataTypes"/>
    I'm creating AddressDataType objects in my endpoint method invokeInternal(...) and want to returm this objects. But i get an validation error ant my soap message looks like this:
    Code:
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
      <SOAP-ENV:Header /> 
      <SOAP-ENV:Body>
      <createDataTypesResponse xmlns="http://springws.cas.de">
        <casDataTypes>
          <key>123</key> 
          <FirstName>Ingo</FirstName> 
          <LastName>Siebert</LastName> 
        </casDataTypes>
        <casDataTypes>
          <key>456</key> 
          <FirstName>Ingo</FirstName> 
          <LastName>Siebert</LastName> 
        </casDataTypes>
      </createDataTypesResponse>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    As we can see, i get casDataTypes and not AddressDataType. Why? I thought that "casDataTypes" is only the name of the array. Instead this is the element name of array elements.
    Has anyone an idea, how i can provide one method for several "subclassed" (with complexContent/extension) XML schema elements?

    Cheers,

    Ingo
    Last edited by res1st; Jun 9th, 2006, 07:23 AM.

  • #2
    Originally posted by res1st
    But i get an validation error ant my soap message looks like this:
    Code:
    <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
      <SOAP-ENV:Header /> 
      <SOAP-ENV:Body>
      <createDataTypesResponse xmlns="http://springws.cas.de">
        <casDataTypes>
          <key>123</key> 
          <FirstName>Ingo</FirstName> 
          <LastName>Siebert</LastName> 
        </casDataTypes>
        <casDataTypes>
          <key>456</key> 
          <FirstName>Ingo</FirstName> 
          <LastName>Siebert</LastName> 
        </casDataTypes>
      </createDataTypesResponse>
      </SOAP-ENV:Body>
    </SOAP-ENV:Envelope>
    As we can see, i get casDataTypes and not AddressDataType. Why?
    You get a validation error because the XML is not valid according to your schema . Don't you just love that PayloadValidatingInterceptor?

    What I would expect to see in the payload is this:

    Code:
    <createDataTypesResponse xmlns="http://springws.cas.de" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
        <casDataTypes xsi:type="AddressDataType" >
          <key>123</key> 
          <FirstName>Ingo</FirstName> 
          <LastName>Siebert</LastName> 
        </casDataTypes>
      </createDataTypesResponse>
    Note the xsi:type attribute. That tells the XML parser that the type is actually an address data type. If this attribute is added, the XML is valid.

    Originally posted by res1st
    I thought that "casDataTypes" is only the name of the array. Instead this is the element name of array elements.
    Try and look at this from an XML perspective, and let's forget about Java for a while. In ArrayOfCasDataTypes, you are defining a sequence (=list) of elements. Each element is called casDataType. It's that simple.

    Originally posted by res1st
    Has anyone an idea, how i can provide one method for several "subclassed" (with complexContent/extension) XML schema elements?
    The trick seems to be to add the xsi:type attribute I mentioned above, which is more a JAXB thing than anything else. This thread seems to be related to your problem, and you might also want to check out the type-substitution sample that comes with JWDSP 2.0's JAXB implementation.

    Cheers,

    Comment


    • #3
      Originally posted by poutsma
      The trick seems to be to add the xsi:type attribute I mentioned above, which is more a JAXB thing than anything else.
      So this means this is not interoperable with other clients than JAXB clients?

      Perhaps the xsi:type approach works with .NET or other Java Bindings, I have not tried yet..., but can we use this in the future?

      Currennlty I think there is no other way than to wrap the whole thing:
      e.g.
      Code:
      <complexType name="CasDataTypeWrapper">
         <choice>
      	<element name="AddressDataType" type="tns:AddressDataType" />
      	<element name="OtherExtendedCasDataType" type="tns:OtherExtendedCasDataType" />
         </choice>
      </complexType>
      
      <complexType name="ArrayOfCasDataTypes">
        <sequence>
          <element name="casDataTypes"  type="tns:CasDataTypeWrapper"	nillable="false" minOccurs="1" maxOccurs="unbounded"/>
        </sequence>
      </complexType>
      and then take the right out..., well seems not to look nice.

      Knows somebody another approach to be interoperable with Java and .NET or whatever clients. Have nothing found in the WS-I. What are your solutions to this?

      Cheers,
      Patrick

      Comment


      • #4
        Originally posted by fgt
        So this means this is not interoperable with other clients than JAXB clients?

        Perhaps the xsi:type approach works with .NET or other Java Bindings, I have not tried yet..., but can we use this in the future?
        The xsi:type is a completely valid XSD construct which is exactly designed for cases like these. It just explicitly sets the schema type for an element. In fact, .NET uses it in this situation too!

        What I meant with "more a JAXB thing than anything else" is that JAXB should be instructed to add this attribute. I'm not a complete JAXB expert, so I don't know how this can be accomplished, but a simple google search resulted in the resources I gave above. They seem related.

        Best,

        Comment


        • #5
          Don't you just love that PayloadValidatingInterceptor?
          Of course, it's really cute.

          Note the xsi:type attribute. That tells the XML parser that the type is actually an address data type.
          That sounds logical. Now i know my goal, only the way is unknown. If can't do it with jaxb, i'll try another one. It's just a bean exchange with SpringWS....i hope.

          The trick seems to be to add the xsi:type attribute I mentioned above, which is more a JAXB thing than anything else.
          I've posted my problem to java.net. If i get a good answer, i'll post it here.

          <complexType name="CasDataTypeWrapper">
          <choice>
          <element name="AddressDataType" type="tns:AddressDataType" />
          <element name="OtherExtendedCasDataType" type="tns:OtherExtendedCasDataType" />
          </choice>
          </complexType>
          Thank you Patrick! I tried it and i have now an AddressDataType element. The "type=AddressDataType" thing seems to be more correct, but your solution is much better than nothing. Thank you.

          Cheers,

          Ingo

          Comment


          • #6
            Jaxb 2.0

            Code:
            <createDataTypesResponse xmlns="http://springws.cas.de" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
                <casDataTypes xsi:type="AddressDataType" >
                  <key>123</key> 
                  <FirstName>Fritz</FirstName> 
                  <LastName>Meier</LastName> 
                </casDataTypes>
              </createDataTypesResponse>
            JAXB 1.6 doesn't handle that it right, it never produces the xsi:type attribute which i need.
            I switched back to JAXB 2.0 and it's working nearly fine. I got the following soap response:
            Code:
            <SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/">
              <SOAP-ENV:Header /> 
              <SOAP-ENV:Body>
                <ns2:createDataTypesResponse xmlns:ns2="http://springws.cas.de">
                  <ns2:casDataType 
                      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                      xsi:type="ns2:AddressDataType">
                    <ns2:key>123</ns2:key> 
                    <ns2:firstName>Fritz</ns2:firstName> 
                    <ns2:lastName>Meier</ns2:lastName> 
                  </ns2:casDataType>
                </ns2:createDataTypesResponse>
              </SOAP-ENV:Body>
            </SOAP-ENV:Envelope>
            The Problem is, that i get an validation error in my log file. Any idea why?
            Code:
            DEBUG webservice.CreateDataTypesRequestEndpoint  - Unmarshalled payload request to [javax.xml.bind.JAXBElement@13ed2e3]
            DEBUG webservice.CreateDataTypesRequestEndpoint  - Marshalling [javax.xml.bind.JAXBElement@1873ad9] to response payload
            ERROR endpoint.PayloadValidatingInterceptor  - XML validation error on response: UndeclaredPrefix: Cannot resolve 'ns2:AddressDataType' as a QName: the prefix 'ns2' is not declared.
            ERROR endpoint.PayloadValidatingInterceptor  - XML validation error on response: cvc-elt.4.1: The value 'ns2:AddressDataType' of attribute 'http://www.w3.org/2001/XMLSchema-instance,type' of element 'ns2:casDataType' is not a valid QName.
            ERROR endpoint.PayloadValidatingInterceptor  - XML validation error on response: UndeclaredPrefix: Cannot resolve 'ns2:AddressDataType' as a QName: the prefix 'ns2' is not declared.
            ERROR endpoint.PayloadValidatingInterceptor  - XML validation error on response: cvc-attribute.3: The value 'ns2:AddressDataType' of attribute 'xsi:type' on element 'ns2:casDataType' is not valid with respect to its type, 'QName'.
            ERROR endpoint.PayloadValidatingInterceptor  - XML validation error on response: cvc-complex-type.2.4.d: Invalid content was found starting with element 'ns2:firstName'. No child element is expected at this point.
            Cheers,

            Ingo

            Comment


            • #7
              Originally posted by res1st
              The Problem is, that i get an validation error in my log file. Any idea why?
              Hmm, that's weird. It seems the validator cannot resolve the ns2 namespace, even though it's there. Just for an experiment, can you copy the payload of your message to a separate file, and use the standard javax.xml.validation api to validate? Something along the lines of:

              Code:
              SchemaFactory factory = SchemaFactory.newInstance(XMLConstants. W3C_XML_SCHEMA_NS_URI);
              Schema schema = factory.newSchema(new File("schema.xsd");
              Validator validator = schema.newValidator();
              validator.validate(new StreamSource(new File("payload.xml"));
              If that doesn't give errors, it's a bug. If that also gives errors, it is consistent (though wrong). Upgrading to a newer XML parser (such as Xerces 2.8.0) might help.

              Keep me informed,

              Comment


              • #8
                confused

                Code:
                SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                Schema schema = factory.newSchema(new File("echo.xsd"));
                Validator validator = schema.newValidator();
                validator.validate(new StreamSource(new File("payload.xml")));
                Here i'm validating against my echo.xsd from my web service. The response is:
                Code:
                org.xml.sax.SAXParseException: cvc-elt.1: Cannot find the declaration of element 'SOAP-ENV:Envelope'.
                	at com.sun.org.apache.xerces.internal.jaxp.validation.Util.toSAXParseException(Unknown Source)
                I can understand that in that way, that i define my message types but i doesn't define the soap envelop. That's why he doesn't know the "Envelope" tag.

                If i use the soap envelope schema(not my echo.xsd), it's not working.
                The response is:
                Code:
                org.xml.sax.SAXParseException: cvc-elt.4.2: Cannot resolve 'ns2:
                AddressDataType' to a type definition for element 'ns2:casDataType'.
                	at com.sun.org.apache.xerces.internal.jaxp.validation.Util.toSAXParseException(Unknown Source)
                Ok, that's also clear. The soap-envelope schema doesn't contain my message types.

                But if i use that tool (https://msv.dev.java.net) to validate against the soap envelope schema, it's says that my document is valid.

                And if i use that tool to validate my payload against my echo.xsd schema, i get this response(not valid):
                Code:
                Error at line:3, column:61 of file:///C:/download/msv-20060319/payload.xml
                  tag name "SOAP-ENV:Envelope" is not allowed. Possible tag names are:
                <createDataTypesRequest>,<createDataTypesResponse>,<echoRequest>,
                <echoResponse>,<secureEchoRequest>,<secureEchoResponse>
                the document is NOT valid.
                I'm somehow confused now...any idea what's wrong?

                Upgrading to a newer XML parser (such as Xerces 2.8.0) might help.
                I haven't added a parser, so i think i'm using the build in parser of java5. How can i switch to the xerces-j 2.8 parser?

                Cheers,

                Ingo

                Comment


                • #9
                  What I meant was just put the payload in a separate payload.xml file, just for test purposes. The file should contain something like:

                  Code:
                  <ns2:createDataTypesResponse xmlns:ns2="http://springws.cas.de">
                        <ns2:casDataType 
                            xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
                            xsi:type="ns2:AddressDataType">
                          <ns2:key>123</ns2:key> 
                          <ns2:firstName>Fritz</ns2:firstName> 
                          <ns2:lastName>Meier</ns2:lastName> 
                        </ns2:casDataType>
                      </ns2:createDataTypesResponse>
                  Then use the snipped I gave in the previous post to validate that:

                  Code:
                  SchemaFactory factory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
                  Schema schema = factory.newSchema(new File("echo.xsd"));
                  Validator validator = schema.newValidator();
                  validator.validate(new StreamSource(new File("payload.xml")));
                  And see if that works.

                  Comment


                  • #10
                    Ok sorry.
                    It works, no exception. It's a bug then.

                    Ingo

                    Comment


                    • #11
                      If it does work if you put it a separate file, it's probably a bug in SWS. Could you file one at the JIRA?

                      Thanks,

                      Comment


                      • #12
                        So is it a bug? Is there a solution to get validator working with abstract schema types?

                        I'm facing the same problem (http://forum.springframework.org/showthread.php?t=42668)

                        Comment


                        • #13
                          Hi Exgorth.

                          Yes, it's a bug of the Java validator. I thought they will automatically update to a new xerces version which would solve the problem (i hope).

                          Arjen described a workaroud in my JIRA report and i use it until now...

                          Cheers,

                          Ingo

                          Comment


                          • #14
                            I've set the system property:
                            Code:
                            <plugin>
                              <groupId>org.mortbay.jetty</groupId>
                              <artifactId>maven-jetty-plugin</artifactId>
                              <configuration>
                                <systemProperties>
                                  <systemProperty>
                                    <name>javax.xml.validation.SchemaFactory</name>
                                    <value>org.apache.xerces.jaxp.validation.XMLSchemaFactory</value>
                                  </systemProperty>
                                </systemProperties>
                              </configuration>
                            </plugin>
                            and i'm still getting the same errors
                            Code:
                            XML validation error on request: UndeclaredPrefix: Cannot resolve 'sch:Flight' as a QName: the prefix 'sch' is not declared.
                            XML validation error on request: cvc-elt.4.1: The value 'sch:Flight' of attribute 'http://www.w3.org/2001/XMLSchema-instance,type' of element 'sch:details' is not a valid QName.
                            XML validation error on request: cvc-type.2: The type definition cannot be abstract for element sch:details.
                            XML validation error on request: UndeclaredPrefix: Cannot resolve 'sch:Flight' as a QName: the prefix 'sch' is not declared.
                            XML validation error on request: cvc-attribute.3: The value 'sch:Flight' of attribute 'xsi:type' on element 'sch:details' is not valid with respect to its type, 'QName'.
                            My schema is differs from listed in SWS-35
                            in attributeFormDefault="unqualified" instead of attributeFormDefault="qualified"

                            So why the workaround doesn't works for me?

                            Comment


                            • #15
                              I've set the system property:
                              I hope you also have a version of the original apache-xerces in your classpath? The property alone isn't enough. As far as i know, if the class of the property isn't fount, then Java falls back to the buggy version.

                              Comment

                              Working...
                              X