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 Wed, 30 Jan 2008 11:46:22 GMT
Not sure exactly why, but it appears that I will have to use Lists as
you have suggested (it seems that that is what JAXB requires). I found
some comments [1] that seem to imply that this is necessary (the idea of
an array-based adapter didn't seem to fix the issue after all)...

I'll see where I get to with that. Thanks for your help (so far!).

Phil :n(

1: http://blogs.sun.com/trajesh/entry/migrating_from_jax_rpc_to

On Mon, 2008-01-28 at 15:45 -0500, Cobery, Marc wrote:
> Hi,
> Have you tried using a List instead of an array for your return value?
> 
> Do you have a demo project that I could reference?
> I have tried the annotation of interfaces and have had it work sporadically.  I just
received a "org.apache.cxf.interceptor.Fault: Marshalling Error: com.rulestream.core.knowledge.domain.MyClass
is not known to this context" exception.
> Before this exception, I could not initialize the web service.
> 
> Regards,
> Marc
> 
> 
> -----Original Message-----
> From: Phil Weighill-Smith [mailto:phil.weighill-smith@volantis.com]
> Sent: Monday, January 28, 2008 12:20 PM
> To: Daniel Kulp
> Cc: cxf-user@incubator.apache.org
> Subject: Re: Problem generating WSDL from Java API with CXF 2.0.3
> 
> Dan,
> 
> What I've found so far is that I can declare myself a new adapter, e.g.:
> 
>     public final class SimpleThingArrayAdapter extends
>             XmlAdapter<SimpleThingImpl[], SimpleThing[]> {
>         @Override
>         public SimpleThingImpl[] marshal(SimpleThing[] simpleThings)
>                 throws Exception {
>             if (simpleThings instanceof SimpleThingImpl[]) {
>                 return (SimpleThingImpl[]) simpleThings;
>             } else {
>                 SimpleThingImpl[] result =
>                         new SimpleThingImpl[simpleThings.length];
>                 System.arraycopy(simpleThings, 0,
>                                  result, 0,
>                                  simpleThings.length);
>                 return result;
>             }
>         }
> 
>         @Override
>         public SimpleThing[] unmarshal(SimpleThingImpl[] simpleThings)
>                 throws Exception {
>             return simpleThings;
>         }
>     }
> 
> and then assign this against the web method, e.g.:
> 
>     @WebResult(name = "result",
>                targetNamespace = Namespace.URI)
>     @XmlJavaTypeAdapter(type = SimpleThing[].class, value = org.bad.jaxb.SimpleThingArrayAdapter.class)
>     SimpleThing[] getThingsThatMatch(
>             @WebParam(name = "namePattern")
>             final String namePattern);
> 
> This then gets rid of the error... I think. Not finished sorting this
> out though...
> 
> If I hit a dead end I'll look see if 2.1 helps.
> 
> Thanks again,
> 
> Phil :n.
> 
> On Mon, 2008-01-28 at 11:41 -0500, Daniel Kulp wrote:
> > On Monday 28 January 2008, Phil Weighill-Smith wrote:
> > > I'm trying to apply the pattern I described earlier to my real world
> > > scenario. The problem I haven't figured out a way round is when I have
> > > parameters and return types based on arrays of the interfaces. I get
> > > an annotation error with JAXB complaining it can't handle interfaces
> > > (despite having the required @XmlJavaTypeAdapter against the interface
> > > itself). I've tried repeating the @XmlJavaTypeAdapter definition as
> > > part of the web method signature but that doesn't seem to work.
> >
> > That will only work with JAX-WS 2.1 and thus CXF 2.1 snapshots.  And even
> > then I'm not sure if we have that working in the snapshots yet.
> >
> > Not sure what to suggest.   I'm wondering if it's not finding the "impl"
> > that goes with it.   With 2.1, I'd suggest adding an @XmlSeeAlso
> > annotation to make sure the impl gets pulled in.   Maybe try a
> > jaxb.index file in the package that just has the line "SimpleThinkImpl"
> > or similar to make sure the impl gets sucked into the context creation.
> >
> > It might just be a bug in jaxb.   I'd honestly suggest trying with the
> > CXF 2.1 snapshots to see if it works there.   2.1 uses the latest JAXB
> > 2.1 version which may have a lot more issues fixed.
> >
> > Dan
> >
> >
> >
> >
> > >
> > > Do I need to provide an adapter for the array type? (I'll give that a
> > > try, I guess.)
> > >
> > > Phil :n(
> > >
> > > PS: If I ever find time, I'm sure I could extend the SimpleService
> > > example to cover these awkward aspects and to get it to a working
> > > example state... don't hold your breath though! ;n)
> > >
> > > On Mon, 2008-01-28 at 10:31 -0500, Daniel Kulp wrote:
> > > > That's very cool.   This is something I'd actually like to see a
> > > > complete project/build/example for as a tutorial or something if you
> > > > can get it working.
> > > >
> > > > >   * 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)
> > > >
> > > > In the SimpleThingImpl, on the getters or on the fields, add:
> > > > @XmlElement(required = true)
> > > >
> > > > >       * 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)
> > > >
> > > > Two options:
> > > > 1) And @XmlElement annotations to everything and fill in namespaces
> > > > for them
> > > >
> > > > 2) Create a package-info.java class in the package containing the
> > > > beans. It would look like:
> > > >
> > > > @javax.xml.bind.annotation.XmlSchema(
> > > >      namespace = "http://the.namespace.to.use",
> > > >      elementFormDefault =
> > > > javax.xml.bind.annotation.XmlNsForm.QUALIFIED) package the package;
> > > >
> > > > >       * ensuring the WSDL contains appropriate documentation.
> > > >
> > > > THAT is something I don't know if it's possible.   You'd probably
> > > > have to ask on the JAXB list about that.
> > > >
> > > > Dan
> > > >
> > > > > Any ideas how to address these?
> > > >
> > > > On Monday 28 January 2008, Phil Weighill-Smith wrote:
> > > > > 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