Team lead for the TopLink/EclipseLink JAXB (MOXy) & SDO implementations, and the Oracle representative on those specifications.
Team lead for the TopLink/EclipseLink JAXB (MOXy) & SDO implementations, and the Oracle representative on those specifications.
import javax.xml.bind.JAXBElement;While useful JAXBElement can get in the way if you want to use your domain model with something like JPA (which doesn't know what to do with it). In this post I will demonstrate how you can eliminate the need for JAXBElement through the use of an XmlAdapter.
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
@XmlElementRefs({
@XmlElementRef(name = "billing-address"),
@XmlElementRef(name = "shipping-address")
})
private JAXBElement<Address> address;
}
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You could leverage MOXy's @XmlPath extension for this use case:
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "A")
@XmlAccessorType(XmlAccessType.FIELD)
public class A {
@XmlPath(".")
private B b;
}
For More Information
The XML you are looking to produce has what is called mixed content. Mixed content is when a element (hostName) has both text (local.yahoo.com) and element (parameters) content.
<XmlSource URL="http://local.yahoo.com/rss/restaurants?csz=Cairo,+CA">
<hostName>local.yahoo.com
<parameters>
...
</parameters>
</hostName>
</XmlSource>
This can be mapped with JAXB with the @XmlMixed annotation where the text and element content go into one list, but this probably isn't what you want. How about something like this instead?
<XmlSource URL="http://local.yahoo.com/rss/restaurants?csz=Cairo,+CA">
<host name="local.yahoo.com">
<parameters>
...
</parameters>
</host>
</XmlSource>
UPDATE
yes, y're right, my bad, i was looking for that form not the one i wrote. how can i make it?
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
You could leverage MOXy's @XmlPath extension for this use case:
import java.net.URL;
import java.util.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlPath;
@XmlRootElement(name = "XmlSource")
@XmlType(propOrder={"parameters", "urlp", "path"})
@XmlAccessorType(XmlAccessType.FIELD)
public class XmlConf {
@XmlAttribute(name="URL")
private URL url;
private List<String> path = new ArrayList<String>();
@XmlElement(name="urlPath")
private String urlp;
@XmlPath("hostName/parameters")
private Map<String, String> parameters;
@XmlPath("hostName/@name")
private String host;
}
For More Information
The solution is what you have posted in your question.
@XmlElement(nillable = true, required = true)
@Override
public Boolean getRawValue() {
return super.getRawValue();
}
@Override
public void setRawValue(final Boolean rawValue) {
super.setRawValue(rawValue);
}
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
Your interpretation of the JAXB spec is correct. I have confirmed the bug you are seeing with the JAXB implementation included in JDK 1.7.0_21 for the Mac. Could you enter an issue using the following link:
If you use EclipseLink MOXy as your JAXB provider (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html) then you get the correct output:
<?xml version="1.0" encoding="UTF-8"?>
<k>
<myMap>
<entry>
<key>cat</key>
<value>meows</value>
</entry>
<entry>
<key>dog</key>
<value>barks</value>
</entry>
</myMap>
<myMap2>
<entry>
<key>bird</key>
<value>tweets</value>
</entry>
<entry>
<key>snake</key>
<value>rattles</value>
</entry>
</myMap2>
<myList>first</myList>
<myList>second</myList>
</k>
JAXB (JSR-222) implementations require a get method with no parameters. You could specify @XmlAccessorType(XmlAccessType.FIELD) so that JAXB deals directly with the field instead.
When I run the code exactly as you have it in your question I get the following, is this not what you are getting as output?
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root>
<someClassList>
<result>
<ae>urn:uuid:b34f3b9e-1086-4dfc-852f-4bc55b5d5a6e</ae>
<status>something</status>
</result>
</someClassList>
<entityImplList>
<entityImpl>
<id>urn:uuid:b34f3b9e-1086-4dfc-852f-4bc55b5d5a6e</id>
<variabel_l>1</variabel_l>
<variabel_2>2</variabel_2>
<variabel_3>3</variabel_3>
<variabel_4>4</variabel_4>
</entityImpl>
</entityImplList>
</root>
UPDATE
Based on investigation by myself and Ørjan Johansen there appears to be a bug related to this use case in the implementation of JAXB included in JDK 1.7.0_21 for Windows. The use case works correctly in JDK 1.7.0_21 for the Mac, and jdk1.6.0_45 for Windows. This use case also works correctly when EclipseLink MOXy is used as the JAXB (JSR-222) provider.
There are a couple of ways to support this use case:
Option #1 - @XmlTransient
You can use the @XmlTransient annotation to prevent a field/property from being marshalled or unmarshalled.
Option #2 - @XmlAccessorType(XmlAccessType.NONE)
You can annotated the class with @XmlAccessorType(XmlAccessType.NONE) so that only annotated fields/properties will be marshalled/unmarshalled.
For More Information
A CDATA section starts with <![CDATA[ and ends with ]>, so your XML document should be:
<rep>
<text type="full"><![CDATA[Demo, <a href="http://www.google.com" target="_blank">Search</a> thank you]]></text>
</rep>
Example Code
import java.io.File;
import javax.xml.bind.*;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Demo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xsr = new File("src/forum16684040/input.xml");
Demo demo = (Demo) unmarshaller.unmarshal(xsr);
System.out.println(demo);
}
}
Output
[text=Demo, <a href="http://www.google.com" target="_blank">Search</a> thank you]
UPDATE
thanks, But this case i can't able to edit the XML, bcoz i get XML from third party API. is there any way to get the result, which i except.
You can use @XmlAnyElement and specify a DomHandler to keep the DOM content as a String. Below is a link to an answer that contains a full example:
You can use EclipseLink JAXB (MOXy)'s external binding file to provide metadata for classes that cannot be modified:
oxm.xml
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="com.example.foo">
<java-types>
<java-type name="First">
<java-attributes>
<xml-element java-attribute="date">
<xml-java-type-adapter value="com.example.foo.DateAdapter"/>
</xml-element>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
Demo
Then you can bootstrap your JAXBContext using a property specifying the metadata location:
import java.util.*;
import javax.xml.bind.JAXBContext;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.OXM_METADATA_SOURCE, "com/example/foo/oxm.xml");
JAXBContext jc = JAXBContext.newInstance(new Class[] {First.class, Second.class}, properties);
}
}
For More Information
Note: I am the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JPA offers extensible entities can be added via its XML mapping file. The virtual properties are accessed via generic get/set methods that take a property name.
@Entity
@VirtualAccessMethods
public class Customer{
// Real Properties
...
// Code for Virtual Properties
@Transient
private Map<String, Object> extensions;
public <T> T get(String name) {
return (T) extentions.get(name);
}
public Object set(String name, Object value) {
return extensions.put(name, value);
}
}
For More Information
A JAXB (JSR-222) implementation by default will not strip of any new line characters.
Java Model (Foo)
Below is a simple Java model with one String property.
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Foo {
private String bar;
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
Demo
The demo code below will convert the XML to objects and then write it back to XML.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum16690011/input.xml");
Foo foo = (Foo) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
input.xml/Output
The input and output both contain the new line characters.
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar>
A
B
C
</bar>
</foo>
UPDATE
If your property has an XmlAdapter associated with it via an @XmlJavaTypeAdapter annotation then this may explain the behaviour.
CollapsedStringAdapter
When the JAXB model is generated from an XML Schema and a node is of type xs:token then it will be annotated like:
@XmlJavaTypeAdapter(CollapsedStringAdapter.class)
public String getBar() {
return bar;
}
You would get the following output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<foo>
<bar>A B C</bar>
</foo>
NormalizedStringAdapter
When the JAXB model is generated from an XML Schema and a node is of type xs:normalizedString then it will be annotated like:
@XmlJavaTypeAdapter(NormalizedStringAdapter.class)
public String getBar() {
return bar;
}
You would get the following output:
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar> A B C </bar>
</foo>
Based on the stack trace you are using EclipseLink MOXy as your JAXB (JSR-222) provider. We added support for the reference implementations com.sun.xml.bind.CharacterEscapeHandler in EclipseLink 2.4. Prior to that release of EclipseLink you would get the exception that you are seeing.
UPDATE
It is possible that you are hittin the following bug, which has been fixed in the EclipseLink 2.5.1 stream.
You can download a nightly build from the following location:
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
JAXB (JSR-222) is the Java standard for XML binding it is leveraged by other standards such as JAX-WS (SOAP Web Services) and JAX-RS (RESTful Web Services).
Since the document is large and you only need a portion of it, I would recommend using a JAXB implementation in combination with a StAX parser. You can use an XMLStreamReader to advance to the portion of the document you wish to unmarshal, and only unmarshal the chunk you need.
Which one would be the best to bind this XML to POJO classes and then to persist to DB with JPA?
As MOXy is a component of EclipseLink which is the JPA reference implementation we spend a significant amount of effort on those use cases. I'm the MOXy lead and I share a cubicle wall with Mike Keith the former JPA co-spec lead.
When creating a JAXBContext based on a model generated from an XML schema you should always use the the newInstance method that takes the package name. This will ensure that all the necessary bits are processed.
JAXBContext jC = JAXBContext.newInstance("ch.forum_datenaustausch.de");
When you use the JAXBContext.newInstance(Class...) method the JAXB implementation is assuming that you started from Jav classes. Since the role of ObjectFactory can be played by any class annotated with @XmlRegistry the ObjectFactory class generated from the XML schema will be automatically picked up. You could do the following, but I still recommend the above approach:
JAXBContext jC = JAXBContext.newInstance(ResponseType.class, ObjectFactory.class);
UPDATE
Thank you! but could you probably explain why it is working with one xsd and not with the other?
The schema where it "works" may have a global element with an anonymous type which causes an @XmlRootElement annotation to be generated meaning the ObjectFactory is not required. The other may have a global element with a named complex type which causes an @XmlElementDecl annotation on an ObjectFactory class to be generated.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The current support for multi-dimensional arrays in MOXy matches the XML representation as defined in the JAXB specification. I will update this answer once I have come up with an appropriate workaround for you.
Below is an enhancement request that you can use to track our first-class support for this use case:
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
With MOXy as your JSON-binding provider the shared references post you referenced (from my blog) will work for JSON just as it does for XML. Since you are using JAX-RS below is an example of configuring MOXy in that environment:
When using @XmlID/@XmlIDREF it is expected that the object being reference by its ID also exist in the document. Since this isn't your use case you would be better off using an XmlAdapter. The XmlAdapter would have a signature similar to:
public class BarAdapter extends XmlAdapter<Integer, Bar> {
...
}
In the XmlAdapter you would be responsible for returning the id from the instance of Bar during the marshal, and for returning an instance of Bar based on the id during an unmarshal.
You can use the @XmlValue annotation on the option property of the Option class.
You could specify @XmlAcessorType(XmlAccessType.FIELD) so that MOXy (or and JAXB implementation) uses the field directly instead of the property (get/set methods). With this access type you will want to put the annotations on the fields.
For More Information
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
Below is how you could support this use case using the JSON-binding in EclipseLink JAXB (MOXy).
Java Model (Root)
Below is the Java model that I will use for this example.
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Root {
private List<String> channels = new ArrayList<String>();
@XmlElementWrapper
@XmlElement(name="channel")
public List<String> getChannels() {
return channels;
}
}
Specify MOXy as the JAXB Provider (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: ):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo Code
In the demo code below we will output the same instance to both XML and JSON.
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(Root.class);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
Root root = new Root();
root.getChannels().add("Test A");
root.getChannels().add("Test B");
// Output XML
marshaller.marshal(root, System.out);
// Output JSON
marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json");
marshaller.setProperty(MarshallerProperties.JSON_INCLUDE_ROOT, false);
marshaller.setProperty(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true);
marshaller.marshal(root, System.out);
}
}
Output
Below is the output from running the demo code:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<channels>
<channel>Test A</channel>
<channel>Test B</channel>
</channels>
</root>
{
"channels" : [ "Test A", "Test B" ]
}
For More Information
In the following document element2 is not namespace qualified so the default namespace is being set to "". The http://blubb.com/ namespacespace has then been assigned to the ns1 prefix in case it is needed.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<root xmlns="http://blubb.com/">
<element>
<element2 xmlns:ns1="http://blubb.com/" xmlns="">
</element2>
</element>
</root>
For More Information on JAXB and Namespaces
The purpose of the CDATA block is to preserve the content as un-parsed character data (which is what you are seeing). Once you have the String you could parse that to access it's data.
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The Binder mechanism in JAXB may be what you are looking for. It doesn't allow a DOM node to be cast to a domain object, but it does maintain a link between a domain object and its corresponding DOM node.
Note: The following code ran clean when using the MOXy as the JAXB provider, but threw an exception when using the impl of JAXB included in the version of the JDK I happen to be running.
JAVA MODEL
I will use the following domain model for this example.
Customer
import java.util.*;
import javax.xml.bind.annotation.*;
@XmlRootElement
public class Customer {
private List<PhoneNumber> phoneNumbers = new ArrayList<PhoneNumber>();
@XmlElementWrapper
@XmlElement(name="phoneNumber")
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
}
PhoneNumber
import javax.xml.bind.annotation.*;
public class PhoneNumber {
private String type;
private String number;
@XmlAttribute
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
@XmlValue
public String getNumber() {
return number;
}
public void setNumber(String number) {
this.number = 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)
<?xml version="1.0" encoding="UTF-8"?>
<customer>
<phoneNumbers>
<phoneNumber type="work">555-1111</phoneNumber>
<phoneNumber type="home">555-2222</phoneNumber>
</phoneNumbers>
</customer>
DEMO CODE
In the demo code below I will do the following:
Binder to find the corresponding domain object.Binder to apply the change to the DOM.Binder to apply the change to the domain object.Demo
import javax.xml.bind.Binder;
import javax.xml.bind.JAXBContext;
import javax.xml.parsers.*;
import javax.xml.xpath.*;
import org.w3c.dom.*;
public class Demo {
public static void main(String[] args) throws Exception {
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setNamespaceAware(true);
DocumentBuilder db = dbf.newDocumentBuilder();
Document document = db.parse("src/forum16599580/input.xml");
XPathFactory xpf = XPathFactory.newInstance();
XPath xpath = xpf.newXPath();
JAXBContext jc = JAXBContext.newInstance(Customer.class);
Binder<Node> binder = jc.createBinder();
binder.unmarshal(document);
// Use Node to Get Object
Node phoneNumberElement = (Node) xpath.evaluate("/customer/phoneNumbers/phoneNumber[2]", document, XPathConstants.NODE);
PhoneNumber phoneNumber = (PhoneNumber) binder.getJAXBNode(phoneNumberElement);
// Modify Object to Update DOM
phoneNumber.setNumber("555-2OBJ");
binder.updateXML(phoneNumber);
System.out.println(xpath.evaluate("/customer/phoneNumbers/phoneNumber[2]", document, XPathConstants.STRING));
// Modify DOM to Update Object
phoneNumberElement.setTextContent("555-2DOM");
binder.updateJAXB(phoneNumberElement);
System.out.println(phoneNumber.getNumber());
}
}
Output
555-2OBJ
555-2DOM
You could do the following with any JAXB (JSR-222) implementation. An implementation is included in the JDK/JRE starting with Java SE 6:
JAVA MODEL
TaskList
import java.util.List;
import javax.xml.bind.annotation.*;
@XmlRootElement(name="task-list")
@XmlAccessorType(XmlAccessType.FIELD)
public class TaskList {
@XmlElement(name="task")
private List<Task> tasks;
}
Task
import javax.xml.bind.annotation.*;
@XmlAccessorType(XmlAccessType.FIELD)
public class Task {
@XmlElement(name="input-location")
private String inputLocation;
@XmlElement(name="output-location")
private String outputLocation;
@XmlElement(name="bit-rate")
private int bitRate;
@XmlElement(name="output-width")
private int outputWidth;
@XmlElement(name="output-height")
private int outputHeight;
@XmlElement(name="target-device")
private String targetDevice;
}
DEMO CODE
Demo
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(TaskList.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum16579050/input.xml");
TaskList taskList = (TaskList) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(taskList, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<task-list>
<task>
<input-location>foo input</input-location>
<output-location>foo output</output-location>
<bit-rate>1</bit-rate>
<output-width>2</output-width>
<output-height>3</output-height>
<target-device>foo</target-device>
</task>
<task>
<input-location>bar input</input-location>
<output-location>bar output</output-location>
<bit-rate>4</bit-rate>
<output-width>5</output-width>
<output-height>6</output-height>
<target-device>bar</target-device>
</task>
</task-list>
EclipseLink JAXB (MOXy) will marshal without an @XmlRootElement annotation, the the JAXB reference implementation will complain.
I suspect that you do not have the jaxb.properties file in the correct location of your Maven setup. If your domain model is in the com.example.foo package then the jaxb.properties file should go in the following location.
src/main/resources/com/example/foo/jaxb.properties
For an example project see:
UPDATE
is it possible to tell moxy/the marshaller to use a fixed jaxb.properties and not to search it deep in package folders (i have many of the and all are identical)
If you want MOXy to always be used as the JAXB (JSR-222) provider then you can add the following to your classpath:
META-INF/services/javax.xml.bind.JAXBContext
The javax.xml.bind.JAXBContext file will contain the following contents:
org.eclipse.persistence.jaxb.JAXBContextFactory
Otherwise you can always use the native MOXy APIs to create the JAXBContext:
JAXBContext jc = org.eclipse.persistence.jaxb.JAXBContextFactory.createContext(new Class[] {Foo.class}, null);
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
EclipseLink JAXB (MOXy) offerst this support through its object graph extension. Object graphs allow you to specify a subset of properties for the purposes of marshalling an unmarshalling. They may be created at runtime programatically:
// Create the Object Graph
ObjectGraph contactInfo = JAXBHelper.getJAXBContext(jc).createObjectGraph(Customer.class);
contactInfo.addAttributeNodes("name");
Subgraph location = contactInfo.addSubgraph("billingAddress");
location.addAttributeNodes("city", "province");
Subgraph simple = contactInfo.addSubgraph("phoneNumbers");
simple.addAttributeNodes("value");
// Output XML - Based on Object Graph
marshaller.setProperty(MarshallerProperties.OBJECT_GRAPH, contactInfo);
marshaller.marshal(customer, System.out);
or statically on the class through annotations:
@XmlNamedObjectGraph(
name="contact info",
attributeNodes={
@XmlNamedAttributeNode("name"),
@XmlNamedAttributeNode(value="billingAddress", subgraph="location"),
@XmlNamedAttributeNode(value="phoneNumbers", subgraph="simple")
},
subgraphs={
@XmlNamedSubgraph(
name="location",
attributeNodes = {
@XmlNamedAttributeNode("city"),
@XmlNamedAttributeNode("province")
}
)
}
)
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {
For More Information
You could create a MessageBodyWriter for this use case. Through the ContextResolver mechanism you can get the JAXBContext associated with your domain model. Then you can get a Marshaller from the JAXBContext and set the JAXB_SCHEMA_LOCATION on it and do the marshal.
package org.example;
import java.io.*;
import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import javax.ws.rs.*;
import javax.ws.rs.core.*;
import javax.ws.rs.ext.*;
import javax.xml.bind.*;
@Provider
@Produces(MediaType.APPLICATION_XML)
public class FormattingWriter implements MessageBodyWriter<Object>{
@Context
protected Providers providers;
public boolean isWriteable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return true;
}
public void writeTo(Object object, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) throws IOException,
WebApplicationException {
try {
ContextResolver<JAXBContext> resolver
= providers.getContextResolver(JAXBContext.class, mediaType);
JAXBContext jaxbContext;
if(null == resolver || null == (jaxbContext = resolver.getContext(type))) {
jaxbContext = JAXBContext.newInstance(type);
}
Marshaller m = jaxbContext.createMarshaller();
m.setProperty(Marshaller.JAXB_SCHEMA_LOCATION, "foo bar");
m.marshal(object, entityStream);
} catch(JAXBException jaxbException) {
throw new WebApplicationException(jaxbException);
}
}
public long getSize(Object t, Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
return -1;
}
}
UPDATE
One other question. What is the connection between the my rest resource and the provider?
You still implement your resource the same way. The MessageBodyWriter mechanism is just a way to override how the writing to XML will be done. The @Provider annotation is a signal to the JAX-RS application to have this class automatically registered.
My resource class would return a
Fooobject. I take it I should be implementing aMessageBodyWriter<Foo>?
You could implement it as MessageBodyWriter<Foo> if you only want it applied to the Foo class. If you want it to apply to more than just Foo you can implement to the isWriteable method to return true for the appropriate classes.
I recommend using the package level @XmlSchema annotation to specify the namespace qualification for you model. A package level annotation goes in a special class called package-info that contains the exact content as shown below. That annotation will mean that all elements in your document without an explicit namespace given will use that namespace.
org/example/foo/package-info.java
@XmlSchema(
namespace = "http://www.example.org/foo",
elementFormDefault = XmlNsForm.QUALIFIED)
package org.example.foo;
import javax.xml.bind.annotation.XmlNsForm;
import javax.xml.bind.annotation.XmlSchema;
Overriding the Namespace
@XmlSchema for all properties in a class using the @XmlType annotation.@XmlRootElement or @XmlElement annotation.For More Information
When mapping JPA entities with JAXB I recommend using the default access (or XmlAccessType.PROPERTY) and annotate the get methods. JPA impls have tricks to handle things such lazy loading that sometimes causes problems when field access is used.
Question 1 - Does this attribute has to have the exact same value ?
A JAXB (JSR-222) implementation expects the elements the elements in the binding file to be qualified with the "http://java.sun.com/xml/ns/jaxb" namespace. It does not depend on a particular prefix being used.
Question 2 - This attribute, in the schema.. in the schema ???
Since the XML schema is an XML document I guess doing this is ok, but I have never done this in an XML schema myself.
Question 3 - The word binding.
I have a kind of love/hate relationship with the word "binding". It has come to be assocated with converting objects to/from data formats that aren't necessarily persistent (i.e. XML, JSON, etc).
Question 4 - In the JAXB binding document schemaLocation="address.xsd" points to the schema location.
I do not believe that the schemaLocation is required in the bindings file.
Since you are just getting started with JAXB you may not want to get hung up on the binding document. It's only needed when you need to customize the classes generated from an XML schema. Below is an example where it is not needed:
What I find is the more interesting use case is staring from objects. Below is an example you may find useful:
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
PROBLEM
The @XmlElementWrapper annotation must be used with a collection property. This means you can have:
@XmlElementWrapper
public List<PhoneNumber> getPhoneNumbers() {
return phoneNumbers;
}
But not
@XmlElementWrapper
public Address getAddress() {
return address;
}
SOLUTION #1 - Using Any JAXB Proivder
You could use an XmlAdapter to accomplish this (see linked answer below):
SOLUTION #2 - Using EclipseLink JAXB (MOXy)
You could leverage the @XmlPath extension to map this use case:
@XmlPath("Former-User-Ids/Address")
public Address getAddress() {
return address;
}
For More Information
@MuhammedRefaat - I have updated my answer with a way to map this use case.
No, but I'm the EclipseLink JAXB (MOXy) lead.
I can help you with that issue if you are interested.
Your model was generated using XMLBeans and that model based on the exception is being interpreted by a JAXB implementation? What was the original problem you hit with JAXB?
@LittleChild - That's correct. The JAXB implementation will not populate them, so they will get whatever you initialize them to or their default value.
@RAjKuamr - I have updated my answer based on your comment.
@ØrjanJohansen - I have been able to confirm the issue you are seeing when using jdk1.7.0_21 for Windows (it is fine on the Mac). This appears to be a bug in the JAXB impl included in that version of the JDK, you can log a bug here: java.net/jira/browse/JAXB). You could always use another implementation such as EclipseLink MOXy (I'm the MOXy lead): blog.bdoughan.com/2011/05/…
You can use MOXy with Jersey for JSON-binding blog.bdoughan.com/2012/05/… and github.com/jersey/jersey/blob/master/examples/json-moxy
@ØrjanJohansen - When I get to the office I will try out this example on a Windows box and see if I can confirm your results.
@ØrjanJohansen - That is a good question. For my result I'm using jdk1.7.0_21 for the Mac.
@dermoritz - I have updated my answer with a possible explanation.
What does the corresponding object model look like?
It is Spring and not JAXB that is adding the response element.
Wouldn't you rather have: "channels" : ["Test A", "Test B"]?
In a previous post I covered how EclipseLink JPA-RS can be used to expose a JPA persistence unit as a RESTful service. In that example we interacted...
In a previous series of posts I covered how to create a JAX-RS service that leveraged JPA for the persistence layer. EclipseLink contains a component...
Java will soon have a standard set of APIs for processing JSON as part of Java EE 7. This standard is being defined as JSR 353 - Java API for JSON...
Suppose you have a domain model that you want to expose as a RESTful service. The problem is you only want to input/output part of your data. ...
JSON with padding is a communication mechanism used in JavaScript to overcome restrictions due to the same origin policy (for more information see:...
One of EclipseLink JAXB (MOXy)'s strengths is the ability to map an object model to both JSON and XML with a single set of metadata. The one weakness...
Is it ironic that it can be difficult to map the java.util.Map class in JAXB (JSR-222)? In this post I will cover some items that will make it much...
In previous articles I demonstrated how EclipseLink JAXB (MOXy) is directly integrated into the JAX-WS implementations in WebLogic (as of 12.1.1) and in...
In this post I will cover how to differentiate between null and empty collections in the XML representation with JAXB (JSR-222). Demo Code The...
In a previous post I introduced how the @XmlAnyElement(lax=true) annotation could be used to create a very flexible mapping. In this post I'll...
JAXB (JSR-222)enables Java to treat a domain model as XML. In this post I will demonstrate how to leverage this by applying an XSLT stylesheet to a JAXB...
For some an XML schema is a strict set of rules for how the XML document must be structured. But for others it is a general guideline to...
JSON binding was added to EclipseLink in version 2.4. If you are using a version of that does not contain this version (i.e. WebLogic 10.3.4...
JAXBElement is a JAXB (JSR-222) mechanism that stores name and namespace information in situations where this can not be determined from the value or...
Recently I have come across a lot of people asking how to read data from, or write data to the middle of an XML document. In this post I will demonstrate...
JAXB (JSR-222) makes it easy for you to convert instances of your domain classes to/from XML. The EclipseLink MOXy implementation offers an extension called Dynamic JAXB where instead of real classes you have instances of a map like class called DynamicEntity. You can access the data on your DynamicEntity using get and set methods that [...]
In a previous series of posts I covered how to create a JAX-RS service that leveraged JPA for the persistence layer. EclipseLink contains a component called JPA-RS that can be used to easily and automatically expose a persistence unit as RESTful service (that supports XML and JSON messages). MOXy provides the XML and JSON-binding for [...]
Java will soon have a standard set of APIs for processing JSON as part of Java EE 7. This standard is being defined as JSR 353 – Java API for JSON Processing (JSON-P) and it is currently at the Final Approval Ballot. JSON-P offers both object oriented and stream based approaches, in this post I [...]
Suppose you have a domain model that you want to expose as a RESTful service. The problem is you only want to input/output part of your data. Previously you would have created a separate model representing the subset and then have code to move data between the models. In EclipseLink 2.5.0 we have a new [...]
One of EclipseLink JAXB (MOXy)‘s strengths is the ability to map an object model to both JSON and XML with a single set of metadata. The one weakness had been that you needed to compromise on the JSON key or XML element for collection properties. I’m happy to say that this issue has been solved [...]
Is it ironic that it can be difficult to map the java.util.Map class in JAXB (JSR-222)? In this post I will cover some items that will make it much easier. Java Model Below is the Java model that we will use for this example. Customer The Customer class has a property of type Map . [...]
In previous articles I demonstrated how EclipseLink JAXB (MOXy) is directly integrated into the JAX-WS implementations in WebLogic (as of 12.1.1) and in GlassFish (as of 3.1.2). In this post I’ll demonstrate how to leverage MOXy in any application server by using the JAX-WS Provider class. Web Service The Provider mechanism in JAX-WS provides you [...]
Demo Code The following demo code will be used for all the different versions of the Java model. It simply sets one collection to null, the second to an empty list, and the third to a populated list. package package blog.xmlelementwrapper; import java.util.ArrayList; import javax.xml.bind.*; public class Demo { [...]
For some an XML schema is a strict set of rules for how the XML document must be structured. But for others it is a general guideline to indicate what the XML should look like. This means that sometimes people want to accept input that doesn’t conform to the XML schema for some reason. In [...]
@XmlRootElement is an annotation that people are used to using with JAXB (JSR-222). It’s purpose is to uniquely associate a root element with a class. Since JAXB classes map to complex types, it is possible for a class to correspond to multiple root elements. In this case @XmlRootElement can not be used and people start [...]