DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

Curious about the future of data-driven systems? Join our Data Engineering roundtable and learn how to build scalable data platforms.

Data Engineering: The industry has come a long way from organizing unstructured data to adopting today's modern data pipelines. See how.

Threat Detection: Learn core practices for managing security risks and vulnerabilities in your organization — don't regret those threats!

Managing API integrations: Assess your use case and needs — plus learn patterns for the design, build, and maintenance of your integrations.

Avatar

Blaise Doughan

Team Lead, TopLink OXM/JAXB/SDO at Oracle

Ottawa, CA

Joined Apr 2010

About

Team lead for the TopLink/EclipseLink JAXB & SDO implementations, and the Oracle representative on those specifications.

Stats

Reputation: 1
Pageviews: 1.3M
Articles: 24
Comments: 44
  • Articles
  • Comments

Articles

article thumbnail
EclipseLink MOXy and the Java API for JSON Processing - Object Model APIs
The Java API for JSON Processing (JSR-353) is the Java standard for producing and consuming JSON which was introduced as part of Java EE 7. JSR-353 includes object (DOM like) and stream (StAX like) APIs. In this post I will demonstrate the initial JSR-353 support we have added to MOXy's JSON binding in EclipseLink 2.6. You can now use MOXy to marshal to: javax.json.JsonArrayBuilder javax.json.JsonObjectBuilder And unmarshal from: javax.json.JsonStructure javax.json.JsonObject javax.json.JsonArray You can try this out today using a nightly build of EclipseLink 2.6.0: http://www.eclipse.org/eclipselink/downloads/nightly.php The JSR-353 reference implementation is available here: https://java.net/projects/jsonp/downloads/download/ri/javax.json-ri-1.0.zip Java Model Below is the simple customer model that we will use for this post. Note for this example we are only using the standard JAXB (JSR-222) annotations. Customer package blog.jsonp.moxy; import java.util.*; import javax.xml.bind.annotation.*; @XmlType(propOrder={"id", "firstName", "lastName", "phoneNumbers"}) public class Customer { private int id; private String firstName; private String lastName; private List phoneNumbers = new ArrayList(); public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } @XmlElement(nillable=true) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } @XmlElement public List getPhoneNumbers() { return phoneNumbers; } } PhoneNumber package blog.jsonp.moxy; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class PhoneNumber { private String type; private String number; public String getType() { return type; } public void setType(String type) { this.type = type; } 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: Specifying EclipseLink MOXy as your JAXB Provider) javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory Marshal Demo In the demo code below we will use a combination of JSR-353 and MOXy APIs to produce JSON. JSR-353's JsonObjectBuilder and JsonArrayBuilder are used to produces instances of JsonObject and JsonArray. We can use MOXy to marshal to these builders by wrapping them in instances of MOXy's JsonObjectBuilderResult and JsonArrayBuilderResult. package blog.jsonp.moxy; import java.util.*; import javax.json.*; import javax.json.stream.JsonGenerator; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextProperties; import org.eclipse.persistence.oxm.json.*; public class MarshalDemo { public static void main(String[] args) throws Exception { // Create the EclipseLink JAXB (MOXy) Marshaller Map jaxbProperties = new HashMap(2); jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, jaxbProperties); Marshaller marshaller = jc.createMarshaller(); // Create the JsonArrayBuilder JsonArrayBuilder customersArrayBuilder = Json.createArrayBuilder(); // Build the First Customer Customer customer = new Customer(); customer.setId(1); customer.setFirstName("Jane"); customer.setLastName(null); PhoneNumber phoneNumber = new PhoneNumber(); phoneNumber.setType("cell"); phoneNumber.setNumber("555-1111"); customer.getPhoneNumbers().add(phoneNumber); // Marshal the First Customer Object into the JsonArray JsonArrayBuilderResult result = new JsonArrayBuilderResult(customersArrayBuilder); marshaller.marshal(customer, result); // Build List of PhoneNumer Objects for Second Customer List phoneNumbers = new ArrayList(2); PhoneNumber workPhone = new PhoneNumber(); workPhone.setType("work"); workPhone.setNumber("555-2222"); phoneNumbers.add(workPhone); PhoneNumber homePhone = new PhoneNumber(); homePhone.setType("home"); homePhone.setNumber("555-3333"); phoneNumbers.add(homePhone); // Marshal the List of PhoneNumber Objects JsonArrayBuilderResult arrayBuilderResult = new JsonArrayBuilderResult(); marshaller.marshal(phoneNumbers, arrayBuilderResult); customersArrayBuilder // Use JSR-353 APIs for Second Customer's Data .add(Json.createObjectBuilder() .add("id", 2) .add("firstName", "Bob") .addNull("lastName") // Included Marshalled PhoneNumber Objects .add("phoneNumbers", arrayBuilderResult.getJsonArrayBuilder()) ) .build(); // Write JSON to System.out Map jsonProperties = new HashMap(1); jsonProperties.put(JsonGenerator.PRETTY_PRINTING, true); JsonWriterFactory writerFactory = Json.createWriterFactory(jsonProperties); JsonWriter writer = writerFactory.createWriter(System.out); writer.writeArray(customersArrayBuilder.build()); writer.close(); } } Highlighted lines: 36, 37, 38, 54, 55, 64 Output Below is the output from running the marshal demo (MarshalDemo). The highlighted portions (lines 2-12 and 18-25) correspond to the portions that were populated from our Java model. [ { "id":1, "firstName":"Jane", "lastName":null, "phoneNumbers":[ { "type":"cell", "number":"555-1111" } ] }, { "id":2, "firstName":"Bob", "lastName":null, "phoneNumbers":[ { "type":"work", "number":"555-2222" }, { "type":"home", "number":"555-3333" } ] } ] Highlighted lines: 2-12, 18-25 Unmarshal Demo MOXy enables you to unmarshal from a JSR-353 JsonStructure (JsonObject or JsonArray). To do this simply wrap the JsonStructure in an instance of MOXy's JsonStructureSource and use one of the unmarshal operations that takes an instance of Source. package blog.jsonp.moxy; import java.io.FileInputStream; import java.util.*; import javax.json.*; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.JAXBContextProperties; import org.eclipse.persistence.oxm.json.JsonStructureSource; public class UnmarshalDemo { public static void main(String[] args) throws Exception { try (FileInputStream is = new FileInputStream("src/blog/jsonp/moxy/input.json")) { // Create the EclipseLink JAXB (MOXy) Unmarshaller Map jaxbProperties = new HashMap(2); jaxbProperties.put(JAXBContextProperties.MEDIA_TYPE, "application/json"); jaxbProperties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, jaxbProperties); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Parse the JSON JsonReader jsonReader = Json.createReader(is); // Unmarshal Root Level JsonArray JsonArray customersArray = jsonReader.readArray(); JsonStructureSource arraySource = new JsonStructureSource(customersArray); List customers = (List) unmarshaller.unmarshal(arraySource, Customer.class) .getValue(); for(Customer customer : customers) { System.out.println(customer.getFirstName()); } // Unmarshal Nested JsonObject JsonObject customerObject = customersArray.getJsonObject(1); JsonStructureSource objectSource = new JsonStructureSource(customerObject); Customer customer = unmarshaller.unmarshal(objectSource, Customer.class) .getValue(); for(PhoneNumber phoneNumber : customer.getPhoneNumbers()) { System.out.println(phoneNumber.getNumber()); } } } } Highlighted lines: 27-30, 37-39 Input (input.json) The following JSON input will be converted to a JsonArray using a JsonReader. [ { "id":1, "firstName":"Jane", "lastName":null, "phoneNumbers":[ { "type":"cell", "number":"555-1111" } ] }, { "id":2, "firstName":"Bob", "lastName":null, "phoneNumbers":[ { "type":"work", "number":"555-2222" }, { "type":"home", "number":"555-3333" } ] } ] Highlighted lines: 4, 15, 20, 24 Output Below is the output from running the unmarshal demo (UnmarshalDemo). Jane Bob 555-2222 555-3333
August 7, 2013
· 13,199 Views
article thumbnail
MOXy's @XmlVariableNode - Using a Map's Key as the Node Name
People often ask me how they can map a java.util.Map such that the keys become the node names. In this post I will demonstrate how this can be done using the new Variable Node mapping that we have added in EclipseLink MOXy. You can try this out today using a nightly build of EclipseLink 2.6.0: http://www.eclipse.org/eclipselink/downloads/nightly.php Input/Output Below are the XML and JSON representations we will use in this example. Each has node names that correspond to keys and contents that correspond to values of a Map. XML (input.xml) 1 2 JSON (Output) { "A" : 1, "B" : 2 } Java Model (Root) We want a non-default XML (and JSON) representation for Map so we will use an XmlAdapter (see: JAXB and java.util.Map). MOXy's @XmlPath extension will be used to prevent the contents of the adapted Map from being wrapped in a parent element (see: XPath Based Mapping). package blog.variablenode.map; import java.util.*; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import org.eclipse.persistence.oxm.annotations.XmlPath; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlPath(".") @XmlJavaTypeAdapter(MapAdapter.class) private Map map = new HashMap(); } XmlAdapter (MapAdapter) An XmlAdapter is used to convert an object for the purposes of marshalling/unmarshalling (see: XmlAdapter - JAXB's Secret Weapon). In this example we convert the Map to an AdaptedMap that has a List of AdaptedEntry values. These AdaptedEntry values have a field (key) to represent the key. It is this field that we will use with @XmlVariableNode (line 13). We will mark the key field with @XmlTransient to prevent if from being marshalled/unmarshalled (line 20). package blog.variablenode.map; import java.util.*; import java.util.Map.Entry; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.eclipse.persistence.oxm.annotations.XmlVariableNode; public class MapAdapter extends XmlAdapter> { public static class AdaptedMap { @XmlVariableNode("key") List entries = new ArrayList(); } public static class AdaptedEntry { @XmlTransient public String key; @XmlValue public Integer value; } @Override public AdaptedMap marshal(Map map) throws Exception { AdaptedMap adaptedMap = new AdaptedMap(); for(Entry entry : map.entrySet()) { AdaptedEntry adaptedEntry = new AdaptedEntry(); adaptedEntry.key = entry.getKey(); adaptedEntry.value = entry.getValue(); adaptedMap.entries.add(adaptedEntry); } return adaptedMap; } @Override public Map unmarshal(AdaptedMap adaptedMap) throws Exception { List adaptedEntries = adaptedMap.entries; Map map = new HashMap(adaptedEntries.size()); for(AdaptedEntry adaptedEntry : adaptedEntries) { map.put(adaptedEntry.key, adaptedEntry.value); } return map; } } Demo Below is some demo code that can be run to prove that everything works. The Root object will be instantiated from XML input and marshalled to create the JSON output. package blog.variablenode.map; 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(Root.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/blog/variablenode/map/input.xml"); Root root = (Root) 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(root, System.out); } } Further Reading If you enjoyed this post then you may also be interested in: MOXy's @XmlVariableNode - JSON Schema Example Specifying EclipseLink MOXy as your JAXB Provider JAXB and java.util.Map JSON Binding with EclipseLink MOXy - Twitter Example
June 20, 2013
· 12,443 Views
article thumbnail
Binding to JSON & XML - Handling Collections
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 in EclipseLink 2.5 (and EclipseLink 2.4.2), and I will demonstrate below with an example. You can try this out today by downloading an EclipseLink 2.5.0 (or EclipseLink 2.4.2) nightly build starting on March 15, 2013 from: http://www.eclipse.org/eclipselink/downloads/nightly.php Domain Model By default a JAXB (JSR-222) implementation will not output a grouping element around collection data. This can be done through the use of the @XmlElementWrapper annotation (see: JAXB & Collection Properties). This grouping element often has a plural name and is a better fit for the key of a JSON array than the repeating element defined by the @XmlElement annotation is. package blog.json.collections; import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder={"name", "emailAddresses"}) public class Customer { private String name; private List emailAddresses = new ArrayList(); public String getName() { return name; } public void setName(String name) { this.name = name; } @XmlElementWrapper(name="email-addresses") @XmlElement(name="email-address") public List getEmailAddresses() { return emailAddresses; } public void setEmailAddresses(List<'String> emailAddresses) { this.emailAddresses = emailAddresses; } } Demo We will specify the JSON_WRAPPER_AS_ARRAY_NAME property with a true value to tell MOXy that it should use the grouping element as the name for the JSON array value. Then we will use the same Marshaller to output the same object to both XML and JSON. package blog.json.collections; import java.util.*; import javax.xml.bind.*; import org.eclipse.persistence.jaxb.MarshallerProperties; public class Demo { public static void main(String[] args) throws Exception { Customer customer = new Customer(); customer.setName("Jane Doe"); customer.getEmailAddresses().add("jane.doe@example.com"); customer.getEmailAddresses().add("jdoe@example.org"); Map properties = new HashMap(1); properties.put(MarshallerProperties.JSON_WRAPPER_AS_ARRAY_NAME, true); JAXBContext jc = JAXBContext.newInstance(new Class[] {Customer.class}, properties); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Output XML marshaller.marshal(customer, System.out); // Output JSON marshaller.setProperty(MarshallerProperties.MEDIA_TYPE, "application/json"); marshaller.marshal(customer, System.out); } } XML Output Below is the XML output from running the demo code. We see that email-addresses is marshalled as the grouping element which contains an email-address element for each item in the collection. Jane Doe jane.doe@example.com jdoe@example.org JSON Output The following JSON output is produced from the same metadata. The only difference is that we told MOXy to use the grouping element as the name for JSON array values. { "customer" : { "name" : "Jane Doe", "email-addresses" : [ "jane.doe@example.com", "jdoe@example.org" ] } } JAX-RS You can easily use MOXy as your JSON-binding provider in a JAX-RS environment (see: MOXy as your JAX-RS JSON Provider - MOXyJsonProvider). You can specify that the grouping element should be used as the JSON array name with the wrapperAsArrayName property on MOXyJsonProvider. package blog.json.collections; import java.util.*; import javax.ws.rs.core.Application; import org.eclipse.persistence.jaxb.rs.MOXyJsonProvider; public class CustomerApplication extends Application { @Override public Set> getClasses() { HashSet> set = new HashSet>(1); set.add(CustomerService.class); return set; } @Override public Set
March 18, 2013
· 6,569 Views
article thumbnail
JAXB and java.util.Map
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. I chose this Map specifically since the key is a domain object and the value is a domain object. package blog.map; import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement public class Customer { private Map addressMap = new HashMap(); public Map getAddressMap() { return addressMap; } public void setAddressMap(Map addressMap) { this.addressMap = addressMap; } } Address The Address class is just a typical POJO. package blog.map; public class Address { private String street; public String getStreet() { return street; } public void setStreet(String street) { this.street = street; } } Demo Code In the demo code below we will create an instance of Customer and populate its Map property. Then we will marshal it to XML. package blog.map; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class); Address billingAddress = new Address(); billingAddress.setStreet("1 A Street"); Address shippingAddress = new Address(); shippingAddress.setStreet("2 B Road"); Customer customer = new Customer(); customer.getAddressMap().put("billing", billingAddress); customer.getAddressMap().put("shipping", shippingAddress); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } Use Case #1 - Default Representation Below is a sample of XML corresponding to our domain model. We see that each item in the Map has key and value elements wrapped in an entry element. shipping 2 B Road billing 1 A Street Use Case #2 - Rename the Element The JAXB reference implementation uses the @XmlElementWrapper annotation to rename the element corresponding to a Map property (we've added this support to MOXy in EclipseLink 2.4.2 and 2.5.0). In previous versions of MOXy the @XmlElement annotation should be used. Customer We will use the @XmlElementWrapper annotation to rename the element corresponding to the addressMap property to be addresses. package blog.map; import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement public class Customer { private Map addressMap = new HashMap(); @XmlElementWrapper(name="addresses") public Map getAddressMap() { return addressMap; } public void setAddressMap(Map addressMap) { this.addressMap = addressMap; } } Output Now we see that the addressMap element has been renamed to addresses. shipping 2 B Road billing 1 A Street Use Case #3 - Add Namespace Qualification In this use case we will examine the impact of applying namespace qualification to a class that has a property of type java.util.Map. There was a MOXy bug related to the namespace qualification of Map properties that has been fixed in EclipseLink 2.4.2 and 2.5.0 (see: http://bugs.eclipse.org/399297). package-info We will use the package level @XmlSchema annotation to specify that all fields/properties belonging to classes in this package should be qualified with the http://www.example.com namespace (see: JAXB & Namespaces). @XmlSchema( namespace="http://www.example.com", elementFormDefault=XmlNsForm.QUALIFIED) package blog.map; import javax.xml.bind.annotation.*; Output We see that the elements corresponding to the Customer and Address classes are namespace qualified, but the elements corresponding to the Map class are not. This is because the Map class is from the java.util package and therefore the information we specified on the package level @XmlSchema annotation does not apply. shipping 2 B Road billing 1 A Street Use Case #4 - Fix Namespace Qualification with an XmlAdapter We can use an XmlAdapter to adjust the namespace qualification from the previous use case. XmlAdapter (MapAdapter) The XmlAdapter mechanism allows you to convert a class to another for the purpose of affecting the mapping (see: XmlAdapter - JAXB's Secret Weapon). To get the appropriate namespace qualification we will use an XmlAdapter to convert the Map to objects in the package for our domain model. package blog.map; import java.util.*; import javax.xml.bind.annotation.adapters.XmlAdapter; public class MapAdapter extends XmlAdapter> { public static class AdaptedMap { public List entry = new ArrayList(); } public static class Entry { public String key; public Address value; } @Override public Map unmarshal(AdaptedMap adaptedMap) throws Exception { Map map = new HashMap(); for(Entry entry : adaptedMap.entry) { map.put(entry.key, entry.value); } return map; } @Override public AdaptedMap marshal(Map map) throws Exception { AdaptedMap adaptedMap = new AdaptedMap(); for(Map.Entry mapEntry : map.entrySet()) { Entry entry = new Entry(); entry.key = mapEntry.getKey(); entry.value = mapEntry.getValue(); adaptedMap.entry.add(entry); } return adaptedMap; } } Customer The @XmlJavaTypeAdapter annotation is used to specify the XmlAdapter on the Map property. Note with an XmlAdaper applied we need to change the @XmlElementWrapper annotation to @XmlElement (evidence that @XmlElement should be used to annotate the element for a Map property). package blog.map; import java.util.*; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement public class Customer { private Map addressMap = new HashMap(); @XmlJavaTypeAdapter(MapAdapter.class) @XmlElement(name="addresses") public Map getAddressMap() { return addressMap; } public void setAddressMap(Map addressMap) { this.addressMap = addressMap; } } Output Now all the elements in the XML output are qualfied with the http://www.example.com namespace. shipping 2 B Road billing 1 A Street
March 14, 2013
· 58,550 Views
article thumbnail
JAXB - Representing Null and Empty Collections
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 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 blog.xmlelementwrapper; import java.util.ArrayList; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Root root = new Root(); root.nullCollection = null; root.emptyCollection = new ArrayList(); root.populatedCollection = new ArrayList(); root.populatedCollection.add("foo"); root.populatedCollection.add("bar"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } Mapping #1 - Default JAXB models do not require any annotations (see JAXB - No Annotations Required). First we will look at what the default behaviour is for collection properties. package blog.xmlelementwrapper; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { List nullCollection; List emptyCollection; List populatedCollection; } Examining the output we see that the output corresponding to the nullCollection and emptyCollection fields is the same. This means with the default mapping we can't round trip the instance. For the unmarshal use case the value of the nullCollection and emptyCollection the value of the fields will be whatever the class initialized them to (null in this case). foo bar Mapping #2 - @XmlElementWrapper The @XmlElementWrapper annotation is used to add a grouping element around the contents of a collection. In addition to changing the appearance of the XML representation it also allows us to distinguish between null and empty collections. package blog.xmlelementwrapper; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlElementWrapper List nullCollection; @XmlElementWrapper List emptyCollection; @XmlElementWrapper List populatedCollection; } The representation for the null collection remains the same, it is absent from the XML document. For an empty collection we see that only the grouping element is marshalled out. Since the representations for null and empty are different we can round trip this use case. foo bar Mapping #3 - @XmlElementWrapper(nillable=true) The nillable property on the @XmlElementWrapper annotation can be used to change the XML representation of null collections. package blog.xmlelementwrapper; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlElementWrapper(nillable=true) List nullCollection; @XmlElementWrapper(nillable=true) List emptyCollection; @XmlElementWrapper(nillable=true) List populatedCollection; } Now the grouping element is present for all three fields. The xsi:nil attribute is used to indicate that the nullCollection field was null. Like the previous mapping this one can be round tripped. foo bar
January 3, 2013
· 50,083 Views
article thumbnail
JAXB's @XmlAnyElement(lax=true) Explained
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 dig a bit deeper into how it relates to both the @XmlRootElement and @XmlElementDecl. @XmlAnyElement (Root) The any field is annotated with @XmlAnyElement(lax=true). This means that for that field if an element is associated with a class via @XmlRootElement or @XmlElementDecl then an instance of the corresponding class will be used to populate the field if not the element will be set as an instance of org.w3c.dom.Element. package blog.anyelement; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Root { @XmlAnyElement(lax = true) protected List createBar(Bar bar) { return new JAXBElement(new QName("bar"), Bar.class, bar); } } Input (input.xml) Below is the input document we'll use for this example. There are 3 elements that correspond to the any property. The first corresponds to the @XmlRootElement annotation on the Foo class. The second corresponds to the @XmlElementDecl annotation for the Bar class and the third does not correspond to any of the domain classes. Hello World A B Demo In the demo code below we will unmarshal the input document, then output the classes of the objects in the resulting any property and then marshal the payload object back to XML. package blog.anyelement; import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class, Foo.class, ObjectFactory.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); File xml = new File("src/blog/anyelement/input.xml"); Root payload = (Root) unmarshaller.unmarshal(xml); for(Object o : payload.any) { System.out.println(o.getClass()); } Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(payload, System.out); } } Output Below is the output from running the demo code. Note the classes corresponding to the objects in the any property. The foo element became an instance of the Foo class. The bar element became an instance of JAXBElement that holds an instance of Bar. The other element became an instance of org.w3c.dom.Element. class blog.anyelement.Foo class javax.xml.bind.JAXBElement class com.sun.org.apache.xerces.internal.dom.ElementNSImpl Hello World A B
January 2, 2013
· 49,400 Views · 6 Likes
article thumbnail
Using JAXB With XSLT to Produce HTML
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 model to produce HTML. This approach is often leveraged when creating JAX-RS applications. Java Model Below is the Java model that will be used for this example. It represents information about a collection of books. Library package blog.jaxbsource.xslt; import java.util.*; import javax.xml.bind.annotation.*; @XmlRootElement public class Library { private List books = new ArrayList(); @XmlElement(name="book") public List getBooks() { return books; } } Book package blog.jaxbsource.xslt; public class Book { private String title; private String author; public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } } XML Structure Our JAXB model can be used to produce XML documents that conform to the following XML schema. The above XML schema was produced using the following code. package blog.jaxbsource.xslt; import java.io.IOException; import javax.xml.bind.*; import javax.xml.transform.Result; import javax.xml.transform.stream.StreamResult; public class GenSchema { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Library.class); jc.generateSchema(new SchemaOutputResolver() { @Override public Result createOutput(String namespaceURI, String suggestedFileName) throws IOException { StreamResult result = new StreamResult(System.out); result.setSystemId(suggestedFileName); return result; } }); } } Stylesheet Below is the XSLT stylesheet that we will use to convert the XML (JAXB model) to HTML. My Library Title Author Demo Code In our demo code we will use the standard javax.xml.transform APIs to do the conversion. Our JAXB input is wrapped in an instance of JAXBSource, and the output is wrapped in an instance of StreamResult. package blog.jaxbsource.xslt; import javax.xml.bind.*; import javax.xml.bind.util.JAXBSource; import javax.xml.transform.*; import javax.xml.transform.stream.*; public class Demo { public static void main(String[] args) throws Exception { // XML Data Book book1 = new Book(); book1.setAuthor("Jane Doe"); book1.setTitle("Some Book"); Book book2 = new Book(); book2.setAuthor("John Smith"); book2.setTitle("Another Novel"); Library catalog = new Library(); catalog.getBooks().add(book1); catalog.getBooks().add(book2); // Create Transformer TransformerFactory tf = TransformerFactory.newInstance(); StreamSource xslt = new StreamSource( "src/blog/jaxbsource/xslt/stylesheet.xsl"); Transformer transformer = tf.newTransformer(xslt); // Source JAXBContext jc = JAXBContext.newInstance(Library.class); JAXBSource source = new JAXBSource(jc, catalog); // Result StreamResult result = new StreamResult(System.out); // Transform transformer.transform(source, result); } } Output The following HTML output was produced as a result of running the demo code. My Library Title Author Some Book Jane Doe Another Novel John Smith
November 21, 2012
· 22,690 Views
article thumbnail
Applying a Namespace During JAXB Unmarshal
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 this example I will demonstrate how this can be done by leveraging a SAX XMLFilter. Java Model Below is the Java model that will be used for this example. Customer package blog.namespace.sax; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement public class Customer { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } package-info We will use the package level @XmlSchema annotation to specify the namespace qualification for our model. @XmlSchema( namespace="http://www.example.com/customer", elementFormDefault=XmlNsForm.QUALIFIED) package blog.namespace.sax; import javax.xml.bind.annotation.*; XML Input (input.xml) Even though our metadata specified that all the elements should be qualified with a namespace (http://www.example.com/customer) our input document is not namespace qualified. An XMLFilter will be used to add the namespace during the unmarshal operation. Jane Doe XMLFilter (NamespaceFilter) The easiest way to create an XMLFilter is to extend XMLFilterImpl. For our use case we will override the startElement and endElement methods. In each of these methods we will call the corresponding super method passing in the default namespace as the URI parameter. package blog.namespace.sax; import org.xml.sax.*; import org.xml.sax.helpers.XMLFilterImpl; public class NamespaceFilter extends XMLFilterImpl { private static final String NAMESPACE = "http://www.example.com/customer"; @Override public void endElement(String uri, String localName, String qName) throws SAXException { super.endElement(NAMESPACE, localName, qName); } @Override public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException { super.startElement(NAMESPACE, localName, qName, atts); } } Demo In the demo code below we will do a SAX parse of the XML document. The XMLReader will be wrapped in our XMLFilter. We will leverage JAXB's UnmarshallerHandler as the ContentHandler. Once the parse has been done we can ask the UnmarshallerHandler for the resulting Customer object. package blog.namespace.sax; import javax.xml.bind.*; import javax.xml.parsers.*; import org.xml.sax.*; public class Demo { public static void main(String[] args) throws Exception { // Create the JAXBContext JAXBContext jc = JAXBContext.newInstance(Customer.class); // Create the XMLFilter XMLFilter filter = new NamespaceFilter(); // Set the parent XMLReader on the XMLFilter SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); filter.setParent(xr); // Set UnmarshallerHandler as ContentHandler on XMLFilter Unmarshaller unmarshaller = jc.createUnmarshaller(); UnmarshallerHandler unmarshallerHandler = unmarshaller .getUnmarshallerHandler(); filter.setContentHandler(unmarshallerHandler); // Parse the XML InputSource xml = new InputSource("src/blog/namespace/sax/input.xml"); filter.parse(xml); Customer customer = (Customer) unmarshallerHandler.getResult(); // Marshal the Customer object back to XML Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } Output Below is the output from running the demo code. Note how the output contains the namespace qualification based on the metadata. Jane Doe Further Reading If you enjoyed this post then you may also be interested in: JAXB & Namespaces Preventing Entity Expansion Attacks in JAXB
November 10, 2012
· 62,209 Views · 1 Like
article thumbnail
Removing JAXBElement From Your Domain Model
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 mapping. For example in the class below the elements billing-address and shipping-address both correspond to the Address class. In order to be able to round trip the data we need to keep track of which element we unmarshalled. import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlElementRefs({ @XmlElementRef(name = "billing-address"), @XmlElementRef(name = "shipping-address") }) private JAXBElement address; } 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. Address The element name and namespace information from JAXBElement needs to be stored somewhere. Instead of using a JAXBElement, we will set the element name and namespace in a QName property on the Address object (line 10). Since we will not be mapping the qName field it has been marked @XmlTransient (line 9, see JAXB and Unmapped Properties). package blog.jaxbelement.remove; import javax.xml.bind.annotation.*; import javax.xml.namespace.QName; @XmlAccessorType(XmlAccessType.FIELD) public class Address { @XmlTransient private QName qName; private String street; private String city; public QName getQName() { return qName; } public void setQName(QName name) { this.qName = name; } } AddressAdapter We will use an XmlAdapter to convert an instance of Address to/from an instance of JAXBElement. During this conversion we must move the name and namespace information between Address and JAXBElement. package blog.jaxbelement.remove; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.adapters.XmlAdapter; public class AddressAdapter extends XmlAdapter, Address>{ @Override public JAXBElement marshal(Address address) throws Exception { return new JAXBElement(address.getQName(), Address.class, address); } @Override public Address unmarshal(JAXBElement jaxbElement) throws Exception { Address address = jaxbElement.getValue(); address.setQName(jaxbElement.getName()); return address; } } Customer The @XmlJavaTypeAdapter annotation is used to specify the XmlAdapter. The XmlAdapter is responsible for converting an instance of Address to a JAXBElement to satisfy the needs of the @XmlElementRefs mapping. The name property on an @XmlElementRef annotation must match the name specified in a @XmlRootElement or @XmlElementDecl annotation. package blog.jaxbelement.remove; import javax.xml.bind.annotation.*; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlElementRefs({ @XmlElementRef(name = "billing-address"), @XmlElementRef(name = "shipping-address") }) @XmlJavaTypeAdapter(AddressAdapter.class) private Address address; public Address getAddress() { return address; } } ObjectFactory The @XmlElementDecl annotation is used when a class is associated with multiple elements (if a class is associated with only one element then @XmlRootElement can be used). It is placed on a factory method in a class annotated with @XmlRegistry (when generated from an XML schema this class is always called ObjectFactory). The factory method returns the domain object wrapped in an instance of JAXBElement. The JAXBElement has a QName that represents the elements name and namespace URI. package blog.jaxbelement.remove; import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.*; import javax.xml.namespace.QName; @XmlRegistry public class ObjectFactory { static final String BILLING_ADDRESS = "billing-address"; static final String SHIPPING_ADDRESS = "shipping-address"; @XmlElementDecl(name=BILLING_ADDRESS) public JAXBElement createBillingAddress(Address address) { return new JAXBElement(new QName(BILLING_ADDRESS), Address.class, address); } @XmlElementDecl(name=SHIPPING_ADDRESS) public JAXBElement createShippingAddress(Address address) { return new JAXBElement(new QName(SHIPPING_ADDRESS), Address.class, address); } } input.xml Below is the input to the demo code. Note how the address data is wrapped in the billing-address element. The billing-address element was one of the element names we specified in a @XmlElementRef annotation on the Customer class. In the demo code we will change this to the shipping-address element, the other element name we specified in an @XmlElementRef annotation. 123 A Street Any Town Demo In the demo code below we will: Unmarshal the input document (line 14) Set a new QName on the Address object. The QName must correspond to one of the @XmlElementDecl annotations on the ObjectFactory class (line 17). Marshal the Customer object back to XML (line 21). package blog.jaxbelement.remove; import java.io.File; import javax.xml.bind.*; import javax.xml.namespace.QName; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class,ObjectFactory.class); Unmarshaller u = jc.createUnmarshaller(); File xml = new File("src/blog/jaxbelement/remove/input.xml"); Customer customer = (Customer) u.unmarshal(xml); // Change the Wrapper Element customer.getAddress().setQName(new QName(ObjectFactory.SHIPPING_ADDRESS)); Marshaller m = jc.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(customer, System.out); } } Output Below is the output from running the demo code. Note how the address data is now wrapped in the shipping-address element. 123 A Street Any Town
August 30, 2012
· 22,284 Views
article thumbnail
Handle the Middle of a XML Document with JAXB and StAX
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 how this can be done using JAXB with StAX. Note: JAXB (JSR-222) and StAX (JSR-173) implementations are included in the JDK/JRE since Java SE 6. XML (input.xml) We will be using a SOAP message as our sample XML. The outer portions of the XML document represent information relevant to the Web Service and the inner portions (lines 5-8) represent the data we want to convert to our domain model. Jane Doe Java Model Our Java model consists of a single domain class. The concepts in this example also apply to larger domain models. package blog.stax.middle; import javax.xml.bind.annotation.*; @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlAttribute int id; String firstName; String lastName; } Unmarshal Demo To unmarshal from the middle of an XML document all we need to do is the following: Create an XMLStreamReader from the XML input (line 12). Advance the XMLStreamReader to the return element (lines 13-16). Unmarshal an instance of Customer from the XMLStreamReader (line 20) package blog.stax.middle; import javax.xml.bind.*; import javax.xml.stream.*; import javax.xml.transform.stream.StreamSource; public class UnmarshalDemo { public static void main(String[] args) throws Exception { XMLInputFactory xif = XMLInputFactory.newFactory(); StreamSource xml = new StreamSource("src/blog/stax/middle/input.xml"); XMLStreamReader xsr = xif.createXMLStreamReader(xml); xsr.nextTag(); while(!xsr.getLocalName().equals("return")) { xsr.nextTag(); } JAXBContext jc = JAXBContext.newInstance(Customer.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement jb = unmarshaller.unmarshal(xsr, Customer.class); xsr.close(); Customer customer = jb.getValue(); System.out.println(customer.id); System.out.println(customer.firstName); System.out.println(customer.lastName); } } Output Below is the output from running the unmarshal demo. 123 Jane Doe Marshal Demo To marshal to the middle of an XML document all we need to do is the following: Create an XMLStreamWriter for the XML output (line 18). Start the document and write the outer elements (lines 19-22). Set the Marshaller.JAXB_FRAGMENT property on the Marshaller (line 26) to prevent the XML declaration from being written. Marshal an instance of Customer to the XMLStreamWriter (line 27). End the document, this will close any elements that have been opened (line 29). package blog.stax.middle; import javax.xml.bind.*; import javax.xml.namespace.QName; import javax.xml.stream.*; public class MarshalDemo { public static void main(String[] args) throws Exception { Customer customer = new Customer(); customer.id = 123; customer.firstName = "Jane"; customer.lastName = "Doe"; QName root = new QName("response"); JAXBElement je = new JAXBElement(root, Customer.class, customer); XMLOutputFactory xof = XMLOutputFactory.newFactory(); XMLStreamWriter xsw = xof.createXMLStreamWriter(System.out); xsw.writeStartDocument(); xsw.writeStartElement("S", "Envelope", "http://schemas.xmlsoap.org/soap/envelope/"); xsw.writeStartElement("S", "Body", "http://schemas.xmlsoap.org/soap/envelope/"); xsw.writeStartElement("ns0", "findCustomerResponse", "http://service.jaxws.blog/"); JAXBContext jc = JAXBContext.newInstance(Customer.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FRAGMENT, true); marshaller.marshal(je, xsw); xsw.writeEndDocument(); xsw.close(); } } Output Below is the output from running the marshal demo. Note that the output from running the demo code will appear on a single line, I have formatted the output here to make it easier to read. Jane Doe
August 27, 2012
· 18,021 Views
article thumbnail
JAXB's @XmlTransient and Property Order
In previous articles I wrote about how the @XmlTransient annotation can be used at the type level to have a class excluded from the inheritance hierarchy, or at the field/property level to unmap a field/property. In this article I'll demonstrate how doing this impacts the propOrder setting on the @XmlType annotation. Java Model Base This class will serve as the root of the inheritance hierarchy. This will be a mapped class, and as such there is nothing special we need to do, to make this happen. package blog.proporder.xmltransient; public abstract class Base { private int id; public int getId() { return id; } public void setId(int id) { this.id = id; } } Person To exclude a class from being mapped as part of the inheritance hierarchy you simply need to annotate it with @XmlTransient. Any super classes of this class that are not annotated with @XmlTransient (i.e. Base) will still be mapped. package blog.proporder.xmltransient; import javax.xml.bind.annotation.XmlTransient; @XmlTransient public class Person extends Base { private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } } Customer Since the parent class (Person) has been marked @XmlTransient the name property will be treated as part of the Customer class and can be included in the propOrder. The Customer class also extends Base which was not marked @XmlTransient so the id property can not be specified in the propOrder. The propOrder setting must not include a field/property that has been annotated with @XmlTransient. package blog.proporder.xmltransient; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlType(propOrder = { "phoneNumbers", "name"}) public class Customer extends Person { private String password; private List phoneNumbers; @XmlTransient public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } @XmlElement(name = "phone-number") public List getPhoneNumbers() { return phoneNumbers; } public void setPhoneNumbers(List phoneNumbers) { this.phoneNumbers = phoneNumbers; } } Demo Code Below is the demo code that can be used to run this example: package blog.proporder.xmltransient; import java.io.File; import javax.xml.bind.*; 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("input.xml"); Customer customer = (Customer) unmarshaller.unmarshal(xml); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } XML (input.xml/Output) Below is the input to, and output from running the demo code. Note how the properties of classes marked with @XmlTransient are included, but properties marked @XmlTransient are not. 123 555-1111 555-2222 Jane Doe
August 25, 2012
· 49,623 Views
article thumbnail
JAXB and Root Elements
@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 getting a bit confused. In this post I'll demonstrate how @XmlElementDecl can be used to map this use case. XML Schema The XML schema below contains three root elements: customer, billing-address, and shipping-address. The customer element has an anonymous complex type, while billing-address and shipping-address are of the same named type (address-type). createBillingAddress(AddressType value) { return new JAXBElement(_BillingAddress_QNAME, AddressType.class, null, value); } @XmlElementDecl(namespace = "http://www.example.org/customer", name = "shipping-address") public JAXBElement createShippingAddress(AddressType value) { return new JAXBElement(_ShippingAddress_QNAME, AddressType.class, null, value); } } package-info The package-info class is used to specify the namespace mapping (see JAXB & Namespaces). @XmlSchema(namespace = "http://www.example.org/customer", elementFormDefault = XmlNsForm.QUALIFIED) package org.example.customer; import javax.xml.bind.annotation.*; Unmarshal Operation Now we look at the impact of the type of root element when unmarshalling XML. customer.xml Below is a sample XML document with customer as the root element. Remember the customer element had an anonymous complex type. 1 Any Street 2 Another Road shipping.xml Here is a sample XML document with shipping-address as the root element. The shipping-address element had a named complex type. 2 Another Road Unmarshal Demo When unmarshalling XML that corresponds to a class annotated with @XmlRootElement you get an instance of the domain object. But when unmarshalling XML that corresponds to a class annotated with @XmlElementDecl you get the domain object wrapped in an instance of JAXBElement. In this example you may need to use the QName from the JAXBElement to determine if you unmarshalled a billing or shipping address. package org.example.customer; import java.io.File; import javax.xml.bind.*; public class UnmarshalDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Unmarshal Customer File customerXML = new File("src/org/example/customer/customer.xml"); Customer customer = (Customer) unmarshaller.unmarshal(customerXML); // Unmarshal Shipping Address File shippingXML = new File("src/org/example/customer/shipping.xml"); JAXBElement je = (JAXBElement) unmarshaller.unmarshal(shippingXML); AddressType shipping = je.getValue(); } } Unmarshal Demo - JAXBIntrospector If you don't want to deal with remembering whether the result of the unmarshal operation will be a domain object or JAXBElement, then you can use the JAXBIntrospector.getValue(Object) method to always get the domain object. package org.example.customer; import java.io.File; import javax.xml.bind.*; public class JAXBIntrospectorDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Unmarshaller unmarshaller = jc.createUnmarshaller(); // Unmarshal Customer File customerXML = new File("src/org/example/customer/customer.xml"); Customer customer = (Customer) JAXBIntrospector.getValue(unmarshaller .unmarshal(customerXML)); // Unmarshal Shipping Address File shippingXML = new File("src/org/example/customer/shipping.xml"); AddressType shipping = (AddressType) JAXBIntrospector .getValue(unmarshaller.unmarshal(shippingXML)); } } Marshal Operation You can directly marshal an object annotated with @XmlRootElement to XML. Classes corresponding to @XmlElementDecl annotations must first be wrapped in an instance of JAXBElement. The factory method you you annotated with @XmlElementDecl is the easiest way to do this. The factory method is in the ObjectFactory class if you generated your model from an XML schema. package org.example.customer; import javax.xml.bind.*; public class MarshalDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("org.example.customer"); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Create Domain Objects AddressType billingAddress = new AddressType(); billingAddress.setStreet("1 Any Street"); Customer customer = new Customer(); customer.setBillingAddress(billingAddress); // Marshal Customer marshaller.marshal(customer, System.out); // Marshal Billing Address ObjectFactory objectFactory = new ObjectFactory(); JAXBElement je = objectFactory.createBillingAddress(billingAddress); marshaller.marshal(je, System.out); } } Output Below is the output from running the demo code. 1 Any Street 1 Any Street
August 12, 2012
· 222,245 Views · 15 Likes
article thumbnail
JAXB - No Annotations Required
There appears to be a misconception that annotations are required on the model in order to use a JAXB (JSR-222) implementation. The truth is that JAXB is configuration by exception, so annotations are only required when you want to override default behaviour. In this example I'll demonstrate how to use JAXB without providing any metadata. Domain Model I will use the following domain model for this example. Note how there are no annotations of any kind. Customer Customer is the root object in this example. Normally we would annotate it with @XmlRootElement. Later in the demo code you will see how we can use an instance of JAXBElement instead. package blog.defaults; import java.util.List; public class Customer { private String firstName; private String lastName; private List phoneNumbers; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } public List getPhoneNumbers() { return phoneNumbers; } public void setPhoneNumbers(List phoneNumbers) { this.phoneNumbers = phoneNumbers; } } PhoneNumber I have purposefully given the fields in this class nonsense names, so that later when we look at the XML you will be able to see that by default the element names are derived from the properties and not the fields. package blog.defaults; public class PhoneNumber { private String foo; private String bar; public String getType() { return foo; } public void setType(String type) { this.foo = type; } public String getNumber() { return bar; } public void setNumber(String number) { this.bar = number; } } Demo Code Since we haven't used @XmlRootElement (or @XmlElementDecl) to associate a root element with our Customer class we will need to tell JAXB what class we want to unmarshal the XML document to. This is done by using one of the unmarshal methods that take a Class parameter (line 14). This will return a JAXBElement, the Customer object is then accessed by calling getValue on it (line 15). To marshal the object back to XML we need to ensure that it is wrapped in a JAXBElement to supply the root element information (line 17). package blog.defaults; import javax.xml.bind.*; import javax.xml.namespace.QName; import javax.xml.transform.stream.StreamSource; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Customer.class); StreamSource xml = new StreamSource("src/blog/defaults/input.xml"); Unmarshaller unmarshaller = jc.createUnmarshaller(); JAXBElement je1 = unmarshaller.unmarshal(xml, Customer.class); Customer customer = je1.getValue(); JAXBElement je2 = new JAXBElement(new QName("customer"), Customer.class, customer); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(je2, System.out); } } input.xml/Output The following is the input to and output from running the demo code. The first thing we see is that it is a very reasonable XML representation of the data, there aren't any JAXB artifacts. By default JAXB will marshal everything as XML elements, and based on our PhoneNumber class we see that the element names were derived from the property names. Jane Doe 555-1111 work 555-2222 home Further Reading If you enjoyed this post then you may also be interested in: The majority of the articles on this blog describe how to leverage the power of JAXB's metadata to support different use cases, I invite you to check them out: http://blog.bdoughan.com/search/label/JAXB If you are interested in specifying metadata without using annotations, you may be interested in EclipseLink JAXB (MOXy)'s external mapping document: Extending JAXB - Representing Metadata as XML Extending JAXB - Representing Metadata as JSON
August 3, 2012
· 20,446 Views · 1 Like
article thumbnail
Binding to JSON & XML - Handling Null
In a previous post I demonstrated how EclipseLink MOXy can be leveraged to produce both XML and JSON representations of your domain model. The same metadata is used for both representations and MOXy applies it to leverage the capabilities of the media type. In this post I'll focus on how null is handled in each of these representations. Domain Model By default a JAXB (JSR-222) implementation will not include a mapped field/property with a null value in the output. If you want the null value represented then you simply add the following annotation @XmlElement(nillable=true). package blog.json.nillable; import javax.xml.bind.annotation.*; @XmlRootElement public class Customer { private String firstName; private String middleName; private String lastName; public String getFirstName() { return firstName; } public void setFirstName(String firstName) { this.firstName = firstName; } public String getMiddleName() { return middleName; } public void setMiddleName(String middleName) { this.middleName = middleName; } @XmlElement(nillable=true) public String getLastName() { return lastName; } public void setLastName(String lastName) { this.lastName = lastName; } } Demo In the demo code below we will set both the middleName and lastName properties to null. Since we have mapped these properties differently in the domain model we will examine the output to see the impact of using @XmlElement(nillable=true). package blog.json.nillable; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { Customer customer = new Customer(); customer.setFirstName("Jane"); customer.setMiddleName(null); customer.setLastName(null); JAXBContext jc = JAXBContext.newInstance(Customer.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); // Output XML marshaller.marshal(customer, System.out); // Output JSON marshaller.setProperty("eclipselink.media-type", "application/json"); marshaller.marshal(customer, System.out); } } XML Output By default JAXB implementations do not include null values in the output, so there is no element corresponding to the middleName property. Since we annotated the lastName property with @XmlElement(nillable=true) and it had a null value, it is represented in the output. In XML an element with a null value is represented by adding the xsi:nil="true" attribute. Jane JSON Output Just like in the XML output, an entry for the middleName property does not appear in the JSON output. Since we annotated the lastName property with @XmlElement(nillable=true) and it had a null value, it is represented in the output. In JSON a null value is represented with null. { "customer" : { "firstName" : "Jane", "lastName" : null } }
April 25, 2012
· 24,182 Views
article thumbnail
Mapping an Arbitrary List of Objects Using JAXB's @XmlAnyElement and XmlAdapter
The @XmlAnyElement annotation enables a property to handle arbitrary XML elements.
February 22, 2012
· 32,047 Views
article thumbnail
JAXB's @XmlType and propOrder
In this post I will demonstrate how to use the propOrder property on the @XmlType annotation to control the ordering of XML elements.
February 14, 2012
· 62,265 Views
article thumbnail
JAXB and Inheritance - Using XmlAdapter
In previous posts I have covered how to map inheritance relationships in JAXB. This can be done by element name (via @XmlElementRef), by the xsi:type attribute, or in EclipseLink MOXy using another XML attribute (via @XmlDescriminatorNode/@XmlDescriminatorValue). In this post the type indicator will be an XML attribute/element unique to that type, and we will leverage an XmlAdapter to implement this behaviour. Input (input.xml) In this example the possible contact methods are Address and PhoneNumber. If the street attribute is present on the contact-method element we will instantiate an Address object, and if the number attribute is present we will instantiate a PhoneNumber object. Java Model Below is the domain model that will be used for this example. Customer package blog.inheritance.xmladapter; import java.util.List; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Customer { @XmlElement(name="contact-method") private List contactMethods; } ContactMethod ContactMethod and its subclasses (Address & PhoneNumber) will be handled by an XmlAdapter, so the only mapping required is @XmlJavaTypeAdapter to specify the implementation of XmlAdapter. package blog.inheritance.xmladapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlJavaTypeAdapter(ContactMethodAdapter.class) public abstract class ContactMethod { } Address package blog.inheritance.xmladapter; public class Address extends ContactMethod { protected String street; protected String city; } PhoneNumber package blog.inheritance.xmladapter; public class PhoneNumber extends ContactMethod { protected String number; } XmlAdapter (ContactMethodAdapter) The AdaptedContactMethod class has been created and represents the combined properties of ContactMethod, Address, and PhoneNumber. In a marshal operation only the properties corresponding to the type being marshalled are populated. During the unmarshal operation after the AdaptedContactMethod has been built, we can look at which properties have been populated to determine the appropriate subtype that should be returned. package blog.inheritance.xmladapter; import javax.xml.bind.annotation.XmlAttribute; import javax.xml.bind.annotation.adapters.XmlAdapter; public class ContactMethodAdapter extends XmlAdapter { @Override public AdaptedContactMethod marshal(ContactMethod contactMethod) throws Exception { if (null == contactMethod) { return null; } AdaptedContactMethod adaptedContactMethod = new AdaptedContactMethod(); if (contactMethod instanceof Address) { Address address = (Address) contactMethod; adaptedContactMethod.street = address.street; adaptedContactMethod.city = address.city; } else { PhoneNumber phoneNumber = (PhoneNumber) contactMethod; adaptedContactMethod.number = phoneNumber.number; } return adaptedContactMethod; } @Override public ContactMethod unmarshal(AdaptedContactMethod adaptedContactMethod) throws Exception { if (null == adaptedContactMethod) { return null; } if (null != adaptedContactMethod.number) { PhoneNumber phoneNumber = new PhoneNumber(); phoneNumber.number = adaptedContactMethod.number; return phoneNumber; } else { Address address = new Address(); address.street = adaptedContactMethod.street; address.city = adaptedContactMethod.city; return address; } } public static class AdaptedContactMethod { @XmlAttribute public String number; @XmlAttribute public String street; @XmlAttribute public String city; } } Demo Code The following demo code will be used for this example. We will unmarshal the input document, output the type of each object in the collection, and then marshal the objects back to XML. package blog.inheritance.xmladapter; import java.io.File; import javax.xml.bind.*; 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/blog/inheritance/xmladapter/input.xml"); Customer customer = (Customer) unmarshaller.unmarshal(xml); for(ContactMethod contactMethod : customer.getContactMethods()) { System.out.println(contactMethod.getClass()); } Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } Output The following is the output from running the demo code. Note how each of the instances of ContactMethod in the collection are of the appropriate sub-type. class blog.inheritance.xmladapter.PhoneNumber class blog.inheritance.xmladapter.Address class blog.inheritance.xmladapter.PhoneNumber Related Forum Questions Below are a couple of use cases that appeared on Stack Overflow that can be implemented using this approach: eclipselink/Moxy : inheritance and attribute name overloading based on type Jaxb objects with the same name Java/JAXB: Unmarshal XML attributes to specific Java object attributes From http://blog.bdoughan.com/2012/01/jaxb-and-inhertiance-using-xmladapter.html
February 2, 2012
· 44,628 Views · 2 Likes
article thumbnail
How Does JAXB Compare to XMLBeans?
In previous posts I compared JAXB (JSR-222) to Simple and XStream when starting from Java objects. In this post I'll compare JAXB to XMLBeans when starting from an XML schema. I will use XMLBeans 2.5.0 (December 2009) which is the latest release. XML Schema (customer.xsd) Below is the XML schema that will be used to generate our domain models. Generating the Classes XMLBeans Below is the call to generate the XMLBeans classes from our XML schema. For the purposes of this example we will use the -srconly flag to generate only the source. 1 scomp -d out -srconly customer.xsd Below are all the artifacts that are generated by XMLBeans. The XML Schema Binary (XSB) files contain metadata need to perform binding and validation: com/example Address.java CustomerDocument.java PhoneNumber.java com/example/impl AddressImpl.java CustomerDocumentImpl.java PhoneNumberImpl.java schemaorg_apache_xmlbeans element/http_3A_2F_2Fwww_2Eexample_2Ecom customer.xsb javaname/com/example Address.xsb CustomerDocument.xsb PhoneNumber.xsb CustomerDocument Customer.xsb namespace/http_3A_2F_2Fwww_2Eexample_2Ecom xmlns.xsb src customer.xsd system/s16C99350D7D3A2544A7BFD5E35CA8BC8 address6f49type.xsb customer3fdddoctype.xsb customer11d7elemtype.xsb customerelement.xsb index.xsb phonenumber9c83type.xsb TypeSystemHolder.class type/http_3A_2F_2Fwww_2Eexample_2Ecom address.xsb phone_2Dnumber.xsb JAXB Below is the call to generate the JAXB classes from an XML schema: 1 xjc -d out customer.xsd Below are all the artifacts that are generated by JAXB. Note how many fewer artifacts are created: com.example Address.java Customer.java ObjectFactory.java package-info.java PhoneNumber.java Java Model - XMLBeans XMLBeans produces a set of Java interfaces that are backed by implementation classes. Below we will examine one of these pairs. Address This is one of the interfaces that is generated by XMLBeans. There are a few interesting things worth noting: This interface exposes POJO properties (line 24), and a DOM like model (line 29). This interface includes a factory (line 66). This factory is used for creating instances of the Address object (line 68), and for unmarshalling instances of Address from XML (line 75). package com.example; /** * An XML address(@http://www.example.com). * * This is a complex type. */ public interface Address extends org.apache.xmlbeans.XmlObject { public static final org.apache.xmlbeans.SchemaType type = (org.apache.xmlbeans.SchemaType) org.apache.xmlbeans.XmlBeans.typeSystemForClassLoader(Address.class.getClassLoader(), "schemaorg_apache_xmlbeans.system.s16C99350D7D3A2544A7BFD5E35CA8BC8").resolveHandle("address6f49type"); /** * Gets the "street" element */ java.lang.String getStreet(); /** * Gets (as xml) the "street" element */ org.apache.xmlbeans.XmlString xgetStreet(); /** * Sets the "street" element */ void setStreet(java.lang.String street); /** * Sets (as xml) the "street" element */ void xsetStreet(org.apache.xmlbeans.XmlString street); /** * Gets the "city" element */ java.lang.String getCity(); /** * Gets (as xml) the "city" element */ org.apache.xmlbeans.XmlString xgetCity(); /** * Sets the "city" element */ void setCity(java.lang.String city); /** * Sets (as xml) the "city" element */ void xsetCity(org.apache.xmlbeans.XmlString city); /** * A factory class with static methods for creating instances * of this type. */ public static final class Factory { public static com.example.Address newInstance() { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newInstance( type, null ); } public static com.example.Address newInstance(org.apache.xmlbeans.XmlOptions options) { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newInstance( type, options ); } /** @param xmlAsString the string value to parse */ public static com.example.Address parse(java.lang.String xmlAsString) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, null ); } public static com.example.Address parse(java.lang.String xmlAsString, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xmlAsString, type, options ); } /** @param file the file from which to load an xml document */ public static com.example.Address parse(java.io.File file) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( file, type, null ); } public static com.example.Address parse(java.io.File file, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( file, type, options ); } public static com.example.Address parse(java.net.URL u) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( u, type, null ); } public static com.example.Address parse(java.net.URL u, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( u, type, options ); } public static com.example.Address parse(java.io.InputStream is) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( is, type, null ); } public static com.example.Address parse(java.io.InputStream is, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( is, type, options ); } public static com.example.Address parse(java.io.Reader r) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( r, type, null ); } public static com.example.Address parse(java.io.Reader r, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, java.io.IOException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( r, type, options ); } public static com.example.Address parse(javax.xml.stream.XMLStreamReader sr) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( sr, type, null ); } public static com.example.Address parse(javax.xml.stream.XMLStreamReader sr, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( sr, type, options ); } public static com.example.Address parse(org.w3c.dom.Node node) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( node, type, null ); } public static com.example.Address parse(org.w3c.dom.Node node, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( node, type, options ); } /** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */ public static com.example.Address parse(org.apache.xmlbeans.xml.stream.XMLInputStream xis) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xis, type, null ); } /** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */ public static com.example.Address parse(org.apache.xmlbeans.xml.stream.XMLInputStream xis, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException { return (com.example.Address) org.apache.xmlbeans.XmlBeans.getContextTypeLoader().parse( xis, type, options ); } /** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */ public static org.apache.xmlbeans.xml.stream.XMLInputStream newValidatingXMLInputStream(org.apache.xmlbeans.xml.stream.XMLInputStream xis) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException { return org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newValidatingXMLInputStream( xis, type, null ); } /** @deprecated {@link org.apache.xmlbeans.xml.stream.XMLInputStream} */ public static org.apache.xmlbeans.xml.stream.XMLInputStream newValidatingXMLInputStream(org.apache.xmlbeans.xml.stream.XMLInputStream xis, org.apache.xmlbeans.XmlOptions options) throws org.apache.xmlbeans.XmlException, org.apache.xmlbeans.xml.stream.XMLStreamException { return org.apache.xmlbeans.XmlBeans.getContextTypeLoader().newValidatingXMLInputStream( xis, type, options ); } private Factory() { } // No instance of this class allowed } } AddressImpl Below is the source for the implementation class: /** * XML Type: address * Namespace: http://www.example.com * Java type: com.example.Address * * Automatically generated - do not modify. */ package com.example.impl; /** * An XML address(@http://www.example.com). * * This is a complex type. */ public class AddressImpl extends org.apache.xmlbeans.impl.values.XmlComplexContentImpl implements com.example.Address { private static final long serialVersionUID = 1L; public AddressImpl(org.apache.xmlbeans.SchemaType sType) { super(sType); } private static final javax.xml.namespace.QName STREET$0 = new javax.xml.namespace.QName("http://www.example.com", "street"); private static final javax.xml.namespace.QName CITY$2 = new javax.xml.namespace.QName("http://www.example.com", "city"); /** * Gets the "street" element */ public java.lang.String getStreet() { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.SimpleValue target = null; target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(STREET$0, 0); if (target == null) { return null; } return target.getStringValue(); } } /** * Gets (as xml) the "street" element */ public org.apache.xmlbeans.XmlString xgetStreet() { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.XmlString target = null; target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(STREET$0, 0); return target; } } /** * Sets the "street" element */ public void setStreet(java.lang.String street) { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.SimpleValue target = null; target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(STREET$0, 0); if (target == null) { target = (org.apache.xmlbeans.SimpleValue)get_store().add_element_user(STREET$0); } target.setStringValue(street); } } /** * Sets (as xml) the "street" element */ public void xsetStreet(org.apache.xmlbeans.XmlString street) { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.XmlString target = null; target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(STREET$0, 0); if (target == null) { target = (org.apache.xmlbeans.XmlString)get_store().add_element_user(STREET$0); } target.set(street); } } /** * Gets the "city" element */ public java.lang.String getCity() { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.SimpleValue target = null; target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(CITY$2, 0); if (target == null) { return null; } return target.getStringValue(); } } /** * Gets (as xml) the "city" element */ public org.apache.xmlbeans.XmlString xgetCity() { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.XmlString target = null; target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(CITY$2, 0); return target; } } /** * Sets the "city" element */ public void setCity(java.lang.String city) { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.SimpleValue target = null; target = (org.apache.xmlbeans.SimpleValue)get_store().find_element_user(CITY$2, 0); if (target == null) { target = (org.apache.xmlbeans.SimpleValue)get_store().add_element_user(CITY$2); } target.setStringValue(city); } } /** * Sets (as xml) the "city" element */ public void xsetCity(org.apache.xmlbeans.XmlString city) { synchronized (monitor()) { check_orphaned(); org.apache.xmlbeans.XmlString target = null; target = (org.apache.xmlbeans.XmlString)get_store().find_element_user(CITY$2, 0); if (target == null) { target = (org.apache.xmlbeans.XmlString)get_store().add_element_user(CITY$2); } target.set(city); } } } Java Model - JAXB JAXB implementations produce annotated POJOs. The generated classes closely resemble the ones we created by hand in the comparisons to Simple and XStream. Address // // This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, vJAXB 2.1.10 in JDK 6 // See http://java.sun.com/xml/jaxb // Any modifications to this file will be lost upon recompilation of the source schema. // Generated on: 2012.01.23 at 01:19:09 PM EST // package com.example; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlType; /** * Java class for address complex type. * * The following schema fragment specifies the expected content contained within this class. * * * * * * * * * * * * * * * */ @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "address", propOrder = { "street", "city" }) public class Address { @XmlElement(required = true) protected String street; @XmlElement(required = true) protected String city; /** * Gets the value of the street property. * * @return * possible object is * {@link String } * */ public String getStreet() { return street; } /** * Sets the value of the street property. * * @param value * allowed object is * {@link String } * */ public void setStreet(String value) { this.street = value; } /** * Gets the value of the city property. * * @return * possible object is * {@link String } * */ public String getCity() { return city; } /** * Sets the value of the city property. * * @param value * allowed object is * {@link String } * */ public void setCity(String value) { this.city = value; } } Demo Code In the demo code we will unmarshal an XML file, add a phone number to the resulting customer object, and then marshal the customer back to XML. XMLBeans With XMLBeans the generated domain model is used to unmarshal (line 12) and marshal (line 19). The generated model also contains methods for interacting with collections (line 15), this is necessary as XMLBeans represent collection properties as arrays. package com.example; import java.io.File; import com.example.CustomerDocument.Customer; public class Demo { public static void main(String[] args) throws Exception { File xml = new File("src/com/example/input.xml"); CustomerDocument customerDocument = CustomerDocument.Factory.parse(xml); Customer customer = customerDocument.getCustomer(); PhoneNumber homePhoneNumber = customer.addNewPhoneNumber(); homePhoneNumber.setType("home"); homePhoneNumber.set("555-HOME"); customerDocument.save(System.out); } } JAXB JAXB separates the marshal/unmarshal calls into the standard runtime APIs (lines 9, 13 and 22). A java.util.List is used for collection properties (line 18). package com.example; import java.io.File; import javax.xml.bind.*; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance("com.example"); File xml = new File("src/com/example/input.xml"); Unmarshaller unmarshaller = jc.createUnmarshaller(); Customer customer = (Customer) unmarshaller.unmarshal(xml); PhoneNumber homePhoneNumber = new PhoneNumber(); homePhoneNumber.setType("home"); homePhoneNumber.setValue("555-HOME"); customer.getPhoneNumber().add(homePhoneNumber); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(customer, System.out); } } Summary Both XMLBeans and JAXB produce Java models that make it easy for developers to interact with XML. The JAXB model however is annotated POJOs which has the following advantages: JPA annotations could easily be applied to the JAXB model enabling the model to be persisted in a relational database. Once generated the JAXB model could be modified to handle changes in the XML schema, the XMLBeans model would need to be regenerated. Starting with Java SE 6 no additional compile/runtime dependencies are required for the JAXB model. There are multiple JAXB implementations available: EclipseLink MOXy, Metro, Apache JaxMe, etc. JAXB is the standard binding layer for JAX-WS (SOAP) and JAX-RS (RESTful) Web Services. From http://blog.bdoughan.com/2012/01/how-does-jaxb-compare-to-xmlbeans.html
February 1, 2012
· 24,940 Views
article thumbnail
XML Schema to Java - Generating XmlAdapters
In previous posts I have demonstrated how powerful JAXB's XmlAdapter can be when starting from domain objects. In this example I will demonstrate how to leverage an XmlAdapter when generating an object model from an XML schema. This post was inspired by an answer I gave to a question on Stack Overflow (feel free to up vote). XMLSchema (format.xsd) The following is the XML schema that will be used for this example. The interesting portion is a type called NumberCodeValueType. This type has a specified pattern requiring it be a seven digit number. This number can have leading zeros which would not be marshalled by JAXB's default conversion of numbers. NumberFormatter Since JAXB's default number to String algorithm will not match our schema requirements, we will need to write our own formatter. We are required to provide two static methods one that coverts our type to the desired XML format, and another that converts from the XML format. package blog.xmladapter.bindings; public class NumberFormatter { public static String printInt(Integer value) { String result = String.valueOf(value); for(int x=0, length = 7 - result.length(); x XJC Call The bindings file is referenced in the XJC call as: xjc -d out -p blog.xmladapter.bindings -b bindings.xml format.xsd Adapter1 This will cause an XmlAdapter to be created that leverages the formatter: package blog.xmladapter.bindings; import javax.xml.bind.annotation.adapters.XmlAdapter; public class Adapter1 extends XmlAdapter { public Integer unmarshal(String value) { return (blog.xmladapter.bindings.NumberFormatter.parseInt(value)); } public String marshal(Integer value) { return (blog.xmladapter.bindings.NumberFormatter.printInt(value)); } } Root The XmlAdapter will be referenced from the domain object using the @XmlJavaTypeAdapter annotation: package blog.xmladapter.bindings; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; @XmlAccessorType(XmlAccessType.FIELD) @XmlType(name = "", propOrder = { "number" }) @XmlRootElement(name = "root") public class Root { @XmlElement(required = true, type = String.class) @XmlJavaTypeAdapter(Adapter1 .class) protected Integer number; public Integer getNumber() { return number; } public void setNumber(Integer value) { this.number = value; } } Demo Now if we run the following demo code: package blog.xmladapter.bindings; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Root.class); Root root = new Root(); root.setNumber(4); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } Output We will get the desired output: 0000004 From http://blog.bdoughan.com/2011/08/xml-schema-to-java-generating.html
December 30, 2011
· 13,405 Views
article thumbnail
JAXB and Joda-Time: Dates and Times
Joda-Time provides an alternative to the Date and Calendar classes currently provided in Java SE. Since they are provided in a separate library JAXB does not provide a default mapping for these classes. We can supply the necessary mapping via XmlAdapters. In this post we will cover the following Joda-Time types: DateTime, DateMidnight, LocalDate, LocalTime, LocalDateTime. Java Model The following domain model will be used for this example: package blog.jodatime; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; @XmlRootElement @XmlType(propOrder={ "dateTime", "dateMidnight", "localDate", "localTime", "localDateTime"}) public class Root { private DateTime dateTime; private DateMidnight dateMidnight; private LocalDate localDate; private LocalTime localTime; private LocalDateTime localDateTime; public DateTime getDateTime() { return dateTime; } public void setDateTime(DateTime dateTime) { this.dateTime = dateTime; } public DateMidnight getDateMidnight() { return dateMidnight; } public void setDateMidnight(DateMidnight dateMidnight) { this.dateMidnight = dateMidnight; } public LocalDate getLocalDate() { return localDate; } public void setLocalDate(LocalDate localDate) { this.localDate = localDate; } public LocalTime getLocalTime() { return localTime; } public void setLocalTime(LocalTime localTime) { this.localTime = localTime; } public LocalDateTime getLocalDateTime() { return localDateTime; } public void setLocalDateTime(LocalDateTime localDateTime) { this.localDateTime = localDateTime; } } XmlAdapters Since Joda-Time and XML Schema both represent data and time information according to ISO 8601 the implementation of the XmlAdapters is quite trivial. DateTimeAdapter package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.DateTime; public class DateTimeAdapter extends XmlAdapter{ public DateTime unmarshal(String v) throws Exception { return new DateTime(v); } public String marshal(DateTime v) throws Exception { return v.toString(); } } DateMidnightAdapter package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.DateMidnight; public class DateMidnightAdapter extends XmlAdapter { public DateMidnight unmarshal(String v) throws Exception { return new DateMidnight(v); } public String marshal(DateMidnight v) throws Exception { return v.toString(); } } LocalDateAdapter package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.LocalDate; public class LocalDateAdapter extends XmlAdapter{ public LocalDate unmarshal(String v) throws Exception { return new LocalDate(v); } public String marshal(LocalDate v) throws Exception { return v.toString(); } } LocalTimeAdapter package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.LocalTime; public class LocalTimeAdapter extends XmlAdapter { public LocalTime unmarshal(String v) throws Exception { return new LocalTime(v); } public String marshal(LocalTime v) throws Exception { return v.toString(); } } LocalDateTimeAdapter package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlAdapter; import org.joda.time.LocalDateTime; public class LocalDateTimeAdapter extends XmlAdapter{ public LocalDateTime unmarshal(String v) throws Exception { return new LocalDateTime(v); } public String marshal(LocalDateTime v) throws Exception { return v.toString(); } } Registering the XmlAdapters We will use the @XmlJavaTypeAdapters annotation to register the Joda-Time types at the package level. This means that whenever these types are found on a field/property on a class within this package the XmlAdapter will automatically be applied. @XmlJavaTypeAdapters({ @XmlJavaTypeAdapter(type=DateTime.class, value=DateTimeAdapter.class), @XmlJavaTypeAdapter(type=DateMidnight.class, value=DateMidnightAdapter.class), @XmlJavaTypeAdapter(type=LocalDate.class, value=LocalDateAdapter.class), @XmlJavaTypeAdapter(type=LocalTime.class, value=LocalTimeAdapter.class), @XmlJavaTypeAdapter(type=LocalDateTime.class, value=LocalDateTimeAdapter.class) }) package blog.jodatime; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter; import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapters; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; Demo To run the following demo you will need the Joda-Time jar on your classpath. It can be obtained here: http://sourceforge.net/projects/joda-time/files/joda-time/ package blog.jodatime; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import org.joda.time.DateMidnight; import org.joda.time.DateTime; import org.joda.time.LocalDate; import org.joda.time.LocalDateTime; import org.joda.time.LocalTime; public class Demo { public static void main(String[] args) throws Exception { Root root = new Root(); root.setDateTime(new DateTime(2011, 5, 30, 11, 2, 30, 0)); root.setDateMidnight(new DateMidnight(2011, 5, 30)); root.setLocalDate(new LocalDate(2011, 5, 30)); root.setLocalTime(new LocalTime(11, 2, 30)); root.setLocalDateTime(new LocalDateTime(2011, 5, 30, 11, 2, 30)); JAXBContext jc = JAXBContext.newInstance(Root.class); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(root, System.out); } } Output The following is the output from our demo code: 2011-05-30T11:02:30.000-04:00 2011-05-30T00:00:00.000-04:00 2011-05-30 11:02:30.000 2011-05-30T11:02:30.000 From http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html
December 29, 2011
· 15,028 Views
article thumbnail
Mapping Objects to Multiple XML Schemas - Weather Example
I have written previous posts on EclipseLink JAXB (MOXy)'s @XmlPath and external binding file extensions. In this post I will demonstrate how powerful these extensions are by mapping a single object model to two different XML schemas. To make the example more "real", the XML data will come from two different services that provide weather information: Google and Yahoo. Java Model The following domain model will be used for this post: Weather Report package blog.weather; import java.util.List; public class WeatherReport { private String location; private int currentTemperature; private String currentCondition; private List forecast; } Forecast package blog.weather; public class Forecast { private String dayOfTheWeek; private int low; private int high; private String condition; } Google Weather API First we will leverage Google's Weather API. The following URL will be used to access the weather data for Ottawa, Canada: http://www.google.com/ig/api?weather=Ottawa The following is the result of performing the above query at time I was writing this article. I have highlighted the portions of the XML document that we will map to: Java Model - Mapped to Google's XML Schema via Annotations We will map the result of the Google weather API via a combination of standard JAXB and MOXy extension annotations. Weather Report package blog.weather; import java.util.List; import javax.xml.bind.annotation.XmlAccessorType; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlRootElement; import javax.xml.bind.annotation.XmlType; import org.eclipse.persistence.oxm.annotations.XmlPath; @XmlRootElement(name="xml_api_reply") @XmlType(propOrder={"location", "currentCondition", "currentTemperature", "forecast"}) @XmlAccessorType(XmlAccessType.FIELD) public class WeatherReport { @XmlPath("weather/forecast_information/city/@data") private String location; @XmlPath("weather/current_conditions/temp_f/@data") private int currentTemperature; @XmlPath("weather/current_conditions/condition/@data") private String currentCondition; @XmlPath("weather/forecast_conditions") private List forecast; } Forecast package blog.weather; import org.eclipse.persistence.oxm.annotations.XmlPath; public class Forecast { @XmlPath("day_of_week/@data") private String dayOfTheWeek; @XmlPath("low/@data") private int low; @XmlPath("high/@data") private int high; @XmlPath("condition/@data") private String condition; } Specify MOXy as the JAXB Provider (jaxb.properties) To configure MOXy as your JAXB provider simply add a file named jaxb.properties in the same package as your domain model with the following entry: javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory For more information see: Specifying EclipseLink MOXy as Your JAXB Provider. Demo The following demo code will read the XML data for Google's weather service, and marshal the objects back to XML: package blog.weather; import java.net.URL; import javax.xml.bind.*; public class GoogleDemo { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(WeatherReport.class); Unmarshaller unmarshaller = jc.createUnmarshaller(); URL url = new URL("http://www.google.com/ig/api?weather=Ottawa"); WeatherReport weatherReport = (WeatherReport) unmarshaller.unmarshal(url); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(weatherReport, System.out); } } Output Below is the result of running the demo code. The output represents the portion of the XML document that we had mapped to: expand source Yahoo Weather API The following URL will be used to access the weather data for Ottawa using the Yahoo Weather API (3369 is the WOEID for Ottawa): http://weather.yahooapis.com/forecastrss?w=3369 The following is the result of performing the above query at time I was writing this article: http://us.rd.yahoo.com/dailynews/rss/weather/Ottawa__CA/*http://weather.yahoo.com/forecast/CAXX0343_f.html Yahoo! Weather for Ottawa, CA en-us Thu, 08 Sep 2011 10:58 am EDT 60 142 18 http://weather.yahoo.com http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif 45.42 -75.69 http://us.rd.yahoo.com/dailynews/rss/weather/Ottawa__CA/*http://weather.yahoo.com/forecast/CAXX0343_f.html Thu, 08 Sep 2011 10:58 am EDT Current Conditions: Mostly Cloudy, 66 F Forecast: Thu - Partly Cloudy. High: 75 Low: 57 Fri - Partly Cloudy. High: 79 Low: 53 Full Forecast at Yahoo! Weather (provided by The Weather Channel) ]]> CAXX0343_2011_09_09_7_00_EDT Java Model - Mapped to Yahoo's XML Schema via XML Metadata Since we can not supply a second set of mappings to an object model via annotations, we must supply subsequent mappings by leveraging MOXy's XML metadata. By default MOXy's mapping document is used to supplement any annotations that are specified on the model. However, if the xml-mapping-metadata-complete flag is set, then the XML metadata will completely replace the metadata provided by annotations (the annotations for the Google mapping will remain on the POJOs, but the xml-mapping-metadata-complete flag tells MOXy to ignore them). Demo The following demo code will read the XML data for Yahoo's weather service, and marshal the objects back to XML. Due to a MOXy bug regarding unmapped CDATA sections (https://bugs.eclipse.org/357145, this bug has been fixed in EclipseLink 2.3.1), a filtered XMLStreamReader was used to remove it from the XML input: package blog.weather; import java.util.HashMap; import java.util.Map; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.Unmarshaller; import javax.xml.stream.StreamFilter; import javax.xml.stream.XMLInputFactory; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.stream.StreamSource; import org.eclipse.persistence.jaxb.JAXBContextFactory; public class YahooDemo { public static void main(String[] args) throws Exception { Map properties = new HashMap(1); properties.put(JAXBContextFactory.ECLIPSELINK_OXM_XML_KEY, "blog/weather/yahoo-binding.xml"); JAXBContext jc = JAXBContext.newInstance(new Class[] {WeatherReport.class}, properties); XMLInputFactory xif = XMLInputFactory.newFactory(); StreamSource xml = new StreamSource("http://weather.yahooapis.com/forecastrss?w=3369"); XMLStreamReader xsr = xif.createXMLStreamReader(xml); xsr = xif.createFilteredReader(xsr, new CDATAFilter()); Unmarshaller unmarshaller = jc.createUnmarshaller(); WeatherReport weatherReport = (WeatherReport) unmarshaller.unmarshal(xsr); Marshaller marshaller = jc.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); marshaller.marshal(weatherReport, System.out); } private static class CDATAFilter implements StreamFilter { public boolean accept(XMLStreamReader xsr) { return XMLStreamReader.CDATA != xsr.getEventType(); } } } Output Below is the result of running the demo code. The output represents the portion of the XML document that we had mapped to: From http://blog.bdoughan.com/2011/09/mapping-objects-to-multiple-xml-schemas.html
December 28, 2011
· 8,357 Views
article thumbnail
Reusing Generated JAXB Classes
In this post I will demonstrate how to leverage the -episode XJC extension to reuse classes previously generated from.an XML schema. This is useful when an XML schema is imported by other XML schemas and you do not want the same classes generated each time. Imported Schema (Product.xsd) The following XML schema represents basic information about a product. Product is a common concept in this example domain so I have decided to define one representation that can be leveraged by other schemas, rather than having each schema define its own representation of product information. Since multiple XML schemas import Product.xsd we can leverage episode files so that the classes corresponding to Product.xsd are only generated once. The following XJC call demonstrates how to generate an episode file called product.episode along with the generated classes: xjc -d out -episode product.episode Product.xsd Importing Schema (ProductPurchaseRequest.xsd) Below is an example of an XML schema that imports Product.xsd: When we generate classes from this XML schema we will reference the episode file we created when we generated Java classes from Product.xsd. If we do not specify the episode file then classes will be generated for both ProductPurchaseRequest.xsd and Product.xsd: xjc -d out ProductPurchaseRequest.xsd -extension -b product.episode Another Importing Schema (ProductQuoteRequest.xsd) Below is another example of an XML schema that imports Product.xsd: Again when we generate classes from this XML schema we will reference the episode file we created when we generated Java classes from Product.xsd. xjc -d out ProductQuoteRequest.xsd -extension -b product.episode How Does it Work? (product.episode) For those of you curious how this works. The episode file generated by XJC is really just a standard JAXB bindings file that is used to customize the class generation. This generated bindings/episode file contains entries that tells XJC that a class already exists for this type. You could write this file by hand, but -episode flag to XJC does it for you. From http://blog.bdoughan.com/2011/12/reusing-generated-jaxb-classes.html
December 6, 2011
· 15,284 Views
article thumbnail
JAXB and Namespace Prefixes
In a previous post I covered how to use namespace qualification with JAXB. In this post I will cover how to control the prefixes that are used. This is not covered in the JAXB (JSR-222) specification but I will demonstrate the extensions available in both the reference and EclipseLink MOXy implementations for handling this use case Java Model The following domain model will be used for this post. The @XmlRootElement and @XmlElement annotation are used to specify the appropriate namespace qualification. package blog.prefix; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlRootElement; @XmlRootElement(namespace="http://www.example.com/FOO") public class Root { private String a; private String b; private String c; @XmlElement(namespace="http://www.example.com/BAR") public String getA() { return a; } public void setA(String a) { this.a = a; } @XmlElement(namespace="http://www.example.com/FOO") public String getB() { return b; } public void setB(String b) { this.b = b; } @XmlElement(namespace="http://www.example.com/OTHER") public String getC() { return c; } public void setC(String c) { this.c = c; } } Demo Code We will use the following code to populate the domain model and produce the XML. package blog.prefix; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext ctx = JAXBContext.newInstance(Root.class); Root root = new Root(); root.setA("A"); root.setB("B"); root.setC("OTHER"); Marshaller m = ctx.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); m.marshal(root, System.out); } } Output XML like the following is produced by default. The JAXB implementation has arbitrarily assigned prefixes to the namespace URIs specified in the domain model: A B OTHER Specify Prefix Mappings with JAXB RI & Metro JAXB The reference and Metro implementations of JAXB provide a mechanism called NamespacePrefixMapper to control the prefixes that will be assigned to namespaces. NamespacePrefixMapper package blog.prefix; import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper; //import com.sun.xml.bind.marshaller.NamespacePrefixMapper; public class MyNamespaceMapper extends NamespacePrefixMapper { private static final String FOO_PREFIX = ""; // DEFAULT NAMESPACE private static final String FOO_URI = "http://www.example.com/FOO"; private static final String BAR_PREFIX = "bar"; private static final String BAR_URI = "http://www.example.com/BAR"; @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if(FOO_URI.equals(namespaceUri)) { return FOO_PREFIX; } else if(BAR_URI.equals(namespaceUri)) { return BAR_PREFIX; } return suggestion; } @Override public String[] getPreDeclaredNamespaceUris() { return new String[] { FOO_URI, BAR_URI }; } } Demo Code The NamespacePrefixMapper is set on an instance of Marshaller. I would recommend wrapping the setPropery call in a try/catch block so that your application does not fail if you change JAXB implementations. package blog.prefix; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; public class Demo { public static void main(String[] args) throws Exception { JAXBContext ctx = JAXBContext.newInstance(Root.class); Root root = new Root(); root.setA("A"); root.setB("B"); root.setC("OTHER"); Marshaller m = ctx.createMarshaller(); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true); try { m.setProperty("com.sun.xml.internal.bind.namespacePrefixMapper", new MyNamespaceMapper()); //m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new MyNamespaceMapper()); } catch(PropertyException e) { // In case another JAXB implementation is used } m.marshal(root, System.out); } } Output The resulting document now uses the NamespacePrefixMapper to determine the prefixes that should be used in the resulting document. A B OTHER Specify Prefix Mappings with EclipseLink JAXB (MOXy) MOXy will use the namespace prefixes as they are defined on the @XmlSchema annotation. In order for MOXy to be able to use the default namespace the elementFormDefault property on the @XmlSchema annotation must be set to XmlNsForm.QUALIFIED. package-info XmlSchema( elementFormDefault=XmlNsForm.QUALIFIED, namespace="http://www.example.com/FOO", xmlns={@XmlNs(prefix="bar", namespaceURI="http://www.example.com/BAR")} ) package blog.prefix; import javax.xml.bind.annotation.XmlNs; import javax.xml.bind.annotation.XmlNsForm; import javax.xml.bind.annotation.XmlSchema; Output The resulting document now uses the xmlns setting from the @XmlSchema annotation to determine the prefixes that should be used in the resulting document. A B OTHER Further Reading If you enjoyed this post then you may also be interested in: JAXB & Namespaces Specifying EclipseLink MOXy as Your JAXB Provider From http://blog.bdoughan.com/2011/11/jaxb-and-namespace-prefixes.html
December 3, 2011
· 238,915 Views · 8 Likes
article thumbnail
JAXB (XJC) Imported Schemas and XML Catalogs
Import allows one XML schema to reference elements and types from another XML schema.
October 22, 2011
· 37,206 Views

