You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tuscany.apache.org by Simon Laws <si...@googlemail.com> on 2009/09/24 14:34:32 UTC

[1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

I'm looking at WSDL generated by Tuscany.  For a simple interface such as..

package service;

import org.osoa.sca.annotations.Service;

@Service(SomeService.class)
public class SomeServiceImpl implements SomeService {

    public AnObject getUsingString(String stringParam) {
        System.out.println("Param value:" + stringParam);

        return getAnObject(stringParam);
    }

    private AnObject getAnObject(String stringParam) {
        return new AnObject(stringParam + "123", 123);
    }

    public AnObject getUsingMoreComplexObject(MoreComplexObject
moreComplexParam) {
        System.out.println("Param value:" + moreComplexParam.getStringParam());

        return getAnObject(moreComplexParam.getStringParam());
    }

}

Tuscany generates the WSDL types...

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="SomeServiceService"
	targetNamespace="http://service/" xmlns:tns="http://service/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:SOAP11="http://schemas.xmlsoap.org/wsdl/soap/">
	<wsdl:types>
		<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
			<xs:complexType name="anObject">
				<xs:sequence>
					<xs:element minOccurs="0" name="someOtherRetValue" type="xs:int" />
					<xs:element minOccurs="0" name="someRetValue" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="moreComplexObject">
				<xs:sequence>
					<xs:element minOccurs="0" name="intParam" type="xs:int" />
					<xs:element minOccurs="0" name="stringParam" type="xs:string" />
					<xs:element minOccurs="0" name="stringParam2" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
		</xs:schema>
		<xs:schema attributeFormDefault="qualified"
			elementFormDefault="unqualified" targetNamespace="http://service/"
			xmlns:xs="http://www.w3.org/2001/XMLSchema">
			<xs:import />
			<xs:element name="getUsingString">
				<xs:complexType>
					<xs:sequence>
						<xs:element minOccurs="0" name="arg0" nillable="true"
							type="xs:string" />
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="getUsingMoreComplexObjectResponse">
				<xs:complexType>
					<xs:sequence>
						<xs:element minOccurs="0" name="return" nillable="true"
							type="anObject" />
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="getUsingMoreComplexObject">
				<xs:complexType>
					<xs:sequence>
						<xs:element minOccurs="0" name="arg0" nillable="true"
							type="moreComplexObject" />
					</xs:sequence>
				</xs:complexType>
			</xs:element>
			<xs:element name="getUsingStringResponse">
				<xs:complexType>
					<xs:sequence>
						<xs:element minOccurs="0" name="return" nillable="true"
							type="anObject" />
					</xs:sequence>
				</xs:complexType>
			</xs:element>
		</xs:schema>
	</wsdl:types>


However the wsgen JAXWS tooling generates the following schema for the WSDL...

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" targetNamespace="http://service/"
xmlns:tns="http://service/"
xmlns:xs="http://www.w3.org/2001/XMLSchema">

  <xs:element name="getUsingMoreComplexObject"
type="tns:getUsingMoreComplexObject"/>

  <xs:element name="getUsingMoreComplexObjectResponse"
type="tns:getUsingMoreComplexObjectResponse"/>

  <xs:element name="getUsingString" type="tns:getUsingString"/>

  <xs:element name="getUsingStringResponse" type="tns:getUsingStringResponse"/>

  <xs:complexType name="getUsingMoreComplexObject">
    <xs:sequence>
      <xs:element name="arg0" type="tns:moreComplexObject" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="moreComplexObject">
    <xs:sequence>
      <xs:element name="intParam" type="xs:int" minOccurs="0"/>
      <xs:element name="stringParam" type="xs:string" minOccurs="0"/>
      <xs:element name="stringParam2" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="getUsingMoreComplexObjectResponse">
    <xs:sequence>
      <xs:element name="return" type="tns:anObject" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="anObject">
    <xs:sequence>
      <xs:element name="someOtherRetValue" type="xs:int" minOccurs="0"/>
      <xs:element name="someRetValue" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="getUsingString">
    <xs:sequence>
      <xs:element name="arg0" type="xs:string" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>

  <xs:complexType name="getUsingStringResponse">
    <xs:sequence>
      <xs:element name="return" type="tns:anObject" minOccurs="0"/>
    </xs:sequence>
  </xs:complexType>
</xs:schema>

Note that difference is that the schema types anObject and
moreComplexObject  are generated into a namespace for wsgen and not
for Tuscany.

Now looking back at various related specs...

WS-I [1] says...

R2105 All xsd:schema elements contained in a wsdl:types element of a
DESCRIPTION MUST have a targetNamespace attribute with a valid and
non-null value, UNLESS the xsd:schema element has xsd:import and/or
xsd:annotation as its only child element(s)

And JAX-WS 2.1 I believe is intended to be WS-I compliant.

The wrinkle then seems to be that the JAXB spec defines a default Java
to XSD mapping where types are not placed in a namespace unless you
configure the Java class with annotations. The spec does talk of
"customizations" and I guess this is what the wsgen tool is doing but
I can't find any explicit statement about what these customizations
might be other than those provided by code annotations. This page [3]
suggests that it's sneaking behind the public JAXB API to make this
happen.

I found that the subject of the JAXB mapping had been discussed
before, e.g. [2], and I do remember testing that the no namespace
schema inclusion was actually valid. However I can't put my finger on
anything to do with customizing the mapping that has been discussed
here and why we aren't doing it.

Anyone know how to get JAXB to generate schema that are WS-I compliant
in this case?

I note that Axis have witten their own generator but I remember a long
time ago we used the Axis code and the stopped using it in favour of
the JAXB code for some reason. Anyone remember why (am searching the
ML also of course).

Regards

Simon

[1] http://www.ws-i.org/Profiles/BasicProfile-1_2%28WGAD%29.html#WSDLTYPES
[2] https://issues.apache.org/jira/browse/TUSCANY-2531
[3] https://jaxb.dev.java.net/guide/Invoking_schemagen_programatically.html

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Ok, a bit more success now following the various exchanges.

I made two changes to Interface2WSDLGenerator.

1/ I flipped a flag to run the JAXB schema generated against the
wrappers instead of just against the wrapped types
2/ I wrote some code to merge the resulting DOMs if there is a no namespace.

I'm extending the itest/wsdlgen scenario with a helloworld service
that references types as follows

src/main/java
   helloworld/
       ABean.java - a plain POJO
       HelloworldService.java - WSDL will be in namspace ""http://helloworld/"
      pacakge-info.java - force ABean into namespace "http://test"
   anotherpackage
       BBean.java - a plain POJO
       CBean.java - has @XmlType(name="")

This now gives rise to

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="HelloWorldServiceService"
	targetNamespace="http://helloworld/" xmlns:tns="http://helloworld/"
	xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
	xmlns:SOAP="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:SOAP11="http://schemas.xmlsoap.org/wsdl/soap/">
	<wsdl:types>
		<xs:schema targetNamespace="http://helloworld/" version="1.0"
			xmlns:ns1="http://test" xmlns:tns="http://helloworld/"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
			<xs:import namespace="http://test" />
			<xs:import namespace="http://helloworld/" />
			<xs:element name="getGreetings" type="tns:getGreetings" />
			<xs:element name="getGreetingsBBean" type="tns:getGreetingsBBean" />
			<xs:element name="getGreetingsBBeanResponse"
type="tns:getGreetingsBBeanResponse" />
			<xs:element name="getGreetingsBean" type="tns:getGreetingsBean" />
			<xs:element name="getGreetingsBeanArray" type="tns:getGreetingsBeanArray" />
			<xs:element name="getGreetingsBeanArrayResponse"
type="tns:getGreetingsBeanArrayResponse" />
			<xs:element name="getGreetingsBeanResponse"
type="tns:getGreetingsBeanResponse" />
			<xs:element name="getGreetingsCBean" type="tns:getGreetingsCBean" />
			<xs:element name="getGreetingsCBeanResponse"
type="tns:getGreetingsCBeanResponse" />

			<xs:element name="getGreetingsResponse" type="tns:getGreetingsResponse" />
			<xs:complexType name="getGreetingsBeanArrayResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsBeanArray">
				<xs:sequence>
					<xs:element maxOccurs="unbounded" minOccurs="0" name="arg0"
						nillable="true" type="ns1:aBean" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsBean">
				<xs:sequence>
					<xs:element minOccurs="0" name="arg0" type="ns1:aBean" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsCBean">
				<xs:sequence>
					<xs:element minOccurs="0" name="arg0">
						<xs:complexType>
							<xs:sequence>
								<xs:element minOccurs="0" name="field1" type="xs:string" />
								<xs:element minOccurs="0" name="field2" type="xs:string" />
							</xs:sequence>
						</xs:complexType>
					</xs:element>
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsBBeanResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsBeanResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetings">
				<xs:sequence>
					<xs:element minOccurs="0" name="arg0" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsCBeanResponse">
				<xs:sequence>
					<xs:element minOccurs="0" name="return" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
			<xs:complexType name="getGreetingsBBean">
				<xs:sequence>
					<xs:element minOccurs="0" name="arg0" type="bBean" />
				</xs:sequence>
			</xs:complexType>

			<xs:complexType name="bBean">
				<xs:sequence>
					<xs:element minOccurs="0" name="field1" type="xs:string" />
					<xs:element minOccurs="0" name="field2" type="xs:string" />
				</xs:sequence>
			</xs:complexType>
		</xs:schema>
		<xs:schema targetNamespace="http://test" version="1.0"
			xmlns:xs="http://www.w3.org/2001/XMLSchema">
			<xs:complexType name="aBean">
				<xs:sequence>
					<xs:element minOccurs="0" name="field1" type="xs:string" />
					<xs:element minOccurs="0" name="field2" type="xs:string" />
				</xs:sequence>
			</xs:complexType>

		</xs:schema>

Still more work to do to update any reference from the merged schema
that occur from anything but the default schema but at least i can see
the light.

Regards

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
On Mon, Sep 28, 2009 at 4:14 PM, Simon Nash <na...@apache.org> wrote:
> Simon Laws wrote:
>>
>> Well same here. I think we have to get pretty close to where the DOMs
>> are generated by JAXB and before the DOMs start getting parsed by
>> Tuscany.
>>
>> Simon
>>
> Please take a look at my fix for TUSCANY-3267 (r813785).  For this fix
> I inserted code into Interface2WSDLGenerator to modify the schema at
> the point where JAXB has generated the DOM but before it is loaded by
> Tuscany.  I think this would be the correct point to do other similar
> post-processing modifications.
>
>  Simon
>
>
Yep, thanks for the heads up Simon. Am in there now.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Nash <na...@apache.org>.
Simon Laws wrote:
> Well same here. I think we have to get pretty close to where the DOMs
> are generated by JAXB and before the DOMs start getting parsed by
> Tuscany.
> 
> Simon
> 
Please take a look at my fix for TUSCANY-3267 (r813785).  For this fix
I inserted code into Interface2WSDLGenerator to modify the schema at
the point where JAXB has generated the DOM but before it is loaded by
Tuscany.  I think this would be the correct point to do other similar
post-processing modifications.

   Simon


Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Well same here. I think we have to get pretty close to where the DOMs
are generated by JAXB and before the DOMs start getting parsed by
Tuscany.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Scott Kurz <sc...@gmail.com>.
Hmm... so given you have tried that approach I'm going to play around
with the post processing approach.   Part of me is thinking it might
not be so bad but then part of me is realizing that since I'm not
sure, I really don't fully know what I'm talking about ;)

