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:[EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] 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 [EMAIL PROTECTED] SimpleThing} by name. > > > > > > * > > > > > > * @param name the name for the [EMAIL PROTECTED] SimpleThing} > > > > > > to be > > > > > > returned. * @return the [EMAIL PROTECTED] 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 > > >