What says JAXB specification: XmlAnyAttribute collision with explicit mapped attribute - java

Scenario
Consider the following class (imports omitted):
#XmlAccessorType(XmlAccessType.NONE)
#XmlRootElement
public class Test {
#XmlAttribute
public int id;
#XmlAnyAttribute
public Map<QName,String> any;
}
What is the behaviour when I do the following:
Test t = new Test();
t.id = 5;
t.any = new HashMap<QName,String>();
t.any.put(new QName("id"), "10");
JAXBContext jc = JAXBContext.newInstance(Test.class);
Marshaller m = jc.createMarshaller();
m.setEventHandler(myEventHandler);
m.marshal(t, System.out);
The obvious problem:
An XML element should be generated for the instance of Test. But the obvious problem is: With which attributes? <test id="5"/>? Or <test id="10"/>? Or an invalid XML <test id="5" id="10"/>?
Please answer:
Will the marshalling be successful (or will there be an exception?)
Will handleEvent(ValidationEvent) of myEventHandler be called? If yes, with what?
What can be expected on System.out, i.e. what is the output XML? (If 1. is answered positive)
Will a (standard conforming) JAXB marshaller always generate well-formed XML? (No schema involved)
Is the behaviour of the reference implementation in the standard library, which outputs <test id="5" id="10"/> and reports absolutely no error, conforming to the JAXB specification?
Please base your answer on solid fundaments:
Of course one can just try it out. But one should be able to predict the exact behaviour with studying the Javadoc and JAXB specification documents. So, if possible, back your answer with citing the relevant part of a documentation source.

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Where to Find the JAXB Specification
For reference the JAXB (JSR-222) specification can be downloaded from the following location: https://jcp.org/en/jsr/detail?id=222
Answers to Your Questions
Will the marshalling be successful (or will there be an exception?)
The JAXB 2.2 specification does not cover what will happen for this use case. Only the unmarshalling use case is defined (see B.3.6.2).
Will handleEvent(ValidationEvent) of myEventHandler be called? If yes, with what?
There is nothing in the JAXB 2.2 spec requiring this.
What can be expected on System.out, i.e. what is the output XML? (If 1. is answered positive)
The behaviour for this is undefined. As you pointed out both the reference and MOXy implementations of JAXB will output two attributes with the same name.
Will a (standard conforming) JAXB marshaller always generate well-formed XML? (No schema involved)
You have identified one case where this is not true.
Is the behaviour of the reference implementation in the standard library, which outputs and reports absolutely no error, conforming to the JAXB specification?
The marshalling behviour is undefined in the specification, therefore the behaviour of the reference (and MOXy) implementations of JAXB don't conflict with the specification.
Where to Report Issues
A seriously developed software should, IMHO, leave no doubts about
behaviour in edge cases.
You can raise issues like this either through Jira or the mailing lists.
https://java.net/jira/browse/JAXB/ (Issue Tracker)
https://java.net/projects/jaxb/lists/ (Mailing Lists)

Related

JAXB - filter fields in fully annotated class

i have a fully annotated class and multiple xsds(each with a different set of fields)
and i wish to marshal according to the different xsds using the same class.
i would like to be able to control the marshaling/unmarshaling process and filter out some fields according to the xsd.
btw i am using cxf.
thanks,
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
If you use MOXy as your JAXB provider then you could have the model mapped to one XML schema via the standard annotations, and then adjust the mappings to match the other XML schemas using MOXy's external mapping document (see: http://blog.bdoughan.com/2010/12/extending-jaxb-representing-annotations.html).
JAXBContext #1 - Created based on annotations to match schema #1
JAXBContext #2 - Created based on annotations and mapping file #1 to match schema #2
JAXBContext #3 - Created based on annotations and mapping file #2 to match schema #3
The mapping file also allows you to have the annotations completely ignored if one of your schemas bares little resemblance to the others.
http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html

JAXB inheritance issue - namespace corruption

We're facing an issue when marshalling an object to xml with JAXB. In our code example (https://github.com/fbe/JaxbIssueTracker, simple maven project, test-case demonstrates what's going wrong) we have three types:
parent
hijacked
concrete
XSDs can be found here: github
The parent type is abstract, concrete extends the parent, parent references the hijacked type in a sequence. From these xsd-files the JAVA files are being generated by JAXB (xjc) without any warn- or error-messages.
When marshalling a concrete type the following xml-output is being generated by JAXB:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ns3:concreteType xmlns:ns2="http://www.felixbecker.name/parent" xmlns="http://www.felixbecker.name/hijacked" xmlns:ns3="http://www.felixbecker.name/concrete">
<ns2:hijacked>
<value>foobar</value>
</ns2:hijacked>
</ns3:concreteType>
As you can see the hijacked-type is falsely using the ns2-prefix which refers to the namespace of the parent type - but instead it should use the default namespace which refers to the hijacked namespace.
JAXB is not able to unmarshal this generated xml although it is generated by itself with activated schema validation.
What is going wrong here? Is the xml-schema broken? Or is JAXB not able to deal with inheritance correctly?
Removing the abstract-attribute from the parent.xsd did not have any effect on the faced issue.
Any help would be highly appreciated! :-)
Used versions (both broken):
JAXB from JDK 1.6
JAXB-RI 2.2.5
Regards,
fbe & ollinux
In your example, the hijacked element is actually defined in the parent schema and so gets placed in the "parent" namespace. This means the namespaces of the marshalled document are correct. If jaxb can unmarshal the document it itself marshalled then this sounds like a bug to me.
To get the hijacked element in the correct namespace you could move the element declaration to the hijacked schema and use
<element ref="hijacked:hijacked"/>
in the parent schema.

