Serialising Objects to XML with Java, Groovy and XStream
From bemoko developer wiki
XStream provides a handy way of going from XML to Objects and back again. This article gives a quick example showing how you can use it within bemokoLive.
Full source for this example is located at http://code.google.com/p/bemoko/source/browse/#svn/sites/examples/trunk/xstream
Step 1 : Create your Site Configuration
Create your site-config.xml to config configuration, plugins, intents and logging for this example:
<?xml version="1.0" encoding="UTF-8"?> <site> <config> <source file="examples~xstream.cfg"/> </config> <content-sources> <source name="proxy" plugin="XmlProxy"/> </content-sources> <intents> <intent name="i" view="index.html"/> </intents> <logging> <priority value="DEBUG" expr="!config.prod" showLocation="true"/> <priority value="INFO" expr="config.prod"/> </logging> </site>
Step 2 : Create And Register Some Site Custom Configuration
Create the file conf/examples~xstream.cfg which configures the a tmp.directory configuration property which we'll use in the plugin in the next step:
tmp.directory = System.getProperty("java.io.tmpdir")
Step 3 : Create The Plugins
Create two domain objects, plugins/domain/Group.groovy
class Group { def name def people = [] }
and plugins/domain/Person.groovy
class Person { def name int age }
and then create a plugin to read serialise and deserialise objects to and from XML
import com.bemoko.live.platform.Bemoko import com.thoughtworks.xstream.XStream import domain.Group import domain.Person @Grab(group='com.thoughtworks.xstream', module='xstream', version='1.3') @Grab(group='xpp3', module='xpp3_min', version='1.1.3.4.O') class XmlProxy { def log = Bemoko.log def model def action @Lazy objectXmlFile = new File("${Bemoko.config.tmp.directory}/example-xstrema-object.xml") void execute(Map p) { action = p.action ?: "load" if (log.debugEnabled) log.debug("Action = ${action}") switch (action) { case ("load") : model = getGroupFromXml() break case ("create") : model = createXmlFromGroup( new Group( name : "mygroup", people : [ new Person (name : "Bob", age : 24), new Person (name : "Jane", age : 29), ] ) ) break } } def getXml() { return objectXmlFile.text } def createXmlFromGroup(group) { objectXmlFile.withOutputStream { out -> new XStream().toXML(group, out) } } def getGroupFromXml() { if (objectXmlFile.exists()) { objectXmlFile.withInputStream { input -> return new XStream().fromXML(input) } } } }
Step 4: Render the Page
Then create a simple HTML template to render this content at ui/root/index.html:
<?xml version="1.0" encoding="UTF-8"?> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>XStream example</title> </head> <body> <h1>XStream example</h1> <p>See <a href="http://xstream.codehaus.org/">XStream for more details on XStream</a></p> [#switch content.proxy.action] [#case "load"] <div>XML Loaded</div> [#if content.proxy.model??] [#assign group = content.proxy.model] <div> Group name : ${group.name} <ul> [#list group.people as person] <li>name : ${person.name} (${person.age})</li> [/#list] </ul> </div> [#else] <div>XML not yet created, please click <a href="/i/action/create">here</a> to create</div> [/#if] [#break] [#case "create"] <div>XML Created</div> <div style="margin:20px;font-size:10pt"> ${content.proxy.xml} </div> [#break] [/#switch] <hr/> <div> <div><a href="/i/action/load">Load XML to Object</a></div> <div><a href="/i/action/create">Create XML from Object</a></div> </div> <hr/> <div>File = ${content.proxy.objectXmlFile}</div> </body> </html>
Step 5 : Access your site
Go to the i intent on you site, e.g. http://localhost:8080/live/examples/xstream/i, and click on the link to create the XML from the object. You should see that the Group object gets serialised down to XML. Now when you click on load you should see the object read back from XML.
This is a very light weight of loading XML into objects which can be used to render in a bemokoLive site. Have a look on the XStream web site if you want any more information on how to to use XStream.
