I have the following data type defined in a wsdl:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions name="myService" targetNamespace="http://example.com" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://example.com" 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="example.com" targetNamespace="example.com" version="1.0">
<xs:simpleType name="MyEnum">
<xs:restriction base="xs:string">
<xs:enumeration value="one"/>
<xs:enumeration value="two"/>
</xs:restriction>
</xs:simpleType>
<!-- SNIP other data types -->
</xs:schema>
</wsdl:types>
</wsdl:definitions>
I want MyEnum to fall into its own package. So, I used a jaxws binding file, and used XPATH to traverse the schema and jaxb bindings to set the package, as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxws:bindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://java.sun.com/xml/ns/jaxws">
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema[#targetNamespace='example.com']">
<jxb:schemaBindings>
<jxb:package name="abra.ca.dabra" /> <!-- this works, and changes package of all classes in the namespace-->
</jxb:schemaBindings>
<jxb:bindings node="//xs:simpleType[#name='MyEnum']">
<jxb:package name="a.b.c"/> <!-- this does not work -->
</jxb:bindings>
</jaxws:bindings>
<!-- SNIP - other functional jaxws bindings -->
</jaxws:bindings>
Now, the path set in schemaBindings takes - and puts all data types from that schema/targetnamespace into package abra.ca.dabra. However, I can't seem to set the package of just MyEnum - which is what I want.
I use cxf's wsdl2java to provide the bindings file. Am I missing something?
I would try it with something likethis:
<jaxws:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
<jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
<!-- set default package structure -->
<jaxws:package name="abra.ca.dabra" />
<!-- set package structure for complex schema types -->
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema/xs:simpleType[#name='MyEnum']">
<jaxb:schemaBindings>
<jaxb:package name="a.b.c" />
</jaxb:schemaBindings>
</jaxws:bindings>
To be more precise you should make the whole wsdl available
Hope this helps ...
Have you tried to add a second schema to the WSDL that only contains MyEnum, with a different namespace? The original schema definition should then import that type from the new namespace.
Related
There are a lot of answers related to this but for some reason, I am still confused and unable to get the Java objects for my XSD.
I am trying to create the Java objects from XSD using the XJC JAXB but when I run the XJC command it results in the error
[ERROR] Property "Value" is already defined. Use <jaxb:property> to resolve this conflict.
Hence, based on my research I found that I need to write the binding file so I wrote the binding file but still I am getting the same error which means that I am messing up something in the binding file. As I am unable to make it work even after a lot of try I thought of posting it and getting some solution.
Following is my XSD which is failing as per the XJC command failure message foo.xsd:
<xsd:complexType name="DocumentExtensionType">
<xsd:sequence>
<xsd:any namespace="##local" processContents="lax" maxOccurs="unbounded"/>
</xsd:sequence>
<xsd:anyAttribute processContents="lax"/>
</xsd:complexType>
Following are the JAXB bindings I tried and executed but still results in an error: foo.xjb
<?xml version="1.0" encoding="UTF-8"?>
<jxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jxb:bindings schemaLocation="foo.xsd">
<jxb:bindings
node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence/xsd:choice/xsd:any[#namespace='http://checklists.nist.gov/sccf/0.1']">
<jxb:property name="any2" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Following is another JAXB binding I've tried: foo.xjb
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation="foo.xsd" version="1.0">
<schemaBindings>
<package name="com.track.doc"/>
</schemaBindings>
<bindings node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence/xsd:any[#namespace='']">
<property name="any2"/>
</bindings>
</bindings>
</bindings>
Following is the command I am running in my terminal:
xjc -p "com.track.doc" -d "/Users/batman/Downloads/XSD" -b foo.xjb foo.xsd
Can someone please guide me what am I doing mistake?
After trying a lot of things finally this code worked for me. However, I posted only a chunk of XSD which was failing when I run this for this small chunk then it works but when I run for the whole XSD it still fails. Not completely sure what's going wrong.
<?xml version="1.0" encoding="UTF-8"?>
<bindings xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
version="2.1">
<bindings schemaLocation="foo.xsd" version="1.0">
<schemaBindings>
<package name="com.track.doc"/>
</schemaBindings>
<bindings node="//xsd:complexType[#name='DocumentExtensionType']/xsd:sequence">
<property name="seq1"/>
</bindings>
</bindings>
</bindings>
One more issue that I noticed in my XSD. If incase you are also having the similar issue then following might help:
Make sure that your XSD file which you are passing as input does not have any field with the name as value.
In my case I had a field with name = "value".
<xsd:attribute type="xsd:float" name="value" use="optional"/>
I replaced it with
<xsd:attribute type="xsd:float" name="floatValue" use="optional"/>
I'm currently working on a xsd which uses the following contruct:
<xs:attribute name="listVersionID" type="xs:normalizedString" use="required" fixed="1.0">
While not problematic per se, it is rather annoying to work with, since the fixed-value of this definition increases between releases of the xsd spec, and we need to modify the values in a seperate constants-class to keep them valid, although little if anything of interest in the xsd has changed. The xsd is maintained elsewhere, so just changing it is no option.
Thus I was asking myself wether there is a jaxb-plugin or similar to turn fixed-value attributes into constants ala
#XmlAttribute(name = "listVersionID")
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
#XmlSchemaType(name = "normalizedString")
protected final String listVersionID = "1.0";
instead of just
#XmlAttribute(name = "listVersionID")
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
#XmlSchemaType(name = "normalizedString")
protected String listVersionID;
which must be populated manually.
Does anyone know of such?
If you don't want to modify your schema, another option is to use an external binding file:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jaxb:bindings schemaLocation="yourschema.xsd" node="/xs:schema">
<jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
</jaxb:bindings>
</jaxb:bindings>
It is equivalent to what proposes #jmattheis in his answer.
Yes it is possible through custom jaxb bindings, which can be added as file at the codegen.
In the jaxb bindings, there is the fixedAttributeAsConstantProperty-attribute. Setting this to true, instructs the code generator to generate attributes with the fixed attribute as java-constants.
There are 2 options for this:
1. Through global bindings:
which then make all attributes with fixed values to constants
<schema targetNamespace="http://stackoverflow.com/example"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">
<annotation>
<appinfo>
<jaxb:globalBindings fixedAttributeAsConstantProperty="true" />
</appinfo>
</annotation>
...
</schema>
2. Through local mappings:
Which only defines the fixedAttributeAsConstantProperty property on a specific attribute.
<schema targetNamespace="http://stackoverflow.com/example"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">
<complexType name="example">
<attribute name="someconstant" type="xsd:int" fixed="42">
<annotation>
<appinfo>
<jaxb:property fixedAttributeAsConstantProperty="true" />
</appinfo>
</annotation>
</attribute>
</complexType>
...
</schema>
Both examples should result in:
#XmlRootElement(name = "example")
public class Example {
#XmlAttribute
public final static int SOMECONSTANT = 42;
}
(I've already googled it and done a search here and found no answer, maybe I'm using the wrong keywords...)
To make it simple, I have two schemas:
a.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://foo.bar/something"
targetNamespace="http://foo.bar/something"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="TFoo">
<xs:attribute name="version" type="xs:string" />
</xs:complexType>
</xs:schema>
b.xsd:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="http://foo.bar/something"
targetNamespace="http://foo.bar/something"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xs:complexType name="TFoo">
<xs:attribute name="version" type="xs:string" />
<xs:attribute name="dateTime" type="xs:dateTime" />
</xs:complexType>
</xs:schema>
Both have the same targetNamespace and a complexType named TFoo.
I have an external binding to change the generated class name of a.xsd from TFoo to TFooA:
a-binding.xml:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="2.1">
<jxb:bindings schemaLocation="a.xsd">
<jxb:bindings node="//xs:complexType[#name='TFoo']">
<jxb:class name="TFooA"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
which works if I compile the a.xsd alone:
$ xjc -b a-binding.xml a.xsd
parsing a schema...
compiling a schema...
bar/foo/something/ObjectFactory.java
bar/foo/something/TFooA.java
bar/foo/something/package-info.java
(look how I got TFooA.java)
But, if I try to compile both schemas at once, I get:
$ xjc -b a-binding.xml a.xsd b.xsd
parsing a schema...
[ERROR] 'TFoo' is already defined
line 13 of file:/home/scherrer/tmp/PL_008f/b.xsd
[ERROR] (related to above error) the first definition appears here
line 9 of file:/home/scherrer/tmp/PL_008f/a.xsd
Failed to parse a schema.
I know TFoo is defined twice, and that's why I have the external binding to solve the conflict.
Obs. both schemas are fictitious, written to exemplify the problem, the real ones (many) are provided by a third party and I can't change them.
Can anyone tell me if this is some kind of xjc restriction (it's not listed here) or shouldn't work at all? Or maybe a bug?
Thanks in advance.
Having 2 different schema documents defining the same name space (and even worse - same element) is equivalent to having 2 different jars contain the same package and same class(es) in the package. This isn't a limitation of jaxb per se - it is a violation of what schema name spaces mean.
In short, you cannot process these schemas together.
The generator cannot create classes because it does not know what to reference. The failure occurs before your attempt to rename. It occurs when reading the schemas.
What you could do is process the schemas separately and change the java package names which are used. This avoids naming conflict in the java package space and basically treats the schema docs as completely separate entities with no references to each other. This can be done by defining the package name to use in the binding:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
version="2.1">
<jxb:bindings schemaLocation="a.xsd" node="/xs:schema">
<jxb:schemaBindings>
<jxb:package name="com.foo.a"></jxb:package>
</jxb:schemaBindings>
</jxb:bindings>
</jxb:bindings>
I think you found a limitation of data binding. Try data projection instead (Disclosure: I'm affiliated with that project).
Your schema b.xsd looks just like an extension to the a.xsd. You can create a projection interface suitable for b.xsd and use it with any documents that fit either a.xsd or b.xsd.
If, for example orders.wsdl imports Orders.xsd, how can it be configured using static-wsdl
<sws:static-wsdl id="orders" location="/WEB-INF/wsdl/orders.wsdl"/>
such that Orders.xsd can be viewed in the browser like http://host/context/Orders.xsd
Dynamic wsdl supports it.
<sws:dynamic-wsdl id="orders"
portTypeName="Orders"
locationUri="http://localhost:8080/ordersService/">
<sws:xsd location="/WEB-INF/xsd/Orders.xsd"/>
</sws:dynamic-wsdl>
But static-wsdl doesn't have the sws:xsd property.
There is no namspace support but you can do this -
<bean id="Orders" class="org.springframework.xml.xsd.SimpleXsdSchema">
<property name="xsd" value="classpath:/Orders.xsd" />
</bean>
This will resolve the referenced xsd in your wsdl file -
<wsdl:types>
<xsd:schema elementFormDefault="qualified">
<xsd:import namespace="..." schemaLocation="Orders.xsd"></xsd:import>
</xsd:schema>
</wsdl:types>
or you can tyt with that
<wsdl:types>
<xs:schema targetNamespace="...."
elementFormDefault="qualified">
<xs:include schemaLocation="xsd/Order.xsd"/>
</xs:schema>
I need to generate many classes from my XML Schema (XSD) in a package (.jar).
How can I configure these classes to be serializable?
(I'm using Eclipse and JAX-B)
If you are using XJC, I recomend you to read this reference: JavaTM Architecture for XML Binding: JAXB RI Vendor Extensions Customizations :
You have to add in your schema aditional namespaces definition to add xjc aditional markup:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
jaxb:version="1.0">
Then, including an <xjc:serializable> node within <jaxb:globalBindings>:
<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings generateIsSetMethod="true">
<xjc:serializable uid="12343"/>
</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>
This will cause that all the concrete classes implement the Serializable interface. Also, you can define the UUID value of the resulting classes (that's an optional attribute).
I've found
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc"
jaxb:version="1.0"
>
<!-- FORCE ALL CLASSES IMPLEMENTS SERIALIZABLE -->
<annotation>
<appinfo>
<jaxb:globalBindings generateIsSetMethod="true">
<xjc:serializable uid="1"/>
</jaxb:globalBindings>
</appinfo>
</annotation>
....
</schema>