Suppose i have a BOOK.java file with the fields(id, name, author) and now while marshalling it to XML file, I want only id to be written in XML file but that has to be decided by some condition. So I was thinking to inject #XmlTransient annotations to other two fields on that condition at runtime. Is it possible to inject an JAXB annotations at runtime? Can i do that and if i can, how can i do so?
Is there any way other then using javassist to do so ?
It sounds like you just want something that's not JAXB. JAXB is great when it fits, but it's pretty restrictive in what it allows you to do. Something like XStream would probably fit your needs better. You can write a custom Converter that will handle all the logic of whether to write a particular field or not.
Related
I am working on a project that has a fair amount of data objects that use a "fluent interface" or "method chaining" on their setters so all of the setters in each data object return this. I have looked around and found this question, but it is unclear to me whether this can be used with Yaml as the annotations specifically mention JSON, and also this seems to enable mapping to objects using an actual builder pattern, which is a little different. The project is currently using SnakeYaml, but that can be tossed away if some other lib like Jackson can do this.
It turns out that this is in fact possible. Jackson supports yaml and will work with builder style setters by default without any extra configuration.
I am writing the service to implement the audit in our application wherein users can view the status of a particular entity before and after any modification and should also be able to roll it back. We have decided to store the XML Serialized object in the databse in XML_TYPE column.
I am new to serialization, I don't know how to achieve the same, any changes needs to be done to the object to be serialized or do we need to have any mapping XML. Can someone please suggest some good libraries, I understand there are lot of those available in the market like JAXB, JIBX, JABX, XStream and etc. Which one would be good and how to use it.
Any help is highly appreciated.
Regards,
Ravi.
Of course, the best for entities is having POJO's (Plain Old Java Objects). No strange properties, references or methods. It simplifies serializing and keeps your model objects neutral from frameworks and strange layers like persistence, UI, remote-access and so on.
XStream: simplicity
I'd suggest using XStream library for serializing. It tries to be the simplest way to serialize and deserialize objects to XML.
You should think searialization this way:
indicate what class is the object
try to serialize each property
So, these are the two problems to resolve in serializing. XStream lets you create a serializer (XStream class), (OPTIONALLY) indicate what tag name use for each class and (OPTIONALLY) indicate the aliases for properties.
So if you have something like:
package pack;
Person
+ mom: Person
+ dad: Person
it will write with no configuration:
<pack.Person>
<mom>
<pack.Person>
...
</pack.Person>
</mom>
<dad>
<pack.Person>
...
</pack.Person>
</dad>
</pack.Person>
But if you tell it to map package.Person to it will use that tag. You can tell it to write property "mom" as "mother" and things like that.
XStream xs = new XStream();
xs.alias("person", Person.class);
xs.aliasAttribute(Person.class, "mom", "mother");
References
XStream also lets you indicate what kind of references you want:
no references: serialize an object
each time it founds it in the object
tree
absolute references: the second time
an object is found it saves a
reference using the absolute path of
the first instance
(/people/person[4]/teacher)
relative references: the same, but
using a relative reference from this
point (../../person[4]/teacher)
JAXB is the standard. In the simplest (and most common case) you just annotate your entities with JAXB annotations, and use a Marshaller to marshal the object to XML.
You can use either Sun's reference implementation, or Apache JaxMe.
XStream is a good alternative as far as I know, although I haven't used it.
I'm trying to figure out the simplest way to map an xml file to to a plain old java object.
Note: That in my example the xml doesn't quite match up with my intended POJO.
///////// THE XML
<?xml version="1.0" encoding="UTF-8"?>
<Animal>
<standardName>
<Name>Cat</Name>
</standardName>
<standardVersion>
<VersionIdentifier>V02.00</VersionIdentifier>
</standardVersion>
</Animal>
////// THE INTENDED POJO
class Animal
{
private String name;
private String versionIdentifier;
}
Regular JAXB (with annotations) won't work as the JAXM Element name annotations don't allow me to specifiy nested elements. (i.e. standardName/Name).
I've looked at Jibx but it seems overly complicated, and no full examples are provided for what I want to do.
Castro seems like it would be able to do what I want (using mapping files), but I wonder if there are any other possible solutions. (Possibly that would allow me to skip mapping files, and just allow me to specify everything in annotations).
Thanks
EclipseLink JAXB (MOXy) allows you to do the path based mapping that you are looking for:
#XmlRootElement
class Animal
{
#XmlPath("standardName/Name/text()")
private String name;
#XmlPath("standardVersion/VersionIdentifier/text()");
private String versionIdentifier;
}
For more information see:
http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions
EclipseLink also allows the metadata to be specified using an external configuration file:
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/ExternalizedMetadata
This article may help you... it only requires you to know xpath
http://onjava.com/onjava/2007/09/07/schema-less-java-xml-data-binding-with-vtd-xml.html
Jakarta Commons Digester should do what you want.
Alternatively, I would recommend writing a transformation class that uses XPath to retrieve elements from the XML.
I consider JiBX the best of the bunch (JAXB, Castor, XMLBeans, etc.), particularly because I favor mapping files over annotations. Admittedly it has a decent learning curve, but the website has a lot of good examples. You must have missed the tutorial.
If you are only going one way (XML --> POJO) you could use Digester.
Side comment: I prefer mapping files over annotations because annotations:
clutter the code (especially when using annotations from several products)
mix concerns (XML, database, etc. in domain layer)
can only bind to a single XML (or database, or web service, etc.) representation
JAXB works well until I need to do something like serialize beans for which I cannot modify the source. If the bean doesn't have a default constructor or if it refers to objects I want to mark transient then I'm stuck writing a separate bean which I can annotate and then manually copy the information over from the other bean.
For instance, I wanted to serialize exception objects, but found that the only way to do that was use a hack that required using com.sun.* classes.
So, what alternatives are there? What's the next most popular xml serializing api? It would be nice to be able to do things like:
Choose at serialization time whether to include certain fields in the result. (marking things transient when running the serializer).
Handle loops in the object graph by using references or something other than just dying.
Perhaps annotate an object so that in version 1 it serializes things in one way and in version 2 it serializes them in another. Then when serializing I just choose which version of the object ot serialize.
Have a way to generate XSDs from annotations on an object.
Basically I just want more flexibility than I currently have with JAXB.
Well the standard answer for wanting a uber configurable serialisation framework is xstream.
JAXB is a spec, so you can pick from different implementations. EclipseLink JAXB (MOXy) has extensions for what you are asking:
Externalized Metadata
Useful when dealing with classes for which you cannot annotate the source or to apply multiple mappings to an object model.
http://bdoughan.blogspot.com/2010/12/extending-jaxb-representing-annotations.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/EclipseLink-OXM.XML
XPath Based Mapping
For true meet-in-the-middle OXM mapping:
http://bdoughan.blogspot.com/2010/09/xpath-based-mapping-geocode-example.html
http://bdoughan.blogspot.com/2011/03/map-to-element-based-on-attribute-value.html
http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/GettingStarted/MOXyExtensions
JPA Compatibility
Including support for bi-directional relationships.
http://bdoughan.blogspot.com/2010/07/jpa-entities-to-xml-bidirectional.html
http://wiki.eclipse.org/EclipseLink/Examples/MOXy/JPA
Also look at JIBX. It's a good xml<->object mapper. My experience is though that if your objects have a somewhat funky relationships it's often easier to create a wrapper object that hides that complexity and then map that object with JIBX.
XStream is a popular XML serialisation library that claims to be able to serialize just about anyting, regardless of constructors or other problems (even deserialize final fields). Give it a try.
Requires no modifications to objects. Serializes internal fields, including private and final. Supports non-public and inner classes. Classes are not required to have default constructor.
If you have a Java object and an XML schema (XSD), what is the best way to take that object and convert it into an xml file in line with the schema. The object and the schema do not know about each other (in that the java classes weren't created from the schema).
For example, in the class, there may be an integer field 'totalCountValue' which would correspond to an element called 'countTotal' in the xsd file. Is there a way of creating a mapping that will say "if the object contains an int totalCountValue, create an element called 'countTotal' and put it into the XML".
Similarly, there may be a field in the object that should be ignored, or a list in the object that should correspond to multiple XML elements.
I looked at XStream, but didn't see any (obvious) way of doing it. Are there other XML libraries that can simplify this task?
I believe this can be achieved via JAXB using it's annotations. I've usually found it much easier to generate Objects from JAXB ( as defined in your schema) using XJC than to map an existing Java object to match my schema. YMMV.
I'm doing Object do XML serialization with XStream. What don't you find "obvious" with this serializer? Once you get the hang of it its very simple.
In the example you provided you could have something like this:
...
XStream xstream = new XStream(new DomDriver());
xstream.alias("myclass", MyClass.class);
xstream.aliasField("countTotal", MyClass.class, "totalCountValue");
String xml = xstream.toXML(this);
...
for this sample class:
class MyClass {
private int totalCountValue;
public MyClass() {
}
}
If you find some serializer more simple or "cool" than this please share it with us. I'm also looking for a change...
Check the XStream mini tutorial here
I use a java library called JiBx to do this work. You need to write a mapping file (in XML) to describe how you want the XML Schema elements to map to the java objects. There are a couple of generator tools to help with automating the process. Plus it's really fast.
I tried out most of the libraries suggested in order to see which one is most suited to my needs. I also tried out a library that was not mentioned here, but suggested by a colleague, which was a StAX implementation called Woodstox.
Admittedly my testing was not complete for all of these libraries, but for the purpose mentioned in the question, I found Woodstox to be the best. It is fastest for marshalling (in my testing, beating XStream by around 30~40%). It is also fairly easy to use and control.
The drawback to this approach is that the XML created (since it is defined by me) needs to be run through a validator to ensure that it is correct with the schema.
You can use a library from Apache Commons called Betwixt. It can map a bean to XML and then back again if you need to round trip.
Take a look at JDOM.
I would say JAXB or Castor. I have found Castor to be easier to use and more reliable, but JAXB is the standard