You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@cxf.apache.org by Chris McClelland <ap...@m3.ath.cx> on 2009/02/16 23:14:36 UTC

@XmlSchema(location=...)

Hi,

Someone pointed out to me today that the JAXB xjc/schemaGen transformations are lossy. Imagine a CXF JAXWS service written code-first, but using types generated from a schema that has an element M defined as a choice of two other elements A and B. That service will accept <M><A/><B/></M> and <M/> without error, even if it has validation enabled.

<!-- foo.xsd -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
           attributeFormDefault="unqualified"
           elementFormDefault="qualified"
           targetNamespace="http://foo.com">
  <xs:element name="M">
    <xs:complexType>
      <xs:choice>
        <xs:element name="C" type="xs:string"/>
        <xs:element name="D" type="xs:string"/>
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

<!-- HelloWorldImpl.java -->
package demo.hw.server;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;
import javax.jws.soap.SOAPBinding;
import gen.M;
@WebService(targetNamespace = HelloWorldImpl.NS_URI)
@SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
public class HelloWorldImpl {
    public static final String NS_URI = "http://foo.com";
    @WebMethod(operationName = "M")
    public String processM(@WebParam(targetNamespace = NS_URI, name = "M") M m) {
        return "X";
    }
}

I guess this is because the runtime does not have access to the source XSD. It only has access to the JAXB annotations on the M class, which merely say that A and B may be omitted (i.e, you cannot say "either A or B but not both must be present" using JAXB annotations). Thus, the set of validation rules implemented by JAXB/CXF is only a subset of the validation rules specified in the source XSD.

But on closer inspection I discovered the 'location' attribute on the @XmlSchema annotation in package-info.java. This specifies the location of the original XSD. Unfortunately if I specify it in my package-info.java, the service generates WSDL that does not include any useful information about the schema:

<wsdl:types>
  <xsd:schema attributeFormDefault="unqualified"
              elementFormDefault="qualified"
              targetNamespace="http://foo.com"
              xmlns:tns="http://foo.com"
              xmlns:xsd="http://www.w3.org/2001/XMLSchema">
    <xsd:element name="M" nillable="true" />
    <xsd:element name="MResponse" nillable="true" type="xsd:string" />
  </xsd:schema>
</wsdl:types>

So...is it possible to get CXF to honour the 'location' attribute on @XmlSchema? Ideally it should consider it when returning the service's WSDL, but also consider it when validating incoming messages.

- Chris


Re: @XmlSchema(location=...)

Posted by Benson Margulies <bi...@gmail.com>.
The validation code could in theory impose the schema as you ask, yes.
Care to make a patch?

