Jaxb: How to specify a default class for an XSD element - java

When generating Java classes from a XSD, how can I specify that for some specific node, a specific and already existent Java class should be used instead of trying to generate one?
Thank you very much.

You can use episode file to reference the existing classes. .episode files are just jaxb bindings file and has mappings between elements and java classes.
a) if those existing classes are also generated from (another) xsd. use below option to first create .episode file.
xjc -episode a.episode a.xsd
then use this a.episode that contains the mappings as input to the next xjc generation.
xjc b.xsd -extension -b a.episode
b) If you want to refer some random classes, then you may have to write your own episode file providing mapping between element and class reference like below.
sample.episode
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" if-exists="true" version="2.1">
<jaxb:bindings scd="x-schema::">
<jaxb:bindings scd="employee">
<jaxb:class ref="www1.example.Employee"/>
<jaxb:package name="www1.example" />
</jaxb:bindings>
</jaxb:bindings>
and use xjc b.xsd -extension -b sample.episode

You should use following binding customization
<bindings version="2.0" xmlns="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:annox="http://annox.dev.java.net" xmlns:namespace="http://jaxb2-commons.dev.java.net/namespace-prefix">
<bindings schemaLocation="../schema/yourSchema.xsd">
<bindings node="//xs:complexType[#name='Foo']">
<class ref="com.FooImpl"/>
</bindings>
</bindings>
</bindings>

Related

JAXB different datatypes parsing per namespace

I have got the JAXB bindings config file like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
version="2.1">
<jaxb:globalBindings generateElementProperty="false">
<jaxb:javaType name="java.util.Date" xmlType="xs:dateTime"
parseMethod="com.utils.EmptyDateTimeAdapter.parseDateTime"
printMethod="com.utils.EmptyDateTimeAdapter.printDateTimeWithZone"/>
<xjc:serializable uid="-1"/>
</jaxb:globalBindings>
</jaxb:bindings>
In xml above I declared that every wsdl dateTime element will be parsed by these methods.
My question is:
How can I change this JAXB config file to specify multiple parse methods for element type per package name or per wsdl?
<jaxws:bindings wsdlLocation="SampleService.wsdl"
xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
<jaxws:bindings node="wsdl:definitions/wsdl:types/xs:schema[#targetNamespace='http://example.com/service/SampleService/']">
<jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:javaType name="java.util.Date" xmlType="xs:date"
parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDateTime"
printMethod="org.apache.cxf.tools.common.DataTypeAdapter.printDateTime"/>
</jxb:globalBindings>
</jaxws:bindings>
</jaxws:bindings>
references :
JBoss Community Archive (Read Only)
JAXB bindings and xs:date to java.util.Date
Custom Jax-b bindings for xs:date to JAVA 8 java.time.LocalDate using Adapter

Import JAXB binding snippet into other binding file

For a certain xsd file, I have created a corresponding binding file that does some actions. In my case, annotating ComplexTypes with annotations. Finding the type is done with an XPath expression. The following example demonstrates this:
<jaxb:bindings
xmlns:xsd="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"
version="2.1"
xmlns:annox="http://annox.dev.java.net" jaxb:extensionBindingPrefixes="annox">
<jaxb:bindings schemaLocation="FirstSchema.xsd" node="/xsd:schema">
<jaxb:bindings node="//xsd:complexType//xsd:element[contains(#type, 'SomeType')]" required="false">
<annox:annotate target="field">#com.example.Type(type = "SomeType")</annox:annotate>
</jaxb:bindings>
//About 100 lines of bindings
</jaxb:bindings>
</jaxb:bindings>
There are more bindings defined than just the single I've shown, but my problem is that the bindings are now executed on the FirstSchema.xsd. I have a lot of other xsd files that require the exact same bindings. If I have over 10 more xsd files, I'd have to copy-paste these bindings every time for every schema.
Is it possible to "extract" the bindings and re-use them for every other xsd file like an import? It's kind of related to this comment/question. The advised solution there is using jaxb:schemaBindings/jaxb:package, but if I understand correctly the following snippet just generates the classes into another package and doesn't really solve the problem?
<jaxb:schemaBindings>
<jaxb:package name="com.example.package"/>
</jaxb:schemaBindings>
You'll be surprized, but old-school XML inclusion works with XJB files.
binding.xjb:
<!DOCTYPE jaxb:bindings [
<!ENTITY gh24type SYSTEM "gh24type.xml">
]>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="annox"
jaxb:version="2.1">
<jaxb:bindings schemaLocation="schema.xsd" node="/xsd:schema">
<!-- ... -->
&gh24type;
</jaxb:bindings>
</jaxb:bindings>
gh24type.xml:
<jaxb:bindings node="xsd:complexType[#name='gh24Type']">
<annox:annotate>#javax.annotation.Generated({"jaxb2-annotate-plugin"})</annox:annotate>
</jaxb:bindings>
So basically nothing spectacular, just entity-based XML inclusion. If you have exactly the same fragments, just include your entity several times for each of the schemas in question.
Alternatives would be writing a special plugin to simplify customization. Which might be a good idea anyway.

How to set #XmlType.namespace via JAXB External Bindings Customization file

