I have a very basic application that uses JAXB marshaller to validate input information against an xsd schema. I register a validation event handler to obtain information about the exceptions. What I would like to achieve is the ability to include this information into xml output structure I receive as a result of marshaling. I’ve included exception collection section into my xsd and now I can instantiate the corresponding exception object once an exception is encountered. The question is how do I attach this object to the rest of my JAXB generated Java objects structure considering the fact that marshaling process had already started? Is it even possible? Or should I try and modify the xml result after the marshaling is done? Any advice would be highly appreciated.
Thanks!
There a couple of ways to do this:
Option #1 - Add an "exceptions" Property to You Root Object
Ensure that the exceptions property is marshalled last, this can be configured using propOrder on the #XmlType annotation.
Create a validation handler that holds onto the root object.
When the validation handler encounters an exception, add that exception to the exceptions property on the root object.
Option #2 - Use an XMLStreamWriter
Create an XMLStreamWriter
Write out a root element
Set the validation handler on the marshaller, ensure that it will store the exceptions encountered.
Marshal the root object to the XMLStreamWriter.
Marshal the individual exceptions encountered to the XMLStreamWriter.
Write out the close for the root element.
Short answer: no. JAXB is intended to take an object graph and produce XML. it's not intended to do this.
Longer answer: You could inject the exception representation into the graph after JAXB is done the first time.
Even longer answer: There are a number of plugin and customization technologies for JAX-B, and it's possible that you could use one of them. However, it's very hard to conceptualize this at the abstract level of your question.
Related
Based on this example Keep child-parent relationship after unmarshalling I'd like to know if it's possible to unmarshall xml file into an existing model (not having the JAXB annotations). My idea is to directly unmarshall into Primefaces Menu Model (https://www.primefaces.org/docs/api/6.0/org/primefaces/model/menu/package-summary.html). Is it possible?
JAXB is configuration by exception, so if your model matches the xml, annotations are not necessary.
Here a blog post and a stackoverflow answer by Blaise Doughan on the topic.
It is possible (if your model is straightforward enough to be JAXB-compatible or with MOXy external mappings), but I would really not recommend it.
If you map to existing model, your XML representation becomes dependent on this existing model. And should the existing model change (like, you update the version of the library you use), you won't be able to unmarshal existing XML and will need migration mechanisms.
From my point of view, it is better to write an XML Schema and compile it to schema-derived classes. Then have a conversion routine to transfrom unmarshalled object structure to the target existing model.
JAXB unmarshalling of a XML file into objects works fine when run in testng unit testcase.
When the same code is used to unmarshall the same XML file in another process, I am getting an empty object. I could verify that objects are getting created for every element in the XML document and all the adapters are getting called. Set the event handler in unmarshaller but there were no validation issues. When I set the xmlns attribute and the prefix, the behavior was slightly different even though empty object is returned.
I saw several posts but could not relate with the problem I am facing.
Please suggest where I should start looking for the problem. Is it mandatory to specify schema when unmarshalling?
The cause is mentioned in this post: JAXB does not call Setter method.
Confirmed that the get method for the list is getting called and is populated.
Replaced the list with an array and the problem was solved.
The beauty of JAXB is it doesnot call the setter and it uses the same List from ther getter. In case of generating JAXB classes from XSD; you can even notice that the elements with maxOccurs=unbound required=true will not have a setter at all.
I'm trying to utilize the Loggly appender utility for log4net.
I've found that their code is enumerating through the ThreadContext properties and appending them to the payload getting sent over the wire to the loggly service. Good idea! However, the same feature is not being applied to the GlobalContext properties. Figuring this was a miss on their part I tried my hand at enumerating through the GlobalContext properties and adding these to the payload as well.
However, this has proven to be a problem. There doesn't appear to be any way to access the keys and associated values as the ThreadContext properties are accessed.
How can the GlobalContext properties be enumerated?
The only way I see would be to retrieve the properties class for the global context (GlobalContext.Properties which returns a GlobalContextProperties class) and get the ReadOnlyPropertiesDictionary returned by the internal method GetReadOnlyProperties() through reflection. Once you have the ReadOnlyPropertiesDictionary you can iterate on keys and values
From what I see the ThreadContext has more or less the same mechanism so you could take example on the ThreadContext enumeration to port it to the GlobalContext.
I use JAXB marshaller to store some java objects as XML files. Some of these objects reference each other, so I unsurprisingly obtain this error:
[com.sun.istack.internal.SAXException2: A cycle is detected in the object graph. This will cause infinitely deep XML
The solution which consists in removing the cycles and use only tree structure is not feasible - I need both navigability directions.
To solve this issue, I would rather use xlink to reference the xml objects instead of copying them in cascade. Is this solution pertinent? Is it possible to do that with JAXB marshaller? How?
You can implement an XLink approach in JAXB using an XmlAdapter. Below are links to various similar answers.
Serialize a JAXB object via its ID?
Using JAXB to cross reference XmlIDs from two XML files
Can JAXB marshal by containment at first then marshal by #XmlIDREF for subsequent references?
I lead the EclipseLink JAXB (MOXy) implementation, and we have the #XmlInverseReference extension for mapping bidirectional relationship that you may be interested in:
http://blog.bdoughan.com/2010/07/jpa-entities-to-xml-bidirectional.html
Dude, you can note in one of the entity the annotation #XmlTransient, so when unmarch, it will not complain about the cycle problem.
But with thius workaround after unmarch the xml you will have to populate the atribute with the #XmlTransient.
I was reading some paper and find this. You can set #XmlTransient and use the callback method to do something after the unmarch. So you can set the parent to you child.
public void afterUnmarshal(Unmarshaller u, Object parent) {
this.pessoa = (Pessoa) parent; }
When marshaling some objects into XML, I need to insert an additional field in each of the resulting XML objects - sort of flag. The purpose is not modifying the source objects but inserting that information in the output XML.
Any ideas if this is possible?
There are a few possible approaches:
1. Use an XmlAdapter
You could leverage JAXB's XmlAdapter. Here you would create a version of the classes with the extra field (the adapted classes could extend the original). Then convert between them in the adapter. Since the alternate version of the class would contain the extra field it would marshal out.
http://bdoughan.blogspot.com/2010/07/xmladapter-jaxbs-secret-weapon.html
2. Use Binder
If you marshal target is DOM, then you could leverage JAXB's Binder. It is intended for infoset preservation, but after a marshal it does maintain a link between the objects and the DOM nodes. Once the marshal is complete you could use the binder to find an object's associated node and update it.
http://bdoughan.blogspot.com/2010/09/jaxb-xml-infoset-preservation.html
3. Wrap the Output Target
If your output target is something like a ContentHandler or XMLStreamWriter then when the appropriate state is reached you could trigger additional events to be called on the nested marshal target.
The easiest way I can think of would be to use JAXB to marshal to a DOM, and then programmatically insert your extra information into that DOM, then re-marshal the DOM to XML.
Ugly and inefficient, but that's the best I can think of.