cxf-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Phil Weighill-Smith <phil.weighill-sm...@volantis.com>
Subject Re: Problem generating WSDL from Java API with CXF 2.0.3
Date Mon, 28 Jan 2008 10:50:31 GMT
Dan/anyone else,

I've got further (not sure if it will actually work with JAXB
marshalling and unmarshalling, will find out later today) whilst still
using interfaces as part of my API - the WSDL now looks more-or-less OK.

The extra steps I've taken, as previously partially outlined, are to:

      * provide a "simple" implementation of the interface, but one that
        supplies setters too
      * provide an XmlJavaTypeAdapter annotation against the SimpleThing
        interface, and supply the XmlAdapter implementation to adapt
        between the interface and the "simple" mutable implementation
      * annotate the implementation to set the XmlType name to the
        interface name so the WSDL looks sensible

So my SEI looks unchanged, but the following is added/modified:

/**
 * A simple thing to communicate over the web service.
 */
@XmlJavaTypeAdapter(SimpleThingAdapter.class)
public interface SimpleThing {
    ...

Plus:

/**
 * Simple but mutable implementation of {@link SimpleThing}.
 */
@XmlType(name = "SimpleThing")
public class SimpleThingImpl implements SimpleThing {
    // The name of this instance
    private String name;

    // The description of this instance
    private String description;

    @Override
    public String getName() {
        return name;
    }

    /**
     * Sets or resets the name of this instance.
     *
     * @param name the new value for the name
     */
    public void setName(final String name) {
        this.name = name;
    }

    @Override
    public String getDescription() {
        return description;
    }

    /**
     * Sets or resets the description for this instance.
     *
     * @param description the new value for the description
     */
    public void setDescription(final String description) {
        this.description = description;
    }
}

And finally:

    class SimpleThingAdapter extends XmlAdapter<SimpleThingImpl, SimpleThing> {
        @Override
        public SimpleThingImpl marshal(SimpleThing simpleThing)
                throws Exception {
            return (SimpleThingImpl) simpleThing;
        }

        @Override
        public SimpleThing unmarshal(SimpleThingImpl simpleThing)
                throws Exception {
            return simpleThing;
        }
    }

With a Document, Literal, Wrapped binding I get the following WSDL:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="SimpleServiceService" targetNamespace="http://org.bad"
                  xmlns:ns1="http://org.bad.SimpleService/service"
                  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
                  xmlns:tns="http://org.bad"
                  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
                  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
    <wsdl:types>
        <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
                   xmlns:tns="http://org.bad.SimpleService/service"
                   attributeFormDefault="unqualified"
                   elementFormDefault="unqualified"
                   targetNamespace="http://org.bad.SimpleService/service">
            <xs:element name="getThing" type="tns:getThing"/>
            <xs:element name="getThingResponse" type="tns:getThingResponse"/>
            <xs:complexType name="getThing">
                <xs:sequence>
                    <xs:element minOccurs="0" name="name" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
            <xs:complexType name="getThingResponse">
                <xs:sequence>
                    <xs:element minOccurs="0" name="result"
                                type="tns:SimpleThing"/>
                </xs:sequence>
            </xs:complexType>
            <xs:complexType name="SimpleThing">
                <xs:sequence>
                    <xs:element minOccurs="0" name="description"
                                type="xs:string"/>
                    <xs:element minOccurs="0" name="name" type="xs:string"/>
                </xs:sequence>
            </xs:complexType>
        </xs:schema>
    </wsdl:types>
    <wsdl:message name="getThing">
        <wsdl:part name="parameters" element="ns1:getThing">
        </wsdl:part>
    </wsdl:message>
    <wsdl:message name="getThingResponse">
        <wsdl:part name="parameters" element="ns1:getThingResponse">
        </wsdl:part>
    </wsdl:message>
    <wsdl:portType name="SimpleService">
        <wsdl:operation name="getThing">
            <wsdl:input name="getThing" message="ns1:getThing">
            </wsdl:input>
            <wsdl:output name="getThingResponse"
                         message="ns1:getThingResponse">
            </wsdl:output>
        </wsdl:operation>
    </wsdl:portType>
    <wsdl:binding name="SimpleServiceServiceSoapBinding"
                  type="ns1:SimpleService">
        <soap:binding style="document"
                      transport="http://schemas.xmlsoap.org/soap/http"/>
        <wsdl:operation name="getThing">
            <soap:operation soapAction="" style="document"/>
            <wsdl:input name="getThing">
                <soap:body use="literal"/>
            </wsdl:input>
            <wsdl:output name="getThingResponse">
                <soap:body use="literal"/>
            </wsdl:output>
        </wsdl:operation>
    </wsdl:binding>
    <wsdl:service name="SimpleServiceService">
        <wsdl:port name="SimpleServicePort"
                   binding="ns1:SimpleServiceServiceSoapBinding">
            <soap:address location="http://localhost:9090/hello"/>
        </wsdl:port>
    </wsdl:service>
</wsdl:definitions>

The only things I still can't control are:

