Convert xs:string to java.util.UUID in jaxb - java

In jaxb, how do you convert a string in xsd to java.util.UUID? Is there a built-in data type converter or do I have to create my own custom converter?

This is much easier to do if you start with Java classes and use JAXB annotations. However, to do this using schema you must use a custom bindings file. Here is an example:
Schema: (example.xsd)
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.com"
xmlns="http://www.example.com"
elementFormDefault="qualified">
<xs:simpleType name="uuid-type">
<xs:restriction base="xs:string">
<xs:pattern value=".*"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="example-type">
<xs:all>
<xs:element name="uuid" type="uuid-type"/>
</xs:all>
</xs:complexType>
<xs:element name="example" type="example-type"/>
</xs:schema>
Bindings: (bindings.xjb) (Note that for brevity in printMethod and parseMethod I assumed that the UuidConverter class was in the default package. These should be fully qualified in reality. So if UuidConverter where in package com.foo.bar then the values should be like com.foo.bar.UuidConverter.parse and com.foo.bar.UuidConverter.print
<!-- Modify the schema location to be a path or url -->
<jxb:bindings version="1.0"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
node="/xs:schema"
schemaLocation="example.xsd">
<!-- Modify this XPATH to suit your needs! -->
<jxb:bindings node="//xs:simpleType[#name='uuid-type']">
<jxb:javaType name=" java.util.UUID"
parseMethod="UuidConverter.parse"
printMethod="UuidConverter.print"/>
</jxb:bindings>
</jxb:bindings>
UuidConverter.java:
import java.util.UUID;
public class UuidConverter {
public static UUID parse(String xmlValue) {
return UUID.fromString(xmlValue);
}
public static String print(UUID value) {
return value.toString();
}
}
Sadly I can't point you to a good reference because its really not documented well. There are bits and pieces of how it all works spread out in blog posts. Took me a few hours to make this work the first time. :-/

Create a simple converter yourself:
UUID.fromString(String uuid);
http://docs.oracle.com/javase/6/docs/api/java/util/UUID.html

Related

How to custom xjc generated enum and field name?

Here is the question, our contract is XSD file. Lately we want it to support Json.But there is some tricky problem we have to solve. When I define xsd like this:
<xs:simpleType name="SomeType">
<xs:restriction base="xs:string">
<xs:enumeration value="SomeSelfDefineType" />
</xs:restriction>
</xs:simpleType>
The generated code is like this:
#XmlType(name = "SomeType")
#XmlEnum
public enum SomeType {
#XmlEnumValue("SomeSelfDefineType")
SOME_SELF_DEFINE_TYPE("SomeSelfDefineType")
}
When using XML, it's fine, because it reads the annotation info, but when we use Json, SomeSelfDefineType will be transfer into SOME_SELF_DEFINE_TYPE. Register a lot of custom Gson serializable/deserializable Interface to resovle this problem is not a good option for me.
I've checked out other's answers about how to custom some name of field or enum, but I really have a lot of enum definations. Is there any plugin or solutions for me to generate code like this:
#XmlType(name = "SomeType")
#XmlEnum
public enum SomeType {
#XmlEnumValue("SomeSelfDefineType")
SomeSelfDefineType("SomeSelfDefineType")
}
I am not familiar with JAXB or its plugins, could anyone give me some xjb settings or plugin for me to save this problem?
you can override the enum values using .xjb as below.
<?xml version="1.0"?>
<jxb:bindings version="2.1" xmlns:jxb="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" jxb:extensionBindingPrefixes="xjc">
<jxb:bindings schemaLocation="yours.xsd">
<jxb:bindings
node="//xs:simpleType[#name='SomeType']/xs:restriction/xs:enumeration[#value='SomeSelfDefineType']">
<jxb:typesafeEnumMember name="SomeSelfDefineType" />
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>

JAXB xjc:simple binding does not generate #XmlRootElement for base class

I am using JAXB 2.0. I have various elements and types defined in an XSD file. Here's an example:
<xs:element name="Person" type="Person" />
<xs:complexType name="Person">
<xs:attribute name="name" type="xs:string"/>
</xs:complexType>
<xs:element name="Musician" type="Musician"/>
<xs:complexType name="Musician">
<xs:complexContent>
<xs:extension base="Person">
<xs:attribute name="instrument" type="xs:string"/>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="People" type="People"/>
<xs:complexType name="People">
<xs:sequence>
<xs:element name="person" type="Person" minOccurs="0" maxOccurs="Unbounded/>
</xs:sequence>
</xs:complexType>
So as you can see from the above schema example, we have a Person, who has a name, and a Musician, who is also a Person (though this may be subject to some debate, but that's for another forum). There is also a People element, which is essentially a collection of Person types.
I have the following in a bindings file:
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.0"
xmlns:xjc= "http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:globalBindings optionalProperty="wrapper">
<xjc:simple/>
</jaxb:globalBindings>
My intended use of these objects is:
A Person may appear as a solitary Marshalled element, or may be a part of a People object
If a Person is part of a People object, then the xsi:type should indicate whether it's just a normal Person or a Musician.
So I need the generated Java classes to contain both an #XmlRootElement annotation as well as an #XmlType annotation. The xjc:simple binding creates both annotations for a Musician, but only creates the #XmlType for Person. So when I Marshall a Person object, all I get is:
<?xml version="1.0" encoding="UTF-8"?>
Whereas what I would like to see is:
<?xml version="1.0" encoding="UTF-8"?>
<Person name="John Doe"/>
For a People object, I want to see:
<?xml version="1.0" encoding="UTF-8"?>
<People>
<person name="John Doe" xsi:type="Person"/>
<person name="Keith Richards" xsi:type="Musician"/>
</People>
I have read about the simple binding with xjc, and it works with all the lowest levels in an inheritance hierarchy. However, the base classes end up without an #XmlRootElement annotation. For the use case I'm working on, it's imperative that base classes can be Marshalled as both a top-level element and as a member of other elements. Any suggestions would be welcome.
https://github.com/highsource/jaxb2-annotate-plugin could be used
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings xmlns:annox="http://annox.dev.java.net"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
jaxb:version="2.1"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc annox">
<jaxb:bindings node="//xs:complexType[#name='Person']">
<annox:annotate>
<annox:annotate annox:class="javax.xml.bind.annotation.XmlRootElement" name="person"/>
</annox:annotate>
</jaxb:bindings>
</jaxb:bindings>

Generating big enum classes with numbers in enum values JAXB, XJC

I'm trying to generate java classes using XJC and I have the following problem:
I'm trying to parse this schema which is a big enum type (bigger than default typesafeEnumMaxMembers). So I use following binding:
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings >
<jxb:globalBindings typesafeEnumMaxMembers="2000"/>
</jxb:bindings>
</jxb:bindings>
and then I call xjc with following line:
C:\Program Files\Java\jdk1.7.0_17\bin\xjc.exe -d C:\Users\buriak\out xml\dAllDocuments_v02.1.xsd xml/binding.xjb
this gives no errors, just that:
parsing a schema...
compiling a schema...
Then it ends without creating anything.
Smaller enum types are easily parsed same way, but bigger once are just ignored and if they are a part of some other type other xsd - they simply become a string:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:include schemaLocation="dAllDocuments_v02.1.xsd"/>
<xs:complexType name="tDocument">
<xs:annotation>
<xs:documentation>Документ - описание</xs:documentation>
</xs:annotation>
<xs:sequence>
<xs:element name="Code_Document" type="dAllDocuments">
<xs:annotation>
<xs:documentation>Код документа</xs:documentation>
</xs:annotation>
</xs:element>
...............
public class TDocument {
#XmlElement(name = "Code_Document", required = true)
protected String codeDocument;
...............
Using JAXB or XmlBeans results with nothing aswell.
Hope somebody knows what to do with that.
EDIT
After browsing without finding answers for long time I started to think, that it is not the size that is the problem.
I was right and as a result I found this - JAXB enumeration with numeric values
But XSD which I'm trying to parse is very big:
<xs:simpleType name="dAllDocuments">
<xs:restriction base="xs:string">
<xs:enumeration value="008001000000"/>
<xs:enumeration value="008001001000"/>
<xs:enumeration value="008001002000"/>
<xs:enumeration value="008001003000"/>
<xs:enumeration value="008001004000"/>
<xs:enumeration value="008001005000"/>
<xs:enumeration value="008001006000"/>
<xs:enumeration value="008001007000"/>
<xs:enumeration value="008001008000"/>
<xs:enumeration value="008001009000"/>
<xs:enumeration value="008001010000"/>....
And it keeps going for long more. There is absolutely no way I can write them all down in such a way:
<jxb:bindings node="//xs:simpleType[#name='dAllDocuments']/xs:restriction/xs:enumeration[#value='008001000000']">
<jxb:typesafeEnumMember name="OOBOOIOOOOOO"/>
</jxb:bindings>
Is there any way to make this work other than specifying name for each value manually?
I mean I can create a program which will make that kind of stuff using Strings, but is there any smart way?
Because actual XSD that I'm parsing is connected to multiple of such ENUM XSD and I need to parse them all.
After spending some more time on research I finally managed to get results which I was waiting for from xjc.
Here is binding file I was using, so that I don't get warning for enum type being too big and so that all those big enum types would have a generated name like VALUE_1, VALUE_2 etc.
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<!-- Raise theEnumMemberSizeCap limit -->
<jxb:bindings >
<jxb:globalBindings typesafeEnumMaxMembers="2000" typesafeEnumMemberName="generateName"/>
</jxb:bindings>
<jxb:bindings schemaLocation="STD_Region_Cadastr.xsd">
<jxb:bindings node="//xs:complexType[#name='tRight_Owner']">
<jxb:class name="tRight_Owner2"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
Also I'd like to mention that, since XSD files, which I was parsing, had a lot of cyrillic letters, here is xjc call I was using:
C:\Program Files\Java\jdk1.7.0_17\bin>xjc.exe -b xml/binding.xjb -d C:\Users\buriak\out xml\STD_Region_Cadastr.xsd -encoding UTF-8
That makes almost every cyrillic letter enterance show in java files correctly.
That's it.

JAXB - Generate schema. Complex Type custom attribute

I need to generate following schema from java class using JAXB.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xdb="http://xmlns.oracle.com/xdb">
<xs:element name="test" type="test"/>
<xs:complexType name="testName" xdb:SQLType="WEBY_TEST_NAME">
<xs:sequence>
<xs:element minOccurs="0" name="date" type="xs:dateTime"/>
<xs:element name="id" type="xs:int"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
How to add xdb:SQLType="WEBY_TEST_NAME" into complexType element using jaxb annotations ?
i done same try for generating the schema for different tags, but the names which include reserve words or else need to declare as
#XmlElement(name="class")
public String getClasss() {
return classs;
}
in pojo, so at time of coding it uses name which we provide, and in java program it uses the declared variables.
may be your declaration become
#XmlElement(name="xdb:SQLType")
public String getxdbSQLType() {
return xdbSQLType;
}

How can I generate a List inside another object in JAX-WS [duplicate]

Let's assume we defined a collection type in XSD as
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string"/>
<xs:element name="baz" type="xs:string"/>
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
When generating Java code from it using XJC the type roughly translates to
public class Foos {
public List<Foos.Foo> getFoos();
public static class Foo {
public String getBar();
public String getBaz();
}
}
As the collection type is part of some other type such as the root of the document, client code of the generated code looks somewhat like this
for(Foo foo : document.getFoos().getFoos())
{
//do something
}
Is there any way to make the client code less ugly without writing a wrapper manually?
It should look like this
for(Foo foo : document.getFoos())
{
//do something
}
Thanks
UPDATE
There are XJC plug-ins that people have written to generate the #XmlElementWrapper annotation instead of having the extra wrapper class.
https://github.com/dmak/jaxb-xew-plugin
ORIGINAL ANSWER
Alternative you could create the class with the #XmlElementWrapper yourself and have the generated classes reference it by doing the following:
Document
You could handcraft your own Document class to get the desired behaviour. You can get the behaviour you are looking for by leveraging the #XmlElementWrapper annotation to get a grouping element.
package forum18247182;
import java.util.*;
import javax.xml.bind.annotation.*;
public class Document {
private List<Foos.Foo> foos = new ArrayList<Foos.Foo>();
#XmlElementWrapper
#XmlElement(name="foo")
public List<Foos.Foo> getFoos() {
return foos;
}
}
XML Schema (schema.xsd)
Here is an expanded XML schema based on your fragment that I will use.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema
xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/schema"
xmlns="http://www.example.org/schema"
elementFormDefault="qualified">
<xs:element name="document" type="Document"/>
<xs:complexType name="Document">
<xs:sequence>
<xs:element name="foos" type="Foos"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Foos">
<xs:sequence>
<xs:element name="foo" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:all>
<xs:element name="bar" type="xs:string" />
<xs:element name="baz" type="xs:string" />
</xs:all>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:schema>
Leverage Existing Class When Generating Java Model from XML Schema (binding.xml)
We will use an external binding file to indicate that during class generation we wish to use our existing class for the complex type called Document.
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:bindings schemaLocation="schema.xsd">
<jxb:bindings node="//xs:complexType[#name='Document']">
<jxb:class ref="forum18247182.Document"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>
XJC Call
We will use the -b option to specify our binding file. We will also use the -p option to force the package name of the generated classes to match that of our Document class. We could also have made the package name of our Document class match the package name that results from generating classes from the XML schema.
xjc -b binding.xml -p forum18247182 schema.xsd
Demo Code
package forum18247182;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import forum18247182.Foos.Foo;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("forum18247182");
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource xml = new StreamSource("src/forum18247182/input.xml");
Document document = unmarshaller.unmarshal(xml, Document.class).getValue();
for(Foo foo : document.getFoos())
{
System.out.println(foo);
}
}
}
Output
Below is the output from running the demo code:
forum18247182.Foos$Foo#51f3336e
forum18247182.Foos$Foo#35b5a4ca

Categories

Resources