This question already has answers here:
What is the simplest and minimalistic java xml api?
(7 answers)
Closed 10 years ago.
I need to save user data between sessions. So I decided to using binary serialization and start saving data in xml. After some research I found several APIs, namely JAXB and xStream.
I looked through samples of xStream and I like it. It is very simple. In two words: you give an object and receive .xml representation of this object. Read an xml and receive object back.
Then I read about JAXB - it is very strong, functional. But all examples I found are about creating of xml schema, generating java classes basing on this schema and so on. At the moment it looks a little bit time consuming for me to describe my classes in .xsd. I hope it is one of many sides of JAXB usage. But what I saw, feared me a little.
Are there any other APIs that suit my task. Or what are pros and cons of JAXB and xStream then?
I would start with JAXB as it is built-in and easy to use. You do not need to start with an XSD. Just add some annotations to your classes.
#XmlRootElement(name="doc")
public class Document {
#XmlElement
protected Foo foo;
// ...
}
Serialization:
Document doc = new Document();
JAXBContext jc = JAXBContext.newInstance(Document.class);
Marshaller m = jc.createMarshaller();
m.marshal(doc, System.out);
Deserialization:
JAXBContext jc = JAXBContext.newInstance(Document.class);
Unmarshaller u = jc.createUnmarshaller();
Document doc = u.unmarshal(System.in);
Replace System.out and System.in by your actual streams and you are ready to go.
There is a short tutorial regarding JAXB Annotations in the JAXB tutorial:
http://jaxb.java.net/tutorial/section_6_2_1-A-Survey-Of-JAXB-Annotations.html
When JAXB is a bit too much of a powerhouse, and a simpler solution could be better, I generally try Castor.
The good part is, you can use the simple introspection mode, quick and easy, and if you ever feel like you need more control over your generated XML, add a descriptor or mapping, but both are optional.
Related
Has someone ever been able to remove unused namespaces during marshal of an object using JAXB? Here is a link of the requested feature: https://github.com/javaee/jaxb-v2/issues/103 (see description)
Is there a property for configuring JAXB for this?
Has this been fixed in MOXy?
I am currently traversing the object that needs to be marshalled and extract all classes that need to be bound into Class[] classesToBeBound.
Then I create a new JAXBContext.newInstance(classesToBeBound)
The unused namespaces now are not included in the XML.
I know that xml validation is valid even with the unused namespaces but to me this is something a framework should handle.
The following link https://blogs.oracle.com/enterprisetechtips/entry/customizing_jaxb mentions various fixed (see middle of the text somewhere) but when trying to find the solution in those links either the link is broken or no-one really solved it.
Any comments are welcome.
(EDIT)
Plain text:
GIVEN
a new instance of JAXBContext and add 2 classes with each a separate namespace.
WHEN
marshalling a class that has these 2 classes as a property but only 1 of them is not null
THEN
I expect only the namespace of the property that is not null to be visible in the XML.
BUT the ACTUAL is
that both namespaces are in the xml.
So my question was how can I remove or tell JAXB to NOT write the unused namespaces?
To put it in java-code:
GIVEN
public class Foo{
private Bar bar; //namespace something2
private User user; //namespace user
}
WHEN
JAXBContext c = JAXBContext.newInstance(Foo.class, Bar.class, User.class);
...
Foo foo = new Foo();
foo.setBar(null);
foo.setUser(new User("Bob"));
marshaller.umarshal(foo);
THEN I expect the xml to be
<foo xmlns="something1" xmlns:user="user">
<user:name>Bob</user:name>
</foo>
BUT the ACTUAL is (note the something2 namespace)
<foo xmlns="something1" xmlns:user="user" xmlns:bar="something2">
<user:name>Bob</user:name>
</foo>
Of course this is a simplified example and our specification of a type has around 30 different namespaces.
As far as I know, this is indeed not possible in JAXB - and is actually a well-known issue. As you have noticed it, the list of produced namespaces are the ones that have been registered in your JAXBContext, and not the ones that are effectively used when marshalling :-(
I the past, I used the same workaround as you (identify the various used classes and narrow the JAXBContext to this limited set of classes).
Another typical workaround is a 2-step processing: a first marshalling with JAXB, followed by a XSLT transformation to get rid of let's says "polluting" namespaces.
This may not be possible as while marshaling of this objects hierarchy happen, at the time of creating root tag, information about which objects are null v/s not null may not be available. Any attempt to get this information in advance may also have side-effects associated with it as respective accessor methods are invoked. Hence JAXB will statically use info from JAXBContext to have this information populated.
You can try using a different javax.xml.bind.Marshaller implementation.
For example org.eclipse.persistence.jaxb.JAXBMarshaller implementation deals well with this case and remove all unnecessary namespaces when marshall the object.
To do so you need to do the next steps:
Add eclipselink-2.6.5.jar to the classpath in order to use the org.eclipse.persistence.jaxb.JAXBMarshaller. If you're using gradle you can add compile 'org.eclipse.persistence:eclipselink:2.6.5' to your dependencies.
Create a jaxb.properties file in the same package where you've the objects to marshall (following the example in your question - JAXBContext c = JAXBContext.newInstance(Foo.class, Bar.class, User.class);, in the package of one of these classes Foo, Bar or User).
In the jaxb.properties file, add the follow property which specify the desired Context factory:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Doing this, the org.eclipse.persistence.jaxb.JAXBMarshaller will be used as a javax.xml.bind.Marshaller implementation on Runtime. And then no unnecessary namespaces will appear when you marshall the objects.
I tried the solution albciff suggested in this thread and it turns out that Eclipse Moxy handles this much better than the reference implementation (org.glassfish.jaxb).
Here's info on how to switch to the Moxy implemenation of JAXB:
https://wiki.eclipse.org/EclipseLink/Examples/MOXy/JAXB/SpecifyRuntime
The documentation doesn't specify it but you can also change the jaxb implemenation with just a single configuration file instead of a jaxb.properties in each package where your jaxb annotated classes exists. Just create a file META-INF/services/javax.xml.bind.JAXBContext (yep unconventional filename) with the contents:
org.eclipse.persistence.jaxb.JAXBContextFactory
This makes the jaxb ContextFinder use the Eclipse Moxy implementation for all jaxb marshalling in the jvm.
Another option is to use a system property -Djavax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Disclaimer though: The namespaces declaration aren't minimized/optimized for the current payload, but at least it doesn't include ALL namespaces that are part of the jaxb grammar. The integration I'm working on went from a staggering 700+ declared namespaces (about 60KB worth of useless overhead per sent message) to at best 3 declarations in a message. Though for messages which have a lot of different types in them, all of the namespaces which are valid in that particular message is declared. That means in some case I still get ~30 declared namespaces when only one would suffice for the current payload.
I guess that SOAP isn't the way to go if you need to optimize on bandwidth.
Yes, they could be omitted. I'm not sure I understood the problem you face correctly. But there is no problem to marshal an object without namespaces.
Try something like this marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, "class for which namepsace not needed"); in your case it should be
marshaller.setProperty(Marshaller.JAXB_NO_NAMESPACE_SCHEMA_LOCATION, bar.class);
I have a couple of questions about JAXB:
What options are there for parsing? Can I implement / plugin my own parser easily?
What about validity? Suppose I have a relaxed parser that is somewhat relaxed regarding the schema. Can I still create an (invalid) object-structure?
Does JAXB provide special means to do e.g. validation on the objects? I'd like to parse to an "invalid" object structure, have some algorithm repair it, then validate (in Java).
Does JAXB provide other means to do fancy things on the objects (e.g. visitor pattern).
What about the memory footprint? Is the object representation (disregarding the parsing) feasible for XML files of 10-100MB?
Good tutorials covering this kind of questions are appreciated, Google revealed only coarse overviews.
Below are my answers to your questions:
What options are there for parsing? Can I implement / plugin my own
parser easily?
JAXB (JSR-222) implementations can unmarshal from many different input types: InputStream, InputSource',Node,XMLStreamReader,XMLEventReader,File,Source`. If your XML representation matches any of these then you're all set.
What about validity? Suppose I have a relaxed parser that is somewhat
relaxed regarding the schema. Can I still create an (invalid)
object-structure?
JAXB implementations requires that the XML be well formed, but does not require it be valid against an XML schema. It is designed to handle a wide range of documents. If you want to ensure "validity" then you can set an XML schema (see JAXB and Marshal/Unmarshal Schema Validation).
Does JAXB provide special means to do e.g. validation on the objects?
I'd like to parse to an "invalid" object structure, have some
algorithm repair it, then validate (in Java).
You can use the javax.xml.validation APIs to do validation on an object model. For a full example see:
http://blog.bdoughan.com/2010/11/validate-jaxb-object-model-with-xml.html
Does JAXB provide other means to do fancy things on the objects (e.g.
visitor pattern).
JAXB models are POJOs so you can design them as you wish. You may be interested in the following classes:
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Marshaller.Listener.html
http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/Unmarshaller.Listener.html
What about the memory footprint? Is the object representation
(disregarding the parsing) feasible for XML files of 10-100MB?
Yes JAXB can be used to process documents of that size. If you are concerned about size, you can use an XMLStreamReader to parse the XML file and then unmarshal objects from the XMLStreamReader in chunks.
Ideally writing should simply a matter of switching writers. One write would write json and another xml. The same would be true of the reverse, one factory takes an InputStream of json and another an InputStream of xml. In both cases the binding stuff would return an object stream given an InputStream.
XStream does this pretty darn well.
Normal instantiation (for XML):
new XStream();
Alternative instantiation (for JSON):
new XStream(new JettisonMappedXmlDriver());
/**************** or ****************/
new XStream(new JsonHierarchicalStreamDriver());
Also, while not a simple lib, JAX-RS implementations (like Jersey, RESTeasy) offer simple way to produce and consume both JSON and xml. They handle choice of backend library transparently based on media type being requested.
Build a facade is rather simple too; I would start by using JAXB for xml and Jackson for JSON; both can take InputStream or Reader, and output using OutputStream or Writer. And both do reasonably good job with data binding.
If you are looking to code this yourself - it sounds like a good case for a Strategy pattern and a Factory Method pattern
Is there is Simple way to read and write Xml in Java?
I've used a SAX parser before but I remember it being unintuitive, I've looked at a couple of tutorials for JAXB and it just looks complicated.
I don't know if I've been spoilt by C#'s XmlDocument class, but All I want to do is create an Xml Document that represents a a set of classes and their members (some are attributes some are elements).
I would look into serialization but the XML has to have the same format as the output of a c# app which I am reverse engineering into Java.
I recommend XOM. Its API is clear and intuitive.
You should check out Xstream. There is a 2 minute tutorial that is really simple. To get the same format, you would model the classes the same.
If you are using jdk 1.4 or newer take a look at XMLEncoder class.
Some of the more popular approaches to consider:
Java Archictecture for XML Binding
JAXB is a specification for a standard XML binding. If you already have an XSD, it can generate your Java classes for you, and then all that's left is to use a standard API for marshalling/unmarshalling.
Reference implementation from Glassfish
Apache's implementation JaxMe
Other binding approaches
As with JAXB, these approaches use XML-based binding configurations. They may provide more fine grained control of the unmarshalling process.
Castor
JIBX
Roll your own
Using StAX
Using XOM
Using plain XPath
Dom4j is a simple api for creating xml documents in java.
Document document = DocumentHelper.createDocument();
Element root = document.addElement( "root" );
Element author2 = root.addElement( "author" )
.addAttribute( "name", "Toby" )
.addAttribute( "location", "Germany" )
.addText( "Tobias Rademacher" );
The most simple way so far is the MarkupBuilder in Groovy. Think of Groovy as a new syntax for Java. The XmlSlurper can be used to read XML.
I think that Apache XMLBeans provides the functionality you are after.
The Wikipedia page gives a good overview and example usage.
There is a wide choice of XML processing options for Java, though judging from the .NET documentation for XmlDocument, the Java DOM implementation is the closest out-of-the-box equivalent.
.NET XmlDocument:
This class implements the W3C Document
Object Model (DOM) Level 1 Core and
the Core DOM Level 2.
Java Document:
See also the Document Object Model (DOM) Level 3 Core Specification.
Sample code:
public static void main(String[] args) throws Exception {
File xmlFile = new File(".classpath");
// read it
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(xmlFile);
// walk it
System.out.println("Node count=" + countNodes(document));
// write it
Source source = new DOMSource(document);
Result result = new StreamResult(System.out);
TransformerFactory transformerFactory = TransformerFactory
.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.transform(source, result);
}
/** Doesn't count attributes, etc */
private static int countNodes(Node node) {
int count = 0;
NodeList kids = node.getChildNodes();
count += kids.getLength();
for (int i = 0; i < kids.getLength(); i++) {
count += countNodes(kids.item(i));
}
return count;
}
I think JAXB is only complicated if you look at wrong examples. Specifically, yes, schema-based way can get messy. But code-first, annotation-based is trivially easy.
Another easy alternative is XStream. And for non-binding case, StaxMate, which is an add-on for streaming Stax parsers.
If SAX parsing is mandatory, JAXP is a good choice. I prefer DOM parsing and use jdom which seems a lot easier to me.
I would certainly use XOM if you want a DOM-like approach and SAX (www.sax.org) if you want a SAX-like approach. I was involved in the early development of XML and SAX was developed as an event-driven approach, which is useful for some applications. DOM/XOM and SAX are complementary - sometimes you need one, sometimes the other. If you wish to build objects as you go rather than read everything into memory, use SAX. If you are happy to read everything in and then process it, use XOM.
I spent far too much time trying to get the W3C DOM to work - IMO it is poorly defined with too many ways of doing some things and not enough for others. When XOM came it revolutionised my productivity.
The XOM community is very knowledgeable and focused and helpful.
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