I am exposing a web service using CXF. I am using the #XmlID and #XmlIDREF JAXB annotations to maintain referential integrity of my object graph during marshalling/unmarshalling.
The WSDL rightly contains elements with the xs:id and xs:idref attributes to represent this.
On the server side, everything works really nicely. Instances of Types annotated with #XmlIDREF are the same instances (as in ==) to those annotated with the #XmlID annotation.
However, when I generate a client with WSDLToJava, the references (those annotated with #XmlIDREF) are of type java.lang.Object.
Is there any way that I can customise the JAXB bindings such that the types of references are either java.lang.String (to match the ID of the referenced type) or the same as the referenced type itself?
Use the inline JAXB bindings to indicate the type to be used. Then JAXB generated code will have correct type.
<complexType name="Column">
<sequence>
<element name="name" type="string" maxOccurs="1" minOccurs="1"></element>
<element name="referencedColumn" type="IDREF" maxOccurs="1" minOccurs="0">
<annotation>
<appinfo>
<jaxb:property>
<jaxb:baseType name="Column"/>
</jaxb:property>
</appinfo>
</annotation>
</element>
</sequence>
<attribute name="id" type="ID" use="required"></attribute>
</complexType>
Also note that you have to declare the jaxb namespace and JAXB version in the schema element.
<schema targetNamespace="http://example.com/schema"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="1.0">
The following seems to at least create string properties for elements/attributes of type xs:IDREF. A good start, but ideally JAXB would generate properties of the same type as the element being referenced. I'll report back if/when I find out how to do that. This result may indicate that I need to write my own converters which would be a shame.
<jxb:bindings version="2.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:globalBindings>
<jxb:javaType name="java.lang.String" xmlType="xs:IDREF" parseMethod="javax.xml.bind.DatatypeConverter.parseString" printMethod="javax.xml.bind.DatatypeConverter.printString" />
</jxb:globalBindings>
</jxb:bindings>
OK, so this isn't going to work. It's not possible for JAXB to generate code with the correct types for the IDREFs because the schema can't specify the types of references and there may be IDREF's pointing to different complex types. How would JAXB know what are the types of the references? An extension to XML Schema would do it! :)
Related
Im triying to implement a simple BPEL process that should be able to accept as an input an element defined in an external XSD.
Im using Eclipse Oxigen.2 Release (4.7.2) and the Eclipse BPEL designer 1.05 Final, also i'm running the BPEL process in Apache ODE Server 1.3.7.
To achieve this im importing the XSD in the BPEL generated WSDL, but when i include this tag the apache ODE Console doesnt show the process if i quit the import tag the process is showed in the console and runs correctly.
As BPEL2.0 is based in WSDL1.1 i was following the WSDL1.1 specification in the Authoring Style part, but it seems to be an error in the example, because they use the wsdl:import to import a XSD. Trying to import the XSD in this way raise a validation error in eclipse.
I found this answer that points to this link that states the error in WSDL1.1 specification:
Some examples in WSDL 1.1 incorrectly show the WSDL import statement
being used to import XML Schema definitions. The Profile clarifies use
of the import mechanisms to keep them consistent and confined to their
respective domains. Imported schema documents are also constrained by
XML version and encoding requirements consistent to those of the
importing WSDL documents.
R2001 A DESCRIPTION MUST only use the WSDL "import" statement to
import another WSDL description.
R2803 In a DESCRIPTION, the namespace attribute of the wsdl:import
MUST NOT be a relative URI.
R2002 To import XML Schema Definitions, a DESCRIPTION MUST use the XML
Schema "import" statement.
R2003 A DESCRIPTION MUST use the XML Schema "import" statement only
within the xsd:schema element of the types section.
R2004 In a DESCRIPTION the schemaLocation attribute of an xsd:import
element MUST NOT resolve to any document whose root element is not
"schema" from the namespace "http://www.w3.org/2001/XMLSchema".
R2009 An XML Schema directly or indirectly imported by a DESCRIPTION
MAY include the Unicode Byte Order Mark (BOM).
R2010 An XML Schema directly or indirectly imported by a DESCRIPTION
MUST use either UTF-8 or UTF-16 encoding.
R2011 An XML Schema directly or indirectly imported by a DESCRIPTION
MUST use version 1.0 of the eXtensible Markup Language W3C
Recommendation.
So with the above information, rigth now i have:
1. XSD Sxhema
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2"
xmlns:cac="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
xmlns:cbc="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
xmlns:ext="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ccts="urn:un:unece:uncefact:documentation:2"
targetNamespace="urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2"
elementFormDefault="qualified"
attributeFormDefault="unqualified"
version="2.1">
<!-- ===== Imports ===== -->
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonAggregateComponents-2"
schemaLocation="../common/UBL-CommonAggregateComponents-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonBasicComponents-2"
schemaLocation="../common/UBL-CommonBasicComponents-2.1.xsd"/>
<xsd:import namespace="urn:oasis:names:specification:ubl:schema:xsd:CommonExtensionComponents-2"
schemaLocation="../common/UBL-CommonExtensionComponents-2.1.xsd"/>
<!-- ===== Element Declarations ===== -->
<xsd:element name="OrderCancellation" type="OrderCancellationType">
<xsd:annotation>
<xsd:documentation>This element MUST be conveyed as the root element in any instance document based on this Schema expression</xsd:documentation>
</xsd:annotation>
</xsd:element>
<!-- ===== Type Definitions ===== -->
<xsd:complexType name="OrderCancellationType">
<xsd:annotation>
<xsd:documentation>
<ccts:Component>
<ccts:ComponentType>ABIE</ccts:ComponentType>
<ccts:DictionaryEntryName>Order Cancellation. Details</ccts:DictionaryEntryName>
<ccts:Definition>A document used to cancel an entire Order.</ccts:Definition>
<ccts:ObjectClass>Order Cancellation</ccts:ObjectClass>
</ccts:Component>
</xsd:documentation>
</xsd:annotation>
<xsd:sequence>
<xsd:element ref="cbc:IssueDate" minOccurs="1" maxOccurs="1">
<xsd:annotation>
<xsd:documentation>
<ccts:Component>
<ccts:ComponentType>BBIE</ccts:ComponentType>
<ccts:DictionaryEntryName>Order Cancellation. Issue Date. Date</ccts:DictionaryEntryName>
<ccts:Definition>The date, assigned by the sender, on which this document was issued.</ccts:Definition>
<ccts:Cardinality>1</ccts:Cardinality>
<ccts:ObjectClass>Order Cancellation</ccts:ObjectClass>
<ccts:PropertyTerm>Issue Date</ccts:PropertyTerm>
<ccts:RepresentationTerm>Date</ccts:RepresentationTerm>
<ccts:DataType>Date. Type</ccts:DataType>
</ccts:Component>
</xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element ref="cbc:IssueTime" minOccurs="0" maxOccurs="1">
<xsd:annotation>
...
</xsd:annotation>
</xsd:element>
<xsd:element ref="cbc:Note" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
...
</xsd:annotation>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
2. Generated WSDL of BPEL Process
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<definitions
xmlns="http://schemas.xmlsoap.org/wsdl/"
xmlns:plnk="http://docs.oasis-open.org/wsbpel/2.0/plnktype"
xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:tns="http://br.ufsc.das.ubl"
xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2"
xmlns:vprop="http://docs.oasis-open.org/wsbpel/2.0/varprop"
xmlns:wsdl="http://service.endpoint.br.ufsc.das/"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
name="OrderingUBL"
targetNamespace="http://br.ufsc.das.ubl">
<!--
Added XSD namespace
xmlns:ubl="urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2"
-->
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
TYPE DEFINITION - List of types participating in this BPEL process
The BPEL Designer will generate default request and response types
but you can define or import any XML Schema type and use them as part
of the message types.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<plnk:partnerLinkType name="IntegratorEndPoint_PLT">
<plnk:role name="IntegratorEndPoint_Role" portType="wsdl:IntegrationEndPointImpl"/>
</plnk:partnerLinkType>
<import location="file:/C:/my/path/IntegrationEndpoint.wsdl" namespace="http://service.endpoint.br.ufsc.das/"/>
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
attributeFormDefault="unqualified"
elementFormDefault="qualified"
targetNamespace="http://br.ufsc.das.ubl">
<!--Importing the XSD file-->
<import
namespace="urn:oasis:names:specification:ubl:schema:xsd:OrderCancellation-2"
schemaLocation="file:/C:/UBL-2.1/xsd/maindoc/UBL-OrderCancellation-2.xsd" />
<element name="OrderingUBLRequest">
<complexType>
<sequence>
<!-- Defining the Type of element OrderingUBLRequest
to be the element in the imported XSD
-->
<element name="input" type="ubl:OrderCancellationType" />
</sequence>
</complexType>
</element>
<element name="OrderingUBLResponse">
<complexType>
<sequence>
<element name="result" type="string"/>
</sequence>
</complexType>
</element>
</schema>
</types>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
MESSAGE TYPE DEFINITION - Definition of the message types used as
part of the port type defintions
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<message name="OrderingUBLRequestMessage">
<part element="tns:OrderingUBLRequest" name="payload"/>
</message>
<message name="OrderingUBLResponseMessage">
<part element="tns:OrderingUBLResponse" name="payload"/>
</message>
<!--
.
. All the other WSDL tags
.
-->
</definitions>
QUESTION
Am I missing something importing the XSD in the WSDL BPEL file and run it in Apache ODE?
I am trying to generate stub files using jaxws wsimport.
In the WSDL there are two types which are conflicting:
line 68: <s:element minOccurs="0" maxOccurs="1" name="DAGSBROTTFELLT" type="s:string" />
and line 119: <s:element minOccurs="0" maxOccurs="1" name="DAGS_BROTTFELLT" type="s:string" />
The reason is that wsimport does not preserves the underscore character "_" and thinks that the both names are the same.
I have created a jaxb bindings file to name explicitly the resulting Java class.
But the wsimport says:
[ERROR] XPath error: null
line 11 of file:/C:/Users/deyan/ss_workspace/MVS%20Services/src/is/mvs/services/ws/xjb/companyInfo.xjb
I have tested the xpath string in
http://www.freeformatter.com/xpath-tester.html#ad-output
And it truly returns the element.
Please help to figure out why the wsimport says that the xpath is null.
Thank you in advance!
This is my WSDL:
https://gognxml.uh.is/xml_service.asmx?WSDL
This is the jaxb bindings file:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxws:bindings
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
wsdlLocation="https://gognxml.uh.is/xml_service.asmx?WSDL">
<enableWrapperStyle>true</enableWrapperStyle>
<enableAsyncMapping>false</enableAsyncMapping>
<jaxws:bindings node="wsdl:definitions/wsdl:types/s:schema/s:complexType[#name='Faersla']/s:sequence/s:element[#name='DAGS_BROTTFELLT']">
<jaxb:class name="Dags_Brottfellt"/>
</jaxws:bindings>
</jaxws:bindings>
One thing I notice is that the XPath expression uses the s namespace prefix (e.g. s:schema), but I don't see that namespace prefix declared anywhere. Is it supposed to be declared on one of the <jaxws:bindings> elements? Or where are such prefixes expected to be declared? Usually, having them declared in the input XML is not sufficient. But I don't know anything about wsimport.
P.S. Looks like the xs prefix is not used, so maybe it was supposed to be s. As you already confirmed in your comment. :-)
I want to generate the POJOs using the xml-binding with a different hierarchy that I have right now.
Now I have an xsd like this one:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://manueldoncel.com" xmlns:tns="http://manueldoncel.com" elementFormDefault="qualified">
<!-- Base element that any element uses / extends -->
<complexType name="baseElement" abstract="true">
<sequence>
<element name="attributes" type="anyType" minOccurs="0" />
</sequence>
<attribute name="id" type="string" />
</complexType>
<complexType name="Square">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
<complexType name="Triangle">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
</schema>
An a xjb like this;
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="figures.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
<xjc:superClass name="org.manuel.metadata.Figure"/>
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
But, I would like to have a better hierarchy with this approach
public abstract class Figure {
// some methods for all the figures
}
public abstract class ThreeSideFigure extends Figure {
.... // some methods for only the Three side Figures
}
So, the Triangle POJO generated from the XSD should extend from ThreeSideFigure rather than from Figure.
In this particular xsd I only put 2 figures, but I can have much more. I would like to be able to specify in the xjb that all the complexType should extends from Figure but only a few of them, should extends from ThreeSideFigure.
Do you know how the xjb should look like?
I don't think the Metro JAXB RI extensions will let you do that.
From the 2.2.7 documentation:
3.1.3. Extending a Common Super Class
The <xjc:superClass> customization allows you to specify the fully
qualified name of the Java class that is to be used as the super class
of all the generated implementation classes. The <xjc:superClass>
customization can only occur within your <jaxb:globalBindings>
customization on the <xs:schema> element
That said, the answer to XJC superinterface and superclass only for all classes? suggests that you may be able to do it with 3rd party extensions. There are some details about plugins in the documentation.
When I run xjc to generate a Java type representing this XSD snippet:
<xs:complexType name="fileUploadRequest">
<xs:choice>
<xs:element name="path" type="xs:string"/>
<xs:element name="file" type="xs:base64Binary"/>
</xs:choice>
</xs:complexType>
I get a class that's indistinguishable from what it would have been if I'd specified a sequence with optional elements instead.
I want a type with a little bit of intelligence, that'll let me have at most 1 element of my choice at a time. If I invoke the generated setFile method for example, it should make the path null. Is there some plugin I can use for what seems like an obvious requirement of a code generator?
binding.xml
You can use the following external binding file to generate the type of property you are looking for:
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<globalBindings choiceContentProperty="true"/>
</bindings>
XJC Call
The binding file is referenced using the -b flag.
xjc -b binding.xml schema.xsd
Generated Property
Now the following property will be generated:
#XmlElements({
#XmlElement(name = "path", type = String.class),
#XmlElement(name = "file", type = byte[].class)
})
protected Object pathOrFile;
For More Information
http://blog.bdoughan.com/2011/04/xml-schema-to-java-xsd-choice.html
I doubt if there is something like this but I thought to ask though:
Does anyone know if there is a library in Java that reads an xsd file and "creates" the defined elements e.g. in a String format to use in the code?
E.g. read in the following schema:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Address">
<xs:complexType>
<xs:sequence>
<xs:element name="Street" type="xs:string" />
<xs:element name="Town" type="xs:string" />
<xs:element name="Country" type="xs:string" minOccurs="0" />
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:schema>
And have a String in the following format:
<Address>
<Street></Street>
<Town></Town>
<Country></Country>
</Address>
Automatic tools do something similar, i.e. parse a WSDL and from the types section create for example JAXB classes that can be instances of the elements defined in schema.
Is there any library to do this?
UPDATE:
For example in Eclipse when creating an xml descriptor for a web application it presents a tree table with all the required elements for the users to fill in according to schema. How do they do it? I imagine they parse the xsds included in the jars
Any input is very welcome.
Thank you!
If its a WSDL file with which you want to generate Java classes, then Axis WSDL2Java (based on JAXB) can be used to get classes based on the schema defined in the WSDL.
JAXB also offers binding framework which you might want to look up.
http://publib.boulder.ibm.com/infocenter/wasinfo/v7r0/index.jsp?topic=/com.ibm.websphere.express.doc/info/exp/ae/twbs_jaxbschema2java.html
Above link should be useful.
oXygen has an XML instance generator that can generate a set of XML document samples based on a given XML Schema.
You can also invoke it from the commandline.