Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails: How to dump an object's properties?

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.

like image 516
EpicVoyage Avatar asked Jun 25 '13 16:06

EpicVoyage


2 Answers

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, age
Child 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 Parents 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.

like image 116
dmahapatro Avatar answered Oct 17 '22 08:10

dmahapatro


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.

like image 36
JavaDev Avatar answered Oct 17 '22 09:10

JavaDev