Scott

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Hi Scott

>
> Are you saying that you tried modifying the parameter types .class
> files (using ASM or something like that), and this still had "no
> effect"?

If you mean the .class files as they exist on disc then, no, I didn't
try doing that.

Or are you saying that modifying the DataType info built
> from introspecting the Java had no impact?

I was trying to modify the in memory version of the classes that JAXB
uses to generate the WSDL. Even if this did work there is a potential
problem that the classes in the JAXB context don't match the classes
that the service interface is expecting which is probably a bad thing.
Anyhow I was just trying to get my mind round this by trying a few
things. None of those things have worked yet though :-(.

I also had a go at modifying the classes as the wrapper code reads
them in order to generate wrappers. That doesn't appear to have any
effect either. I've maybe got my asm code wrong or in the wrong place.
The databinding and WSDL gen code is sufficiently opaque that it's
difficult to tell.

Anyhow the next thing to try is the post processing schema merge I
guess. But that looks pretty nasty.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Scott Kurz <sc...@gmail.com>.
On Mon, Sep 28, 2009 at 9:14 AM, Simon Laws <si...@googlemail.com> wrote:
> Quick update....
>
> I spent some time looking at whether we could modify the data type on
> the fly at the point at where the Tuscany data types are generated.
> However it turns out that the WSDL generation needs to be driven from
> the wrapper types and these seem to be generated directly of each Java
> method rather than based on the pre-parsed input and output type
> structures. So we can go in an re-write the type in question but it
> has no effect as the generated wrappers will still be referencing the
> unaltered Java type.

Simon,

I can't tell for sure from your email...

Are you saying that you tried modifying the parameter types .class
files (using ASM or something like that), and this still had "no
effect"?    Or are you saying that modifying the DataType info built
from introspecting the Java had no impact?

Scott

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Quick update....

I spent some time looking at whether we could modify the data type on
the fly at the point at where the Tuscany data types are generated.
However it turns out that the WSDL generation needs to be driven from
the wrapper types and these seem to be generated directly of each Java
method rather than based on the pre-parsed input and output type
structures. So we can go in an re-write the type in question but it
has no effect as the generated wrappers will still be referencing the
unaltered Java type.

Next thing I'm going to look at is to see if it's possible to change
the schema later in the process, i.e. after JAXB has generated the
schema. This looks messy though as we store a schema as a schema
collection, as schema and a DOM all at the same time. I'm not sure how
important these different representations are but I expect we have to
merge them all.

Anyone have any better ideas?

Regards

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
OK, I think I understand what's going on. With an empty name specified
it's expecting to generate the type in line but we don't have the
wrapper classes in the list of classes when we generate the schema so
it's generating nothing.

So maybe we can modify our code to add the wrapper classes in as well.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Rather disappointingly. When I add a new type to my sample (that I'm
using to play with wsdl generation) as follows;

@XmlType(name="")
public class CBean {

    protected String field1;
    protected String field2;

    public String getField1() {
        return field1;
    }

    public void setField1(String field1) {
        this.field1 = field1;
    }

    public String getField2() {
        return field2;
    }

    public void setField2(String field2) {
        this.field2 = field2;
    }
}

Then JAXBContext.generateSchema() doesn't generate schema for it.
wsgen for the same interface does however generate schema for CBean
:-(. This JAXB library is just not playing ball.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Simon Laws <si...@googlemail.com>.
Hi Scott

I agree th's rule we want to follow. Without annotation wsgen places
the types in the namespace generated from the service class' packages.
I note that the other way to alter this mapping is with
package-info.java.

Another approach is to force any generated schema types with no
namespace into the namespace of the WSDL after the xsd has been
generated. The JAXB schema generation will already have taken account
of any package-info information.

I've opened TUSCANY-3283 to track this one.

Simon

Re: [1.x & 2.x] Generated WSDL not WS-I compliant in some cases?

Posted by Scott Kurz <sc...@gmail.com>.
Simon,

That was a helpful write up of the issues.

What about the idea of modifying the class file to specify an
@XmlType.name() equal to "" (rather than "##default"), so that we would
end up following this mapping rule per the JAXB spec.

   otherwise if @XmlType.namespace() is
   "##default" && @XmlType.name() is "" and
   class is not annotated with @XmlRootElement, then
   the {target namespace} of the attribute or element
   to which the property or field, from where this class is
   referenced, is mapped.

Having seen how opaque the JAXB RI tooling can be, I wonder if this
might be a good approach.

Scott