      * whether the various parameters and results can be "null" (i.e. I
        would like to change the minOccurs="0" to minOccurs="1" - the
        default for XML Schema)
      * ensuring that the generated complex types have all elements in
        the required namespace (the schema has elementFormDefault as
        "unqualified", whilst I'd like them to be qualified)
      * ensuring the WSDL contains appropriate documentation.

Any ideas how to address these?

Phil :n.

On Fri, 2008-01-25 at 11:50 -0500, Daniel Kulp wrote:
> JAXB generally doesn't like interfaces too much.  In general, we 
> definitely suggest using concrete classes.   
> 
> That said, one major issue is that your interface doesn't have setter 
> methods on it.   There's no way there's any chance of it working without 
> that.   JAXB would only expose properties that have bother getters and 
> setters.   That said, I still doubt it will work as interfaces.   The 
> jaxws spec really doesn't allow for that at all.   Just concrete data 
> objects.
> 
> Dan
> 
> 
> 
> 
> On Friday 25 January 2008, Phil Weighill-Smith wrote:
> > For some reason I can't get CXF 2.0.3 to generate what looks like
> > correct WSDL from a set of Java interfaces. I either get no XML
> > representing the object(s) or get an abstract complex type for the
> > object(s) depending on the interfaces involved.
> >
> > Here's a simple example. Because I use interfaces for the returned
> > object(s) I have a factory. This looks like:
> >
> > package org.bad;
> >
> > /**
> >  * A simple factory to allow JAXB to handle the various interfaces
> > used. */
> > public class SimpleFactory {
> >     /**
> >      * Support the {@link SimpleThing} class.
> >      *
> >      * @return a SimpleThing implementation. Added setters for good
> > luck not *         knowing just how JAXB should handle unmarshalling
> > */
> >     public SimpleThing createSimpleThing() {
> >         return new SimpleThing() {
> >             /**
> >              * The description.
> >              */
> >             private String description = null;
> >
> >             /**
> >              * The name.
> >              */
> >             private String name = null;
> >
> >             @Override
> >             public String getDescription() {
> >                 return description;
> >             }
> >
> >             @Override
> >             public String getName() {
> >                 return name;
> >             }
> >
> >             /**
> >              * Allow the description to be modified.
> >              *
> >              * @param description the new description
> >              */
> >             public void setDescription(String description) {
> >                 this.description = description;
> >             }
> >
> >             /**
> >              * Allow the name to be modified.
> >              *
> >              * @param name the new name
> >              */
> >             public void setName(String name) {
> >                 this.name = name;
> >             }
> >         };
> >     }
> > }
> >
> > I then have the SimpleThing (the object to be returned) defined as:
> >
> > package org.bad;
> >
> > import javax.xml.bind.annotation.XmlType;
> >
> > /**
> >  * A simple thing to communicate over the web service.
> >  */
> > @XmlType(factoryClass = SimpleFactory.class,
> >          factoryMethod = "createSimpleThing")
> > public interface SimpleThing {
> >     /**
> >      * A read-only name property.
> >      *
> >      * @return the name property
> >      */
> >     String getName();
> >
> >     /**
> >      * A read-only description property.
> >      *
> >      * @return the description property
> >      */
> >     String getDescription();
> > }
> >
> > Finally, the service is then defined thus:
> >
> > package org.bad;
> >
> > import javax.jws.WebService;
> > import javax.jws.WebParam;
> > import javax.jws.WebResult;
> > import javax.jws.soap.SOAPBinding;
> >
> > /**
> >  * The SEI java class.
> >  */
> > @WebService(name = "SimpleService",
> >             targetNamespace = "http://org.bad.SimpleService/service")
> > @SOAPBinding(style = SOAPBinding.Style.RPC,
> >              use = SOAPBinding.Use.ENCODED,
> >              parameterStyle = SOAPBinding.ParameterStyle.WRAPPED)
> > public interface SimpleService {
> >     /**
> >      * Get a {@link SimpleThing} by name.
> >      *
> >      * @param name the name for the {@link SimpleThing} to be
> > returned. * @return the {@link SimpleThing} with that name, or null if
> > there isn't a
> >      *         match
> >      */
> >     @WebResult(name = "result",
> >                targetNamespace = "http://org.bad.SimpleService")
> >     SimpleThing getThing(
> >             @WebParam(name = "name")
> >             final String name);
> > }
> >
> > When I run the java2wsdl (via the IDEA's Web Services integration
> > mechanism) I get the following output:
> >
> > <?xml version="1.0" encoding="UTF-8"?>
> > <wsdl:definitions name="SimpleServiceService"
> > targetNamespace="http://org.bad"
> >                   xmlns:ns1="http://org.bad.SimpleService/service"
> >                   xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
> >                   xmlns:tns="http://org.bad"
> >                   xmlns:xsd="http://www.w3.org/2001/XMLSchema"
> >                   xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
> >     <wsdl:message name="getThing">
> >         <wsdl:part name="name" type="xsd:string">
> >         </wsdl:part>
> >     </wsdl:message>
> >     <wsdl:message name="getThingResponse">
> >         <wsdl:part name="result">
> >         </wsdl:part>
> >     </wsdl:message>
> >     <wsdl:portType name="SimpleService">
> >         <wsdl:operation name="getThing">
> >             <wsdl:input name="getThing" message="ns1:getThing">
> >             </wsdl:input>
> >             <wsdl:output name="getThingResponse"
> >                          message="ns1:getThingResponse">
> >             </wsdl:output>
> >         </wsdl:operation>
> >     </wsdl:portType>
> >     <wsdl:binding name="SimpleServiceServiceSoapBinding"
> >                   type="ns1:SimpleService">
> >         <soap:binding style="rpc"
> >                      
> > transport="http://schemas.xmlsoap.org/soap/http"/> <wsdl:operation
> > name="getThing">
> >             <soap:operation soapAction="" style="rpc"/>
> >             <wsdl:input name="getThing">
> >                 <soap:body use="literal"
> >
> > namespace="http://org.bad.SimpleService/service"/>
> >             </wsdl:input>
> >             <wsdl:output name="getThingResponse">
> >                 <soap:body use="literal"
> >
> > namespace="http://org.bad.SimpleService/service"/>
> >             </wsdl:output>
> >         </wsdl:operation>
> >     </wsdl:binding>
> >     <wsdl:service name="SimpleServiceService">
> >         <wsdl:port name="SimpleServicePort"
> >                    binding="ns1:SimpleServiceServiceSoapBinding">
> >             <soap:address location="http://localhost:9090/hello"/>
> >         </wsdl:port>
> >     </wsdl:service>
> > </wsdl:definitions>
> >
> >
> > As you can see, there is no XML binding schema for SimpleThing and
> > nothing in the result from the getThing operation (in bold)... what
> > have I done wrong?
> >
> > Note that I found I could not use use the default binding style
> > (document) and use (literal) with wrapped or bare parameter styles
> > since these threw exceptions (either that the wrapper classes were
> > missing from the class path or with an NPE from the generator code
> > somewhere).
> >
> > Phil
> 
> 
> 


Mime
View raw message