Hi,
I do a simple experiment about the design sugguest by Dan.
First, I use jaxb, not xjc. I think they have the principle.
The schema like this[1]:
<xs:element name="deliveryMode" type="soapjms:deliveryModeType" />
<xs:complexType name="deliveryModeType">
<xs:simpleContent>
<xs:extension base="xs:string">
</xs:extension>
</xs:simpleContent>
</xs:complexType>
The generated class for DeliveryModeType like this[2]:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "deliveryModeType", propOrder = {
"value"
})
public class DeliveryModeType{
@XmlValue
protected String value;
/**
* Gets the value of the value property.
*
* @return
* possible object is
* {...@link String }
*
*/
public String getValue() {
return value;
}
/**
* Sets the value of the value property.
*
* @param value
* allowed object is
* {...@link String }
*
*/
public void setValue(String value) {
this.value = value;
}
public boolean isSetValue() {
return (this.value!= null);
}
}
The DeliveryModeType doesn't extend TExtensibilityElementImpl. So I
just
modify the class and make it look like this[3]:
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "deliveryModeType", propOrder = {
"value"
})
public class DeliveryModeType extends TExtensibilityElementImpl{
@XmlValue
protected String value;
/**
* Gets the value of the value property.
*
* @return
* possible object is
* {...@link String }
*
*/
public String getValue() {
return value;
}
/**
* Sets the value of the value property.
*
* @param value
* allowed object is
* {...@link String }
*
*/
public void setValue(String value) {
this.value = value;
}
public boolean isSetValue() {
return (this.value!= null);
}
}
Then when I publish a service, I get an exception[4]
Creating Service {http://cxf.apache.org/jms_greeter}JMSGreeterService
from WSDL: file:./wsdl/jms_greeter.wsdl
Exception in thread "main" javax.xml.ws.WebServiceException:
org.apache.cxf.service.factory.ServiceConstructionException: Failed to
create service.
at
org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:275)
at
org.apache.cxf.jaxws.EndpointImpl.publish(EndpointImpl.java:209)
at
org.apache.cxf.jaxws.spi.ProviderImpl.createAndPublishEndpoint(ProviderImpl
.java:84) at javax.xml.ws.Endpoint.publish(Endpoint.java:47)
at demo.jms_greeter.server.Server.<init>(Server.java:30)
at demo.jms_greeter.server.Server.main(Server.java:34)
Caused by:
org.apache.cxf.service.factory.ServiceConstructionException:
Failed to create service.
at
org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:93)
at
org.apache.cxf.service.factory.ReflectionServiceFactoryBean.buildServiceFro
mWSDL(ReflectionServiceFactoryBean.java:317) at
org.apache.cxf.service.factory.ReflectionServiceFactoryBean.initializeServi
ceModel(ReflectionServiceFactoryBean.java:437) at
org.apache.cxf.service.factory.ReflectionServiceFactoryBean.create(Reflecti
onServiceFactoryBean.java:195) at
org.apache.cxf.jaxws.support.JaxWsServiceFactoryBean.create(JaxWsServiceFac
toryBean.java:163) at
org.apache.cxf.frontend.AbstractWSDLBasedEndpointFactory.createEndpoint(Abs
tractWSDLBasedEndpointFactory.java:100) at
org.apache.cxf.frontend.ServerFactoryBean.create(ServerFactoryBean.java:117
) at
org.apache.cxf.jaxws.JaxWsServerFactoryBean.create(JaxWsServerFactoryBean.j
ava:167) at
org.apache.cxf.jaxws.EndpointImpl.getServer(EndpointImpl.java:346) at
org.apache.cxf.jaxws.EndpointImpl.doPublish(EndpointImpl.java:259)
... 5
more
Caused by: javax.wsdl.WSDLException: WSDLException (at
/wsdl:definitions/wsdl:binding/soapjms:deliveryMode):
faultCode=PARSER_ERROR: Error reading element
{http://www.w3.org/2008/07/soap/bindings/JMS/}deliveryMode:
java.lang.RuntimeException:
com.sun.xml.bind.v2.runtime.IllegalAnnotationsException: 1 counts of
IllegalAnnotationExceptions
@XmlValue is not allowed on a class that derives another class.
this problem is related to the following location:
at protected java.lang.String
org.apache.cxf.transport.jms.spec.DeliveryModeType.value
at org.apache.cxf.transport.jms.spec.DeliveryModeType
at public org.apache.cxf.transport.jms.spec.DeliveryModeType
org.apache.cxf.transport.jms.spec.ObjectFactory.createDeliveryModeType()
at org.apache.cxf.transport.jms.spec.ObjectFactory
at
org.apache.cxf.wsdl.JAXBExtensionHelper.unmarshall(JAXBExtensionHelper.java
:299) at
com.ibm.wsdl.xml.WSDLReaderImpl.parseExtensibilityElement(Unknown
Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.parseBinding(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.parseDefinitions(Unknown
Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at com.ibm.wsdl.xml.WSDLReaderImpl.readWSDL(Unknown Source)
at
org.apache.cxf.wsdl11.WSDLManagerImpl.loadDefinition(WSDLManagerImpl.java:2
10) at
org.apache.cxf.wsdl11.WSDLManagerImpl.getDefinition(WSDLManagerImpl.java:17
5) at
org.apache.cxf.wsdl11.WSDLServiceFactory.<init>(WSDLServiceFactory.java:91)
... 14 more
So I have a question. What's wrong? Could the xjc solve this
exception?
thank you.
liu
Daniel Kulp wrote:
On Thu June 25 2009 1:39:34 am liucong wrote:
Hi, Dan,
Thank you very much for your advice. By some experiments for
the
WSDL extension. I think it is right that this WSDL extension
needs some
changes to CXF wsdl processing. And the CXF wsdl processing will
supoort
the entension in SOAP/JMS. I think this kind of extension is
necessary
for CXF wsdl processing.
The best place to look is in the cxf trunk/common/xjc/ts
project. That
project is an XJC plugin that adds "toString" methods to all the
generated types.
For MOST cases, you would need make the superclass be
TExtensibilityElementImpl instead of Object.
In other cases, it's a bit more complex:
1) For stuff that sublasses JAXBElement, you would need to make it
implement ExtensibilityElement and add those methods and field.
2) For Enums - I think the stuff from (1) applies as well, not really
sure though.
Technically, it PROBABLY just needs to apply to "root" elements.
(Stuff
with @XmlRootElement annotations).
Dan
Are there any documents which help me finish this kind of
extension? thank you! :-)
Liu
Daniel Kulp wrote:
Hmm... I'm not really sure. I don't think there IS a schema
that
would work properly for this. My gut feeling was something like:
<xs:complexType name="deliveryModeType">
<xs:simpleContent>
<xs:restriction base="wsdl:tExtensibilityElement">
<xs:enumeration value="PERSISTENT" />
<xs:enumeration value="NON_PERSISTENT" />
</xs:restriction>
</xs:simpleContent>
</xs:complexType>
but I know that doesn't work.
This will probably need some changes to CXF wsdl processing to
really
get this to work well. Actually, this could provide a good
opportunity to cleanup the JAXB WSDL extension mechanism to NOT
require that the schema extends the wsdl:tExtensibilityElement
type. I'm actually thinking a xjc plugin that would make all
the generated
types
automatically implement the wsdl4j ExtensibiltyElement interface
and
add the methods/fields for that.
That can significantly cleanup the CXF schemas for all the
extensors.
It would be completely automatic.
Dan
On Tue June 23 2009 11:51:43 am liucong wrote:
Hi,
I want to add wsdl extension for SOAP/JMS according to
http://www.w3.org/TR/2008/WD-soapjms-20081121/#wsdl-extensions.
For example, I want add wsdl extension for DeliveryMode
property. I
edit the wsdl file like[1]:
<wsdl:binding name="JMSGreeterPortBinding"
type="tns:JMSGreeterPortType"> <soap:binding style="document"
transport="http://www.w3.org/2008/07/soap/bindings/JMS/"/>
<soapjms:deliveryMode>PERSISTENT</soapjms:deliveryMode>
<wsdl:operation name="greetMe">
<soap:operation soapAction="test" style="document"/>
<wsdl:input name="greetMeRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="greetMeResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
...
</wsdl:binding>
If I add the extension schema like this[2]:
<xs:element name="deliveryMode" type="soapjms:deliveryModeType" />
<xs:complexType name="deliveryModeType">
<xs:complexContent>
<xs:extension base="wsdl:tExtensibilityElement">
<xs:sequence>
<xs:element name="deliveryMode">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="PERSISTENT" />
<xs:enumeration value="NON_PERSISTENT" />
</xs:restriction>
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
But I can't get the extension in the wsdl.
If I change the wsdl like this[3]:
<wsdl:binding name="JMSGreeterPortBinding"
type="tns:JMSGreeterPortType"> <soap:binding style="document"
transport="http://www.w3.org/2008/07/soap/bindings/JMS/"/>
<soapjms:deliveryMode><soapjms:deliveryMode>PERSISTENT</soapjms:delive
ry Mod e></soapjms:deliveryMode>
<wsdl:operation name="greetMe">
<soap:operation soapAction="test" style="document"/>
<wsdl:input name="greetMeRequest">
<soap:body use="literal"/>
</wsdl:input>
<wsdl:output name="greetMeResponse">
<soap:body use="literal"/>
</wsdl:output>
</wsdl:operation>
...
</wsdl:binding>
I'll get the result of deliveryMode extension.
I think the wsdl extension just can add attributes, element to a
extension element in CXF. But I can't get the extension element's
value. Is it right?
My question is: how to get the extension information in [1].
What does
the extension schema look like?
thanks.
Liu