Comments

Swing links of the week, February 9th

Nov 14, 2013 · Jonathan Giles

Interesting article. Below is some additional information.

JAXB came to Java with Java 6.

An implementation of JAXB 2 (JSR-222) implementation is included in Java SE 6. It will work with Java SE 5 and above. JAXB 2 was introduced as part of Java EE 5.

I didn't know that there are so many other libraries for XML data binding, nor I can explain why so many different implementations exist. It seems every firm and organization wrote their own implementation

This statement is pretty true. A couple things to note are:

  • EclipseLink MOXy is a JAXB 2 implementation that conforms to the same specification and compliance tests as the reference implementation. MOXy is the default JAXB provider in WebLogic as of WebLogic 12.1.1.
  • TopLink's object-to-XML offering (which was open sourced as EclipseLink MOXy) supported JAXB 1 (JSR-031)
  • Apache had a JAXB implementation called JaxMe
  • Members of object-to-XML libraries such as TopLink (myself, Blaise Doughan), XMLBeans (David Bau), JiBX (Dennis M. Sosnosk) participated in the creation of JSR-222.
XStream – XStreamely Easy Way to Work with XML Data in Java

Apr 24, 2013 · mitchp

The ability to provide metadata programmatically is a key feature of XStream (although other XML-binding solutions have this as well), but XStream does have its weaknesses such as support for namespaces (see http://xstream.codehaus.org/faq.html#XML_namespaces). Below is a link to an article I wrote comparing XStream with JAXB (JSR-222), note I'm the EclipseLink JAXB (MOXy) lead.

  • How Does JAXB Compare to XStream?
Unlock User in asp.net membership login system

Apr 24, 2013 · Sangam Uprety

The ability to provide metadata programmatically is a key feature of XStream (although other XML-binding solutions have this as well), but XStream does have its weaknesses such as support for namespaces (see http://xstream.codehaus.org/faq.html#XML_namespaces). Below is a link to an article I wrote comparing XStream with JAXB (JSR-222), note I'm the EclipseLink JAXB (MOXy) lead.

  • How Does JAXB Compare to XStream?
C# Partial Methods

Mar 17, 2013 · Richard Carr

In this post an XmlAdapter is only required to unmarshal the document from use case #4. If a JAXB (JSR-222) impl can produce XML without an XmlAdapter then it can consume that XML without an XmlAdapter.

C# Partial Methods

Mar 17, 2013 · Richard Carr

In this post an XmlAdapter is only required to unmarshal the document from use case #4. If a JAXB (JSR-222) impl can produce XML without an XmlAdapter then it can consume that XML without an XmlAdapter.

JAXB and java.util.Map

Mar 17, 2013 · James Sugrue

In this post an XmlAdapter is only required to unmarshal the document from use case #4. If a JAXB (JSR-222) impl can produce XML without an XmlAdapter then it can consume that XML without an XmlAdapter.

JAXB and java.util.Map

Mar 17, 2013 · James Sugrue

In this post an XmlAdapter is only required to unmarshal the document from use case #4. If a JAXB (JSR-222) impl can produce XML without an XmlAdapter then it can consume that XML without an XmlAdapter.

Using JAXB With XSLT to Produce HTML

Nov 22, 2012 · James Sugrue

The key point to this post is that an XSLT transform can be applied to a Java model annotated with JAXB (JSR-222) annotations. One reason HTML was used as the result as the document would be sufficiently different from the source. The other reason is that this is a common use case in the creation of JAX-RS (JSR-311) services that return HTML.


VIEWS - they offer no optimisation benefits; they are simply inline macros

Jun 22, 2012 · Tony Thomas

Hi Goel,

Here is a link to an article I wrote that explains how to leverage XmlAdapters when starting from an XSD:

  • http://java.dzone.com/articles/xml-schema-java-generating

-Blaise

VIEWS - they offer no optimisation benefits; they are simply inline macros

Jun 22, 2012 · Tony Thomas

Hi Goel,

Here is a link to an article I wrote that explains how to leverage XmlAdapters when starting from an XSD:

  • http://java.dzone.com/articles/xml-schema-java-generating

-Blaise

VIEWS - they offer no optimisation benefits; they are simply inline macros

Jun 22, 2012 · Tony Thomas

Hi Goel,

Here is a link to an article I wrote that explains how to leverage XmlAdapters when starting from an XSD:

  • http://java.dzone.com/articles/xml-schema-java-generating

-Blaise

JRuby Performance with the Java 6 Port for OS X (Tiger and Leopard)

Jun 22, 2012 · Mr B Loid

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

JRuby Performance with the Java 6 Port for OS X (Tiger and Leopard)

Jun 22, 2012 · Mr B Loid

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

XML Schema to Java - Generating XmlAdapters

Jun 22, 2012 · James Sugrue

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

XML Schema to Java - Generating XmlAdapters

Jun 22, 2012 · James Sugrue

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

XML Schema to Java - Generating XmlAdapters

Jun 22, 2012 · James Sugrue

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

JRuby Performance with the Java 6 Port for OS X (Tiger and Leopard)

Jun 22, 2012 · Mr B Loid

Hi Afandi,

The "name" attribute on the "jxb:javaType" element specifies the type of the generated field/property, and is required according to the XML schema for the bindings document. We need to specify it since the print/parse methods are not required to be on the classpath to infer the types from.

-Blaise

10 Handy Editor Keyboard Shortcuts in NetBeans IDE 6.0

Feb 01, 2012 · Mr B Loid

Hi Robert,

Are there any fully flexible JSON binding frameworks out there that can map multiple bindings into the same set of classes?

Check out the JSON-binding that we are adding to MOXy in EclipseLink 2.4.0:

  • JSON Binding with EclipseLink MOXy - Twitter Example
  • Binding to JSON & XML - Geocode Example

The same external mapping document is used as for the XML binding which allows you to apply multiple mappings:

  • Mapping Objects to Multiple XML Schemas - Weather Example

-Blaise

How Does JAXB Compare to XMLBeans?

Feb 01, 2012 · James Sugrue

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

How Does JAXB Compare to XMLBeans?

Feb 01, 2012 · James Sugrue

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

How Does JAXB Compare to XMLBeans?

Feb 01, 2012 · James Sugrue

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

Mono and FastCGI. An awkward relationship.

Feb 01, 2012 · Mr B Loid

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

Mono and FastCGI. An awkward relationship.

Feb 01, 2012 · Mr B Loid

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

Mono and FastCGI. An awkward relationship.

Feb 01, 2012 · Mr B Loid

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

Mono and FastCGI. An awkward relationship.

Feb 01, 2012 · Mr B Loid

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

How Does JAXB Compare to XMLBeans?

Feb 01, 2012 · James Sugrue

Hi Edward,

Thank you for your comment, below are my answers to your questions:

Are there advantages of XMLBeans over JAXB?

XMLBeans is built around the concept of infoset preservation. This includes things like comments, processing instructions, and whitespace that just doesn't map to your doman model. Using JAXB's Marshaller/Unmarshaller this info set isn't preserved. However if you use the JAXB's Binder it can be:

  • http://blog.bdoughan.com/2010/09/jaxb-xml-infoset-preservation.html
It seems that validation of an individual XmlObject is an advantage of using XMLBeans.


Validation of an individual XmlObject is a useful aspect of using XMLBeans. JAXB implementations are able to leverage the javax.xml.validation APIs to achieve some of this behaviour:

  • http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html

If you are not worried about validation then why not use JSON?

JSON is a very useful format, that does overlap with XML. However it is not able to represent everything that XML can so it is not always a direct replacement. This is a topic worthy of its own post.

Why isn't having re-generation (set up in the pom, let's say) better then modifying your POJOs by hand after changing the schema?

Regeneration is a valid option that is available to users of both XMLBeans and JAXB. JAXB also gives you the option of editing the domain objects by hand.

-Blaise

Joni merged to JRuby trunk

Jan 01, 2012 · Mr B Loid

Additionally,

  1. JAXB 2 models can be used with any JAXB runtime (Metro, MOXy, JaxMe), while JAXB 1 models must be used with the implementation that generated them.
  2. JAXB 2 is the standard binding layer for JAX-WS and JAX-RS.
  3. A JAXB 2 implementation is included in Java SE 6.
  4. JAXB 2 supports marshalling/unmarshalling StAX.
  5. JAXB 2 supports javax.xml.validation APIs for schema validation. The JAXB Validator class is now deprecated.
What are the differences between JAXB 1.0 and JAXB 2.0

Jan 01, 2012 · James Sugrue

Additionally,

  1. JAXB 2 models can be used with any JAXB runtime (Metro, MOXy, JaxMe), while JAXB 1 models must be used with the implementation that generated them.
  2. JAXB 2 is the standard binding layer for JAX-WS and JAX-RS.
  3. A JAXB 2 implementation is included in Java SE 6.
  4. JAXB 2 supports marshalling/unmarshalling StAX.
  5. JAXB 2 supports javax.xml.validation APIs for schema validation. The JAXB Validator class is now deprecated.
Coming soon: Really Simple History 0.6 beta

Oct 25, 2011 · Mr B Loid

Hi Ali,

The XML schema may be provided by a third party and you won't have control over how the imports are specified. This is the type of scenario where XML catalogs are useful.

-Blaise
Coming soon: Really Simple History 0.6 beta

Oct 25, 2011 · Mr B Loid

Hi Ali,

The XML schema may be provided by a third party and you won't have control over how the imports are specified. This is the type of scenario where XML catalogs are useful.

-Blaise
JAXB (XJC) Imported Schemas and XML Catalogs

Oct 25, 2011 · James Sugrue

Hi Ali,

The XML schema may be provided by a third party and you won't have control over how the imports are specified. This is the type of scenario where XML catalogs are useful.

-Blaise
JAXB (XJC) Imported Schemas and XML Catalogs

Oct 25, 2011 · James Sugrue

Hi Ali,

The XML schema may be provided by a third party and you won't have control over how the imports are specified. This is the type of scenario where XML catalogs are useful.

-Blaise
10 Handy Editor Keyboard Shortcuts in NetBeans IDE 6.0

Oct 21, 2011 · Mr B Loid

Thanks Ed.
10 Handy Editor Keyboard Shortcuts in NetBeans IDE 6.0

Oct 21, 2011 · Mr B Loid

Thanks Ed.
10 Handy Editor Keyboard Shortcuts in NetBeans IDE 6.0

Oct 21, 2011 · Mr B Loid

Thanks Ed.
Headius: Are Authors Technological Poseurs?

Jun 27, 2011 · Gerd Storm

EclipseLink MOXy (http://www.eclipse.org/eclipselink/moxy.php) is a JAXB 2.1/2.2 (JSR-222) implementation, that is currently missing from your list. MOXy offers extensions for:

XPath Based Mapping

  • http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
  • http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html

External Mapping File

  • http://bdoughan.blogspot.com/2010/12/extending-jaxb-representing-annotations.html

Mapping JPA Entities

  • http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA
Is your IT department scalable?

Mar 25, 2011 · Stacy Doss

Once again a nightmare to parse and it's not exactly human readable. XML in this structure will also result in an ambiguous schema, which in turn plays havoc with auto-code generators (e.g. JAXB).

JAXB implementations (Metro, MOXy, JaxMe, etc) do not require a grouping element. In fact the default behavior is not to have them:

@XmlElement(name="member")
private List<String> members;

Although a grouping element may be added:

@XmlElementWrapper(name="members")
@XmlElement(name="member")
private List<String> members;

-Blaise

JAXB - XML binding in Java

Dec 14, 2010 · Pavel Sumarokov

WRT XStream, JAXB is quite easy to use. Check out: http://bdoughan.blogspot.com/2010/10/how-does-jaxb-compare-to-xstream.html
How to Copy Bean Properties With a Single Line of Code

Sep 01, 2010 · James Sugrue

Copying properties from one bean is quite common especially if you are working with a lot of POJOs, for example working with JAXB objects.

WRT JAXB, coming up with a better copy process is solving the wrong problem. For years now we have been adding extensions to the EclipseLink JAXB implementation (MOXy) to make the copy step unneccessary. These extensions include:

  • XPath based mapping
  • JPA entity support (bi-directional relationships, composite keys, embedded key classes)
  • Externalized metadata
  • For more information see:

  • http://www.eclipse.org/eclipselink/moxy.php
  • Tell yourself 10 times that you don't own that anymore

    Sep 01, 2010 · Tony Thomas

    Copying properties from one bean is quite common especially if you are working with a lot of POJOs, for example working with JAXB objects.

    WRT JAXB, coming up with a better copy process is solving the wrong problem. For years now we have been adding extensions to the EclipseLink JAXB implementation (MOXy) to make the copy step unneccessary. These extensions include:

  • XPath based mapping
  • JPA entity support (bi-directional relationships, composite keys, embedded key classes)
  • Externalized metadata
  • For more information see:

  • http://www.eclipse.org/eclipselink/moxy.php
  • Squeak Relicensing Effort

    Apr 29, 2010 · Gerd Storm

    Seriously, people, where's this fascination in Java coming from? How many home-grown loggers, web frameworks, ORM solutions and XML parsers do we really need?

    I agree, and this is where standards/specifications can really help out. Gone are the days of XML parsers with proprietary APIs. If I'm doing StAX parsing, I can use the parser that comes with my JDK or with minimal config (without recompiling) I can swap in Woodstox StAX parser.

    The same thing is happening with ORM. In the past TopLink, Hibernate, and others had proprietary APIs. But now we have the JPA spec (which is implemented by TopLink, EclipseLink, Hibernate, and others), and their are standard APIs for doing the most common things. Implementations compete on their extensions points, and the best extensions are brought back into the specification.

    JAXB is to OXM what JPA is to ORM. The JAXB (JSR 222) APIs were created by a committee in which members of Metro, TopLink (EclipseLink), XMLBeans, EMF, and others participated. Many think of Metro as JAXB, but there are other implementations such as EclipseLink MOXy. Switching between JAXB implementations also requires minimal config (no recompiling).

    In general the specs represent the commoditized behaviour (do we really need another way to report a characters event, query by primary key, or map a property to an XML attribute?). Innovation is in the area beyond the specifications. Luckily today the majority of parser, JPA, and JAXB implementations are open source and available to be contributed to.

    Squeak Relicensing Effort

    Apr 29, 2010 · Gerd Storm

    Seriously, people, where's this fascination in Java coming from? How many home-grown loggers, web frameworks, ORM solutions and XML parsers do we really need?

    I agree, and this is where standards/specifications can really help out. Gone are the days of XML parsers with proprietary APIs. If I'm doing StAX parsing, I can use the parser that comes with my JDK or with minimal config (without recompiling) I can swap in Woodstox StAX parser.

    The same thing is happening with ORM. In the past TopLink, Hibernate, and others had proprietary APIs. But now we have the JPA spec (which is implemented by TopLink, EclipseLink, Hibernate, and others), and their are standard APIs for doing the most common things. Implementations compete on their extensions points, and the best extensions are brought back into the specification.

    JAXB is to OXM what JPA is to ORM. The JAXB (JSR 222) APIs were created by a committee in which members of Metro, TopLink (EclipseLink), XMLBeans, EMF, and others participated. Many think of Metro as JAXB, but there are other implementations such as EclipseLink MOXy. Switching between JAXB implementations also requires minimal config (no recompiling).

    In general the specs represent the commoditized behaviour (do we really need another way to report a characters event, query by primary key, or map a property to an XML attribute?). Innovation is in the area beyond the specifications. Luckily today the majority of parser, JPA, and JAXB implementations are open source and available to be contributed to.

    Squeak Relicensing Effort

    Apr 29, 2010 · Gerd Storm

    Seriously, people, where's this fascination in Java coming from? How many home-grown loggers, web frameworks, ORM solutions and XML parsers do we really need?

    I agree, and this is where standards/specifications can really help out. Gone are the days of XML parsers with proprietary APIs. If I'm doing StAX parsing, I can use the parser that comes with my JDK or with minimal config (without recompiling) I can swap in Woodstox StAX parser.

    The same thing is happening with ORM. In the past TopLink, Hibernate, and others had proprietary APIs. But now we have the JPA spec (which is implemented by TopLink, EclipseLink, Hibernate, and others), and their are standard APIs for doing the most common things. Implementations compete on their extensions points, and the best extensions are brought back into the specification.

    JAXB is to OXM what JPA is to ORM. The JAXB (JSR 222) APIs were created by a committee in which members of Metro, TopLink (EclipseLink), XMLBeans, EMF, and others participated. Many think of Metro as JAXB, but there are other implementations such as EclipseLink MOXy. Switching between JAXB implementations also requires minimal config (no recompiling).

    In general the specs represent the commoditized behaviour (do we really need another way to report a characters event, query by primary key, or map a property to an XML attribute?). Innovation is in the area beyond the specifications. Luckily today the majority of parser, JPA, and JAXB implementations are open source and available to be contributed to.

    Squeak Relicensing Effort

    Apr 29, 2010 · Gerd Storm

    Your db model classes tend to be different than your jaxb classes. So you end up with a lot of stupid conversion: request xml -> jaxb dtos ->db model->sql -> result set -> db model -> jaxb dtos -> response xml. I have a lot of code and tests that are about babysitting data through this chain instead of actual business logic.

    EclipseLink JAXB (aka MOXy) was designed to solve just that problem. Its XPath based mappings allows you to map your own domain model to any XML schema (or multiple XML schemas).

    It is also the only binding solution I'm aware of with specific support for mapping JPA entities. This includes bi-directional relationships, compound keys, and embedded key classes.

    Plus, if you are already using EclipseLink/TopLink for your JPA layer, you will already be familiar with some of the extension points.

    User has been successfully modified

    Failed to modify user

    ABOUT US

    • About DZone
    • Support and feedback
    • Community research
    • Sitemap

    ADVERTISE

    • Advertise with DZone

    CONTRIBUTE ON DZONE

    • Article Submission Guidelines
    • Become a Contributor
    • Core Program
    • Visit the Writers' Zone

    LEGAL

    • Terms of Service
    • Privacy Policy

    CONTACT US

    • 3343 Perimeter Hill Drive
    • Suite 100
    • Nashville, TN 37211
    • support@dzone.com

    Let's be friends: