Note: Editing this to rephrase it around JAXB in hopes of getting new answers. I'm using CXF, but it's using JAXB for the mappings.
I've got a POJO model. Right now I have it mapped via annotations and using JAXB to spew/read XML. However that's only one XML format and I need to map that POJO model to one of various XML formats depending on the 3rd party system I'm integrating with (e.g. various 3rd parties all have the concept of a "person", but map it differently). I've read through the entire JAXB tutorial, but everything is centered around annotations. Is there some external way to map the classes so I can read/write multiple mappings where I pick the mapping to use at any given point (i.e. I know I'm spewing a "person" to Foo Inc., so use the foo mapping)?
Edit: I just found something called JAXBIntroductions that might do the job.
http://community.jboss.org/wiki/JAXBIntroductions
If you are using EclipseLink JAXB (MOXy) you can take advantage of the externalized mapping feature to apply many XML representations to your POJOs.
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/EclipseLink-OXM.XML
Also, since MOXy's mappings are XPath based you can actually map your POJOs to a wide variety of XML schemas.
you can use XStream for this. you can work without annotations like this:
XStream xstream = new XStream();
XStream xstream = new XStream(new DomDriver());
xstream.alias("person", Person.class);
xstream.alias("phonenumber", PhoneNumber.class);
hope that helps
EDIT: create another XStream instance for a different output
Person demo = new Person("Chris");
XStream xStream = new XStream();
xStream.alias("person", Person.class);
System.out.println(xStream.toXML(demo));
XStream xStream2 = new XStream();
xStream2.alias("dev", Person.class);
System.out.println(xStream2.toXML(demo));
output:
<person>
<name>Chris</name>
</person>
<dev>
<name>Chris</name>
</dev>
you can try http://code.google.com/p/jlibs/wiki/SAX2JavaBinding
This is also based on annotations. but annotations are not on your POJO.
Related
I have the next task: read XML file from some directory and convert it to JSON string.
The problem: initial XML and JSON have different names for corresponding properties, e.g. x_date in XML and j_date in JSON.
I have created the class with required field for JSON with such annotations:
public class Card {
#JacksonXmlProperty(localName = "x_date")
#JsonProperty("j_date")
private String date;
// other fields
I have tried to serialize/deserialize test XML file, and it's seems work correctly.
But I'm not sure that is ok to annotate fields with #JacksonXmlProperty and #JsonProperty annotations at the same time. Maybe it's better to create one class per XML part and one for the JSON and transfer the data between them some mapper (e.g. Orika)?
Any suggestions?
Finally solved this by splitting logic in two separate classes: Card.class for XML data with help of #JacksonXmlProperty annotation and CardDto.class which uses #JsonProperty. Mapping between these classes is handled by Orika mapper.
This split will ease further customization of both classes and will allow add new functionality (e.g. persist data to the database using new entity class).
I have a java object (let's name it JsonValidator) that can be configured in YAML file.
I would like to describe a schema of JSON objects in YAML notation something like this
And then I need to validate JSON objects according to the schema. Does anybody know any Java libs I can use or any examples?
Thanks
The schema of a json document can be defined using json schema (actually, OpenAPI uses a custom flavor of json schema). It is essentially a json document defining the structure of an other json document. There are a few java implementations out there. If you want to stick to YAML for defining the schema, then will first need to convert YAML to JSON and then use the json schema validator, see this SO question for doing that.
You can find some Java validators for JSON Schema here.
Jersey is not showing a list in the JSON output when I retrieve the object using Hibernate. The list within the object is defined like this:
#OneToMany(cascade=CascadeType.ALL)
#OrderColumn
private List<Project> projects = new ArrayList<Project>();
When I retrieve the object (which also contains the projects list), I get the normal fields (ints and Strings and such), but not this list. When I use the debugger, I can see that the list is indeed there, but Jersey doesn't output it in JSON.
It looks like you need to configure a JSON Serializer such as Jackson. The answers to this question have some guidance on how to do that.
Once you have Jackson with JAXB support configured, you will need to add appropriate JAXB annotations to the Project class (either XML based one or JSON based ones, the serializer can be configured to support either or both). So, for example adding this to Project
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "")
#XmlRootElement(name = "project"))
public class Project {
Should be enough to serialize Project and it's fields to JSON.
I'm looking for best tool/way to create and load JAVA objects from XML definitions.
I had checked out JAXB, seems pretty nice, but didn't find is there a way to work with Entities which properties are dynamic, or changed from time to time, so want to have something like automatic way of working with entities, without converting Object into predefine Entity object. Does something like that exists?
Workflow would be like this read from XML create class for each Entity with dynamic set of attributes and/or create ORM mapping part for those entities and then all manipulation retrieve/store into db or probably will going to use some NoSQL solution like MongoDB.
Note: I'm the EclipseLink JAXB (MOXy) lead, and a member of the JAXB 2 (JSR-222) expert group.
Check out the following EclipseLink example. It demonstrates how to use dynamic properties with both the JPA and JAXB implementations:
http://wiki.eclipse.org/EclipseLink/Examples/MySports
Option #1 - Static Objects with Dynamic Properties
MOXy has an #XmlVirtualAccessMethods extension which allows you to map entries in a map to XML. This allows you to add properties to a static class. In the example below the Customer class has a "real" name property and may have many "virtual" properties.
package blog.metadatasource.refresh;
import java.util.*;
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.XmlVirtualAccessMethods;
#XmlRootElement
#XmlType(propOrder={"firstName", "lastName", "address"})
#XmlVirtualAccessMethods
public class Customer {
private String name;
private Map<String, Object> extensions = new HashMap<String, Object>();
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Object get(String key) {
return extensions.get(key);
}
public void set(String key, Object value) {
extensions.put(key, value);
}
}
The virtual properties are defined via MOXy's XML metadata. In the example below we will add two properties: middleName and shippingAddress.
<?xml version="1.0"?>
<xml-bindings
xmlns="http://www.eclipse.org/eclipselink/xsds/persistence/oxm"
package-name="blog.metadatasource.refresh">
<java-types>
<java-type name="Customer">
<java-attributes>
<xml-element
java-attribute="middleName"
name="middle-name"
type="java.lang.String"/>
<xml-element
java-attribute="shippingAddress"
name="shipping-address"
type="blog.metadatasource.multiple.Address"/>
</java-attributes>
</java-type>
</java-types>
</xml-bindings>
For More Information
http://blog.bdoughan.com/2011/06/extensible-models-with-eclipselink-jaxb.html
http://blog.bdoughan.com/2011/06/moxy-extensible-models-multi-tenant.html
http://blog.bdoughan.com/2011/06/moxy-extensible-models-multiple.html
http://blog.bdoughan.com/2011/06/moxy-extensible-models-refresh-example.html
Option #2 - Dynamic Objects
MOXy also offers full dynamic object models:
DynamicJAXBContext jaxbContext = DynamicJAXBContextFactory.createContextFromXSD(xsdInputStream, null, null, null);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
DynamicEntity customer = (DynamicEntity) unmarshaller.unmarshal(inputStream);
DynamicEntity address = jaxbContext.newDynamicEntity("org.example.Address");
address.set(street, "123 A Street");
address.set(city, "Any Town");
customer.set("address", address);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(customer, System.out);
For More Information
http://wiki.eclipse.org/EclipseLink/UserGuide/MOXy
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/Dynamic
So, you're basically trying to make POJO's (plain old Java objects) using XML files? They are just like data classes, right?
I'm a big fan of XStream, which is really easy to use and works great if you don't need validation. I've used Castor when validation against a schema was required. I just used XStream to save an object to an xml file and then I can read it back in from anywhere, even if I change the data values associated with the object (which I think is what you mean by "dynamic set of attributes", right?).
I'm using Xstream to serialize a EJB entity class to be transferred by a web service, but it also writes the database specific information in this case the following code. Is it possible to omit this information?
<oracle.toplink.essentials.internal.helper.DatabaseField>
<scale>0</scale>
<length>255</length>
<precision>0</precision>
<isUnique>false</isUnique>
<isNullable>true</isNullable>
<isUpdatable>true</isUpdatable>
<isInsertable>true</isInsertable>
<columnDefinition></columnDefinition>
<name>ZIPCODEID</name>
<table>
<name>ZIPCODE</name>
<tableQualifier></tableQualifier>
<qualifiedName>ZIPCODE</qualifiedName>
<uniqueConstraints/>
</table>
<sqlType>4</sqlType>
<index>0</index>
</oracle.toplink.essentials.internal.helper.DatabaseField>
From FAQ:
How do I specify that a field should not be serialized?
Make it transient, specify it with XStream.omitField() or annotate it with #XStreamOmitField
EclipseLink (open sourced from TopLink) JAXB has extensions specifically for mapping JPA entities to XML:
For more information see:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA
If you use openJPA you can detach the object to get the naked entity.
Check ->
http://openjpa.apache.org/builds/1.0.0/apache-openjpa-1.0.0/docs/manual/ref_guide_remote.html
Hope it helps...