Spring JAXB - Unmarshalling an XML document with schema validation

I am trying to work out how to unmarshall and XML document to a Java document.
The top of the xml document looks like this
<xs:myData xmlns:xs="http://www.example.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.com example.xsd ">
There is a schema file whose top section looks like this:
<schema targetNamespace="http://www.example.com"
elementFormDefault="qualified"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xs="http://www.example.com">
I would like to unmarshall the xml document using Spring/JaxB and eventually convert it to a JPA object. I am not sure how to go about so i looked for examples on google and came up with this http://thoughtforge.net/610/marshalling-xml-with-spring-ws-and-jaxb/
I understand most of it except how or where the schema is used.
I have seen other examples where the schema is explicitly specified, i.e.
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
unmarshaller.setSchema(sysConfigSchema);
RootElement root = (RootElement)unmarshaller.unmarshal(
new File("example1.xml"));
How is the schema shown in the first link used to validate the xml document?
Are there any disadvantages to using Spring's jaxb2Marshaller as opposed to direct use of JAXB?
What is the effect of having the namespace next to the XmlElement annotation? (See the Person class)
I would appreciate any more examples showing Spring/REST with unmarshalling with schema validation.
Thanks
As far as I know JAXB does not parse xsi attribute to dereference XSD, load it and use for validation. Perhaps that was done to disable automatic validation, otherwise it would be problematic to switch it off :)
Spring Jaxb2Marshaller was obviously added to implement the same interface org.springframework.oxm.Marshaller (which is implemented also by CastorMarshaller, JibxMarshaller, ...). It is very powerful and allows you to tune JAXBContext in very flexible way (I can't imagine the scenario when provided API is not enough). From pattern point of new Jaxb2Marshaller is a builder, so it does not add anything to core JAXB functionality. But there are some evident advantages. For example, schema loading is very simple. In the article the Spring context refers the person.xsd (<property name="schema" value="classpath:schema/person.xsd"/>) which one need to put into resources explicitly. Then JAXB marshaller/unmarshaller will use this schema to validate XML when XML is generated/loaded.
#XmlElement(..., namepsace="xxx") will automatically generate this XML element with a specified namespace. It's rare case if somebody does not use namespaces. I would say writing XSD without namespaces is not normal, as you want to avoid the element name collision.
Using JAXB with RestTemplate is very simple. You need to be sure that JAXB runtime is in your classpath (JDK 6 already has it) and your bean is annotated with #XmlRootElement. Then just use Person person = restTemplate.getForObject(restServiceUrl, Person.class),

How to map an XML to Java objects by XPaths?

Given the XML example:
<fooRoot>
<bar>
<lol>LOLOLOLOL</lol>
</bar>
<noob>
<boon>
<thisIsIt></thisIsIt>
</boon>
</noob>
</fooRoot>
Which should be mapped to:
class MyFoo {
String lol;
String thisIsIt;
Object somethingUnrelated;
}
Constraints:
XML should not be transformed, it is provided as a parsed org.w3c.dom.Document object.
Class does not and will not map 1:1 to the XML.
I'm only interested to map specific paths of the XML to specific fields of the object.
My dream solution would look like:
#XmlMapped
class MyFoo {
#XmlElement("/fooRoot/bar/lol")
String lol;
#XmlElement("/noob/boon/thisIsIt")
String thisIsIt;
#XmlIgnore
Object somethingUnrelated;
}
Does anything likewise exists? What I've found either required a strict 1:1 mapping (e.g. JMX, JAXB) or manual iteration over all fields (e.g. SAX, Commons Digester.)
JiBX binding definitions come the nearest to what I'm lokking for. However, this tool is ment to marshall/unmarshall complete hierarchy of Java objects. I only would like to extract parts of an XML document into an existing Java bean at runtime.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
You can do this with MOXy:
#XmlRootElement(name="fooRoot")
class MyFoo {
#XmlPath("bar/lol/text()")
String lol;
#XmlElement("noob/boon/thisIsIt/text()")
String thisIsIt;
#XmlTransient
Object somethingUnrelated;
}
For More Information
http://blog.bdoughan.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html
Try XStream. It's super easy. Hope it helps! I don't have time now for a full example :)
One option could be write a custom annotation which will take the XPath expression as input and do the bindings.