I am using JAXB to process multiple XML documents.
My issue is that I cannot change the related xsd's and I don't want to amend the generated classes.
What I want to do is employ JAXB Binding customization files to achieve the desired result.
All I need to do is perform the equivalent of using the #XmlType.namespace annotation.
Is it possible to set the #XmlType.namespace annotation via JAXB Binding Customization files?
Disclaimer: I am the author of the jaxb2-annotate-plugin.
You can use the jaxb2-annotate-plugin to add arbitrary annotations to your schema-derived classes. #XmlType will be something like:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:annox="http://annox.dev.java.net"
jaxb:extensionBindingPrefixes="xjc annox"
version="2.1">
<jaxb:bindings schemaLocation="schema.xsd" node="/xs:schema">
<jaxb:bindings node="xs:complexType[#name='someType']">
<annox:annotateClass>#javax.xml.bind.annotation.XmlType(namespace="urn:test")</annox:annotateClass>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
If you already have an #XmlType there, the customized annotation will be "merged" into it.

XJC [ERROR] XPath evaluation of "//*[local-name()='schema']" results in empty target node

I am new to XJC. I'm attempting to consume a WSDL and generate binding classes with the XJC command and I got the following error:
C:\jaxb>xjc -verbose -b c:\jaxb\bindings-wsdl.xjb -wsdl c:\jaxb\BioMetScrnSvc.wsdl
parsing a schema...
[ERROR] XPath evaluation of "//*[local-name()='schema']" results in empty target node
line 8 of file:/C:/jaxb/bindings-wsdl.xjb
Failed to parse a schema.
My binding file is as follows:
<jaxb:bindings version="2.1"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:impl="http://www.openuri.org/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:intf="http://www.openuri.org/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<jaxb:bindings node="//*[local-name()='schema']">
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
</jaxb:bindings>
The WSDL provided to me is something as follows:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://www.openuri.org/"
xmlns:impl="http://www.openuri.org/"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:intf="http://www.openuri.org/">
<wsdl:types>
<schema elementFormDefault="qualified" targetNamespace="http://www.openuri.org/"
xmlns="http://www.w3.org/2001/XMLSchema">
...
From all the suggestions I have read from this site, I have included the necessary namespaces into the binding file to no avail. I have tested the Xpath and it is correct.
If I don't have a binding file, a JAXBElement is generated instead of a String. Understood it is because of minOccurs and nillable occurring together.
Regards,
Wes
I could not make bindings work with node. This might be a bug in XJC, I'll check/report to Oracle.
But SCD bindings do work! So here's a solution for you. Make a file namely "wsdl.xjb" and put following code in it. And place it on the same folder (for simplicity OR you can place anywhere then you will need to mention its path) where you have your example.wsdl file.
<jaxb:bindings
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0">
<jaxb:bindings scd="x-schema::tns" xmlns:tns="http://www.openuri.org/">
<jaxb:globalBindings generateElementProperty="false"/>
</jaxb:bindings>
</jaxb:bindings>
You'll need to include a -extension command switch and your final command will look like this:
xjc -extension -verbose -wsdl example.wsdl -b wsdl.xjb

JAXB Root Class Rename using binding.xml

I use the Dali plugin in Eclipse to generate Java classes using an xsd file, which essentially just invokes xjc on the schema file. I used the advice here to resolve naming conflicts by applying an XML binding file to the class generation. This worked well, but I tried to take it a step further by renaming the root element, and the result was that I lost the XmlRootElement annotation. I tried using annox to add the root element annotation back in, but I get this error: Unsupported binding namespace "http://annox.dev.java.net". Perhaps you meant "http://java.sun.com/xml/ns/jaxb/xjc"?
Here is my initial binding.xml file (without annox):
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
version="2.1">
<!-- Force all classes to be generated at the top level, this will potentially cause name conflicts -->
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="mySchema-1.0.0.xsd">
<!-- Rename the root element -->
<jaxb:bindings node="//xs:element[#name='MyRootClassNameIsReallyLong']/xs:complexType">
<jaxb:class name="ShorterName"/>
</jaxb:bindings>
<!-- Rename the Bar class to resolve a naming conflict -->
<jaxb:bindings node="//xs:element[#name='Foo']/xs:complexType/xs:sequence/xs:element[#name='Bar']/xs:complexType">
<jaxb:class name="FooBar"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
By the way, it's worth noting that the schema file came from a third party, so I have no interest in modifying it. Likewise, I'd rather not tamper with the generated Java files, so that's why I am interested in the binding xml approach.
Edit (9/11/2013) - Here is the binding XML with annox:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
xmlns:annox="http://annox.dev.java.net"
version="2.1">
<!-- Force all classes to be generated at the top level, this will potentially cause name conflicts -->
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="mySchema-1.0.0.xsd">
<!-- Rename the root element -->
<jaxb:bindings node="//xs:element[#name='MyRootClassNameIsReallyLong']/xs:complexType">
<jaxb:class name="ShorterName"/>
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="MyRootClassNameIsReallyLong" />
</annox:annotate>
</jaxb:bindings>
<!-- Rename the Bar class to resolve a naming conflict -->
<jaxb:bindings node="//xs:element[#name='Foo']/xs:complexType/xs:sequence/xs:element[#name='Bar']/xs:complexType">
<jaxb:class name="FooBar"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
Annox is an XJC add on, so you in addition to declaring the namespace prefx (xmlns:annox="http://annox.dev.java.net), you also need to declare it as an extensionBindingPrefix.
Your openning tag should then look like this:
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/jaxb
http://java.sun.com/xml/ns/jaxb/bindingschema_2_0.xsd"
jaxb:extensionBindingPrefix="annox"
version="2.1">

Categories

Resources