On Mon, Feb 16, 2009 at 5:14 PM, Chris McClelland <ap...@m3.ath.cx> wrote:
> Hi,
>
> Someone pointed out to me today that the JAXB xjc/schemaGen transformations
> are lossy. Imagine a CXF JAXWS service written code-first, but using types
> generated from a schema that has an element M defined as a choice of two
> other elements A and B. That service will accept <M><A/><B/></M> and <M/>
> without error, even if it has validation enabled.
>
> <!-- foo.xsd -->
> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>          attributeFormDefault="unqualified"
>          elementFormDefault="qualified"
>          targetNamespace="http://foo.com">
>  <xs:element name="M">
>   <xs:complexType>
>     <xs:choice>
>       <xs:element name="C" type="xs:string"/>
>       <xs:element name="D" type="xs:string"/>
>     </xs:choice>
>   </xs:complexType>
>  </xs:element>
> </xs:schema>
>
> <!-- HelloWorldImpl.java -->
> package demo.hw.server;
> import javax.jws.WebMethod;
> import javax.jws.WebParam;
> import javax.jws.WebService;
> import javax.jws.soap.SOAPBinding;
> import gen.M;
> @WebService(targetNamespace = HelloWorldImpl.NS_URI)
> @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
> public class HelloWorldImpl {
>   public static final String NS_URI = "http://foo.com";
>   @WebMethod(operationName = "M")
>   public String processM(@WebParam(targetNamespace = NS_URI, name = "M") M
> m) {
>       return "X";
>   }
> }
>
> I guess this is because the runtime does not have access to the source XSD.
> It only has access to the JAXB annotations on the M class, which merely say
> that A and B may be omitted (i.e, you cannot say "either A or B but not both
> must be present" using JAXB annotations). Thus, the set of validation rules
> implemented by JAXB/CXF is only a subset of the validation rules specified
> in the source XSD.
>
> But on closer inspection I discovered the 'location' attribute on the
> @XmlSchema annotation in package-info.java. This specifies the location of
> the original XSD. Unfortunately if I specify it in my package-info.java, the
> service generates WSDL that does not include any useful information about
> the schema:
>
> <wsdl:types>
>  <xsd:schema attributeFormDefault="unqualified"
>             elementFormDefault="qualified"
>             targetNamespace="http://foo.com"
>             xmlns:tns="http://foo.com"
>             xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>   <xsd:element name="M" nillable="true" />
>   <xsd:element name="MResponse" nillable="true" type="xsd:string" />
>  </xsd:schema>
> </wsdl:types>
>
> So...is it possible to get CXF to honour the 'location' attribute on
> @XmlSchema? Ideally it should consider it when returning the service's WSDL,
> but also consider it when validating incoming messages.
>
> - Chris
>
>

Re: @XmlSchema(location=...)

Posted by Benson Margulies <bi...@gmail.com>.
Dan is too polite, or lazy, to write,

"Benson was completely confused to suggest that the current behavior
is intended. The behavior you asked for is intended."

But please be sure to read that into his reply.

On Tue, Feb 17, 2009 at 10:50 AM, Daniel Kulp <dk...@apache.org> wrote:
>
> Definitely log a bug for this (and provide a test case if possible).
>
> If you would like to start digging into it, I can point out some places to
> start your investigation:
>
> JAXBDataBinding - in the generateJaxbSchemas() method, put a breakpoint or
> println or something in the createOutput() method of the SchemaOutputResolver
> to see if JAXB is even trying to output anything for those schemas.
>
> If JAXB is NOT trying to output anything, then we'll need to loop through the
> packages in the context list and check for the @XmlSchema package level
> annotations ourselves and pull them in.    Not a big deal.    The
> contextClasses set contains all the classes, just loop through them looking
> for package-infos with the annotation.
>
>
> If JAXB IS calling the createOutput() method for those, then we're most likely
> stripping off a schemaLocation attribute in the addSchemaDocument(..) of the
> superclass (AbstractDataBinding).    That will be a bit trickier to workaround
> as most of the time, we do want that stipped off for generated schema (so it's
> properly inlined in the wsdl).     Before going down this route, it would be
> good to see the results of the first check above.
>
> Thanks!
> Dan
>
>
>
> On Mon February 16 2009 5:14:36 pm Chris McClelland wrote:
>> Hi,
>>
>> Someone pointed out to me today that the JAXB xjc/schemaGen transformations
>> are lossy. Imagine a CXF JAXWS service written code-first, but using types
>> generated from a schema that has an element M defined as a choice of two
>> other elements A and B. That service will accept <M><A/><B/></M> and <M/>
>> without error, even if it has validation enabled.
>>
>> <!-- foo.xsd -->
>> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>>            attributeFormDefault="unqualified"
>>            elementFormDefault="qualified"
>>            targetNamespace="http://foo.com">
>>   <xs:element name="M">
>>     <xs:complexType>
>>       <xs:choice>
>>         <xs:element name="C" type="xs:string"/>
>>         <xs:element name="D" type="xs:string"/>
>>       </xs:choice>
>>     </xs:complexType>
>>   </xs:element>
>> </xs:schema>
>>
>> <!-- HelloWorldImpl.java -->
>> package demo.hw.server;
>> import javax.jws.WebMethod;
>> import javax.jws.WebParam;
>> import javax.jws.WebService;
>> import javax.jws.soap.SOAPBinding;
>> import gen.M;
>> @WebService(targetNamespace = HelloWorldImpl.NS_URI)
>> @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
>> public class HelloWorldImpl {
>>     public static final String NS_URI = "http://foo.com";
>>     @WebMethod(operationName = "M")
>>     public String processM(@WebParam(targetNamespace = NS_URI, name = "M")
>> M m) { return "X";
>>     }
>> }
>>
>> I guess this is because the runtime does not have access to the source XSD.
>> It only has access to the JAXB annotations on the M class, which merely say
>> that A and B may be omitted (i.e, you cannot say "either A or B but not
>> both must be present" using JAXB annotations). Thus, the set of validation
>> rules implemented by JAXB/CXF is only a subset of the validation rules
>> specified in the source XSD.
>>
>> But on closer inspection I discovered the 'location' attribute on the
>> @XmlSchema annotation in package-info.java. This specifies the location of
>> the original XSD. Unfortunately if I specify it in my package-info.java,
>> the service generates WSDL that does not include any useful information
>> about the schema:
>>
>> <wsdl:types>
>>   <xsd:schema attributeFormDefault="unqualified"
>>               elementFormDefault="qualified"
>>               targetNamespace="http://foo.com"
>>               xmlns:tns="http://foo.com"
>>               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>>     <xsd:element name="M" nillable="true" />
>>     <xsd:element name="MResponse" nillable="true" type="xsd:string" />
>>   </xsd:schema>
>> </wsdl:types>
>>
>> So...is it possible to get CXF to honour the 'location' attribute on
>> @XmlSchema? Ideally it should consider it when returning the service's
>> WSDL, but also consider it when validating incoming messages.
>>
>> - Chris
>
> --
> Daniel Kulp
> dkulp@apache.org
> http://www.dankulp.com/blog
>

Re: @XmlSchema(location=...)

Posted by Daniel Kulp <dk...@apache.org>.
Definitely log a bug for this (and provide a test case if possible).

If you would like to start digging into it, I can point out some places to 
start your investigation:

JAXBDataBinding - in the generateJaxbSchemas() method, put a breakpoint or 
println or something in the createOutput() method of the SchemaOutputResolver 
to see if JAXB is even trying to output anything for those schemas. 

If JAXB is NOT trying to output anything, then we'll need to loop through the 
packages in the context list and check for the @XmlSchema package level 
annotations ourselves and pull them in.    Not a big deal.    The 
contextClasses set contains all the classes, just loop through them looking 
for package-infos with the annotation.  


If JAXB IS calling the createOutput() method for those, then we're most likely 
stripping off a schemaLocation attribute in the addSchemaDocument(..) of the 
superclass (AbstractDataBinding).    That will be a bit trickier to workaround 
as most of the time, we do want that stipped off for generated schema (so it's 
properly inlined in the wsdl).     Before going down this route, it would be 
good to see the results of the first check above.

Thanks!
Dan



On Mon February 16 2009 5:14:36 pm Chris McClelland wrote:
> Hi,
>
> Someone pointed out to me today that the JAXB xjc/schemaGen transformations
> are lossy. Imagine a CXF JAXWS service written code-first, but using types
> generated from a schema that has an element M defined as a choice of two
> other elements A and B. That service will accept <M><A/><B/></M> and <M/>
> without error, even if it has validation enabled.
>
> <!-- foo.xsd -->
> <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
>            attributeFormDefault="unqualified"
>            elementFormDefault="qualified"
>            targetNamespace="http://foo.com">
>   <xs:element name="M">
>     <xs:complexType>
>       <xs:choice>
>         <xs:element name="C" type="xs:string"/>
>         <xs:element name="D" type="xs:string"/>
>       </xs:choice>
>     </xs:complexType>
>   </xs:element>
> </xs:schema>
>
> <!-- HelloWorldImpl.java -->
> package demo.hw.server;
> import javax.jws.WebMethod;
> import javax.jws.WebParam;
> import javax.jws.WebService;
> import javax.jws.soap.SOAPBinding;
> import gen.M;
> @WebService(targetNamespace = HelloWorldImpl.NS_URI)
> @SOAPBinding(parameterStyle = SOAPBinding.ParameterStyle.BARE)
> public class HelloWorldImpl {
>     public static final String NS_URI = "http://foo.com";
>     @WebMethod(operationName = "M")
>     public String processM(@WebParam(targetNamespace = NS_URI, name = "M")
> M m) { return "X";
>     }
> }
>
> I guess this is because the runtime does not have access to the source XSD.
> It only has access to the JAXB annotations on the M class, which merely say
> that A and B may be omitted (i.e, you cannot say "either A or B but not
> both must be present" using JAXB annotations). Thus, the set of validation
> rules implemented by JAXB/CXF is only a subset of the validation rules
> specified in the source XSD.
>
> But on closer inspection I discovered the 'location' attribute on the
> @XmlSchema annotation in package-info.java. This specifies the location of
> the original XSD. Unfortunately if I specify it in my package-info.java,
> the service generates WSDL that does not include any useful information
> about the schema:
>
> <wsdl:types>
>   <xsd:schema attributeFormDefault="unqualified"
>               elementFormDefault="qualified"
>               targetNamespace="http://foo.com"
>               xmlns:tns="http://foo.com"
>               xmlns:xsd="http://www.w3.org/2001/XMLSchema">
>     <xsd:element name="M" nillable="true" />
>     <xsd:element name="MResponse" nillable="true" type="xsd:string" />
>   </xsd:schema>
> </wsdl:types>
>
> So...is it possible to get CXF to honour the 'location' attribute on
> @XmlSchema? Ideally it should consider it when returning the service's
> WSDL, but also consider it when validating incoming messages.
>
> - Chris

-- 
Daniel Kulp
dkulp@apache.org
http://www.dankulp.com/blog