Is there a library to convert Java POJOs to and from JSON and XML? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 8 years ago.
Improve this question
I have an object graph that I would like to convert to and from JSON and XML, for the purposes of creating a REST-style API. It strikes me that someone must have done this already, but a quick search using Google and Stack Overflow reveals nothing.
Does anyone know of a suitable (Apache or equivalent license preferred) library to do this?
GSON from google : http://code.google.com/p/google-gson/,
or
Jackson the library used in spring :https://github.com/FasterXML/jackson
and I would concur with others suggesting jaxb for XML to pojo, well supported lots of tools : its the standard.
For POJO to XML I suggest using JAXB (there are other libraries as well, such as XStream for example, but JAXB is standardized).
For JSON I don't know anything, but if you want to implement a RESTful API, you might be interested in JSR-311 which defines a server-side API for RESTful APIs and Jersey, which is its reference implementation.
Use Xstream http://x-stream.github.io/ for xml and JSON http://www.json.org/java/ for JSON. I dont think there is one library that does both.
Or write a wrapper which delegates to XStream renderers/JSON renderers depending on what you want.
I think you may be looking for something similar to what is here: JSON.org Java section
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) supports mapping a single object model to both XML and JSON with the same metadata:
http://blog.bdoughan.com/2011/08/binding-to-json-xml-geocode-example.html
License Information
http://wiki.eclipse.org/EclipseLink/FAQ/General#How_is_EclipseLink_Licensed.3F
DOMAIN MODEL
Below is the domain model we will use for this example. For this example I'm just using the standard JAXB (JSR-222) annotations which have are available in the JDK/JRE since Java SE 6.
Customer
package forum658936;
import java.util.List;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
String firstName;
#XmlElement(nillable=true)
String lastName;
#XmlElement(name="phone-number")
List<PhoneNumber> phoneNumbers;
}
PhoneNumber
package forum658936;
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
public class PhoneNumber {
#XmlAttribute
int id;
#XmlValue
String number;
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
XML
input.xml
This is the XML that our demo code will read in and convert to domain objects.
<?xml version="1.0" encoding="UTF-8"?>
<customer xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<firstName>Jane</firstName>
<lastName xsi:nil="true"/>
<phone-number id="123">555-1234</phone-number>
</customer>
Things to note about the XML:
The xsi:nil attribute is used to indicate that the lastName is null.
The phone-number element is a complex type with simple content (see: http://blog.bdoughan.com/2011/06/jaxb-and-complex-types-with-simple.html).
JSON
Output
Below is the JSON that was output by running the demo code.
{
"firstName" : "Jane",
"lastName" : null,
"phone-number" : [ {
"id" : 123,
"value" : "555-1234"
} ]
}
Things to note about the JSON:
The null value is used to represent that the lastName is null. There is no presence of the xsi:nil attribute.
The collect of phone numbers is of size 1 and is correctly bound by square brackets. Many libraries incorrectly treat collections of size 1 as JSON objects.
The property of type int was correctly marshalled without quotes.
In the XML representation id was an attribute, but in the JSON representation there is not need for it to be specially represented.
DEMO CODE
In the demo code below we will convert an XML document to objects, and then convert those same instances to JSON.
Demo
MOXy doesn't just interpret JAXB annotations it is a JAXB implementation so the standard JAXB runtime APIs are used. JSON binding is enabled by specifying MOXy specify properties on the Marshaller.
package forum658936;
import java.io.File;
import javax.xml.bind.*;
import org.eclipse.persistence.jaxb.MarshallerProperties;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum658936/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.marshal(customer, System.out);
}
}
Json-lib is licensed under the Apache 2.0 license.
It can also transform JSON objects to XML, but you'd need to convert your POJOs to JSON through it first.
Personally I would tackle the two separately; and to convert JSON<->XML via JSON<-> Pojo <-> XML.
With that: Java<->POJO with JAXB (http://jaxb.dev.java.net; also bundled with JDK 1.6) with annotations (XStream is ok too); and for JSON, Jackson's ObjectMapper (http://jackson.codehaus.org/Tutorial). Works nicely with Jersey, and I am use it myself (current Jersey version does not bundle full Pojo data binding by default, but will in near future)
I would actually not use any of xml libs to produce "json": XStream and JAXB/Jettison can produce kind of JSON, but it uses ugly conventions that are rather non-intuitive.
EDIT (18-Jul-2011): Jackson actually has an extension called "jackson-xml-databind" that can read/write XML, similar to JAXB. So it can be used for both JSON and XML, to/from POJOs.
Last I saw on the website, XStream will do both. It supports XML and JSON as serialization targets.
There are almost literally hundreds. My favorites are GSON for POJO <-> JSON and castor-xml for POJO <-> XML.
As a bonus both are licensed under Apache License 2.0 style licenses.
Have a look at Genson library http://code.google.com/p/genson/wiki/GettingStarted.
It is easy to use, performant and was designed with extension in mind.
Actually it does json/java conversion but not xml. However xml support may be added in a future version.
I'm using it in web applications and REST web services in jersey, but also in some cases to store objects in their json form into a database.
Ah and it's under Apache 2.0 license.

Categories

Resources