The setup:
I am working on a Grails project that involves a lot of XML data transfers. We are using Apache CXF's wsdl2java utility to generate the appropriate Java classes for the data formats.
We are caching some of the XML results and I need to find out if we have already cached a specific value at a specific point in the code (this has happened before).
What I am looking for:
A way to recursively dump random objects.
What I have tried so far:
1) println() -- This works well for hashmaps with basic types like Strings and Integers, but fails on generic Objects. It outputs the wsdl2java class's .toString() output, which resembles "com.company.services.provider.ADDRESS@2b1234ca1." Since this is an auto-generated class, we cannot replace that method easily.
2) The method outlined here: http://padcom13.blogspot.com/2009/12/groovy-dumping-objects-properties.html
I have wrapped this in a function and added it to the Object.metaClass in BootStrap.groovy. That allows it to be called recursively; however, only about half of the wsdl2java classes seem to inherit this function (verified with "println(obj.metaClass.metaMethods*.name.sort())"). None of them explicitly extend Object so I am lost.
What is the cleanest way to recursively dump a random object's properties (preferably human-readable)?
Thanks in advance!
EDIT:
Many thanks to @dmahapatro and @JavaDev for their ideas. Here is the code that I am looking at right now:
import grails.converters.JSON
Object.metaClass.debug_dump = {
JSON.use('deep')
println(new JSON(delegate).toString())
}
...
session.cxfResult.debug_dump()
And this is the error that it produces when run:
Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl with modifiers "public". Stacktrace follows:
Message: Class org.codehaus.groovy.grails.web.converters.marshaller.json.GenericJavaBeanMarshaller can not access a member of class org.apache.xerces.jaxp.datatype.XMLGregorianCalendarImpl with modifiers "public"
This persists despite following the directions of this individual on the Grails user list.
Best possible option would be to render the object graph as deep JSON or XML (cannot achieve with normal JSON or XML converters). Grails provides converters which effectively parses the object graph to a human readable form and is also useful for rendering response in webservice calls. Below is a detailed example as to how an object graph can be rendered either to a valid JSON Object or an XML.
Use Case:
Consider an object graph like:
Parent
has Child
, name, dob, ageChild
has name, dob, age, GrandChild
and has many Qualities
GrandChild
has Address
, blah, blah etc
Sample
Detail example using domain objects with outputs can be found here.
Detail example using POGOs with outputs can be found here
Key Area:
The key area to focus on is the controller method where all Parent
s are fetched and serialized as JSON or XML
//Parent Controller
import grails.converters.JSON
import grails.converters.XML
def index() {
JSON.use('deep')
render Parent.all as JSON
//XML.use('deep')
//render Parent.all as XML
}
Inference:
Grails converters can also be used for normal POGO object graphs and are not only confined to domain objects. You can either write the response to an out stream, log appender or to an http response, you could achieve the deep serialization of the object graph from root to leaf node in all cases.
The example mentioned in above would make it clear as to how the out format would look like.
Sample apps written and tested using Grails 2.2.2.
You can try use to render the object as JSON instead of using making it implicitly call toString(). I think it will render the structure of the object properly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With