Online Books:
java.net on MarkMail:
Search |
||||||||||||||||||||||||||||||||||||
Open Source: DigesterPosted by sayedh on September 21, 2005 at 7:18 PM PDT
So this is the first is a series of Open Source entries that I'll make. I would like to raise awareness of open source projects available to Java developers. To help achieve this I'll download/play with some projects, some that I've used before and some that I haven't. Then I'll discuss my experience with it. Also the more feedback the better, good or bad! Also I'd like to have a consistent format for these entries, so if you notice any changes that you think I should make please let me know. On with this blog!
Apache DigesterIn this blog we will examine the Apache Digester which is included in the Jakarta Commons project.MotivationThe reason why I chose the Digester is because it seems to be a simple alternative to reading XML files with out needing an XSD. Also I have used the Digester before so I'm a little familiar with it, but I'd like to get to know more as well. I'm interested to hear what you guys say about your experience with the Digester.Background (Appetizer)As applications and services move towards adaptability and inter-operatibility the use of XML continues. When faced with the problem of handling XML files there are many options to the Java developer. Here is a brief listing of some of those options.
For a better comparison of this see the Related Resources. Beef & Potatoes (Main course)Now we have come to the main course I'll show you how to get the Digester and some simple example(s) of its use. I'll also present some sample code that I've written to demonstrate the use of the Digester, and all of it is available to you. As you continue to read or while you look through the code keep in mind that I'm new to the Digester so I may have, and probably, did make some mistakes in its use, and I hope you point them out! I'd much rather make a mistake here than in production code :) How to get the code is described at the end of this entry.First of all you'll want to download the Digester, you can find it in the Jakarta Commons project. I imagine I'll be looking at a bunch of these projects so you might as well get used to hearing that name. :) Many cool things happening over there. Ok so the project documentation page says: Many Jakarta projects read XML configuration files to provide initialization of various Java objects within the system. There are several ways of doing this, and the Digester component was designed to provide a common implementation that can be used in many different projects. So in a nutshell if you need to read an XML file then the Digester may be a good choice for you. However if you also need to, or better yet ever may need to, write the contents back to an XML file the Digester is NOT and option for you. Its kinda like a one-way hash, no functionality to go the other way :) Now the Digester seems to be using a SAX based parser in the backend so keep that in mind as you are using it. It kinda explains some things about how you are going to use it. Basically here are the steps to use the Digester:
<?xml version="1.0" encoding="ISO-8859-1"?>
<entries>
<entry owner="sayedh" created="2005-09-19T08:30:00-05:00">
<subject style="simple">Sample subject</subject>
<body style="bodySimple">The contents of last nights dream goes right in here!</body>
<permissions>
<include>
<user>mollyk</user>
<user>mikem</user>
<user>keelys</user>
<user>gilbertoc</user>
<group>friends0</group>
</include>
<exclude>
<user>desireel</user>
</exclude>
</permissions>
</entry>
<entry owner="sayedh" created="2005-09-17T04:25:00-05:00">
<subject style="simple">Subject 2</subject>
<body style="bodySimple">Body 2 in here</body>
<permissions>
<include>
<group>everyone</group>
</include>
<exclude>
<user>desireel</user>
</exclude>
</permissions>
</entry>
<entry owner="sayedh" created="2005-09-16T01:25:22-05:00">
<subject style="simple">Subject 3</subject>
<body style="bodySimple">Body 3 in here</body>
<permissions>
<include>
<group>everyone</group>
</include>
<exclude>
<user>desireel</user>
</exclude>
</permissions>
</entry>
</entries>
This represents a overly simplified possible representation of entries in a journal. Note: I'm the owner of the
Dreamcatcher Project which is an eXtensible forum. The example code will be available on that
project page so I'll try to make most of it somehow related. But this XML file is obviously not what is going to be used :)
In the sample code you'll see that we have to following objects defined, with the exception of the parsing classes.
In addition to this you'll find 2 classes that are responsible for parsing the files those are:
/**
* Have digester read the XML string and return all entries contained within it
* @param str
* @return
* @throws SAXException
* @throws IOException
*/
public EntryCollection buildFromXMLString() throws IOException, SAXException{
Digester digester = new Digester();
digester.setValidating(false);
digester.addObjectCreate( "entries",EntryCollection.class );
//now deal with Entry class
digester.addObjectCreate("entries/entry", Entry.class);
digester.addSetProperties("entries/entry", "owner", "owner");
digester.addSetProperties("entries/entry","created","created");
digester.addSetNext("entries/entry","addEntry");
digester.addBeanPropertySetter("entries/entry/subject", "subject");
digester.addSetProperties("entries/entry/subject","style","subjectStyle");
digester.addBeanPropertySetter("entries/entry/body","body");
digester.addSetProperties("entries/entry/body","style","bodyStyle");
digester.addObjectCreate("entries/entry/permissions", Permissions.class);
digester.addCallMethod("entries/entry/permissions/include/user", "includeUser",0);
digester.addCallMethod("entries/entry/permissions/include/group", "includeGroup",0);
digester.addCallMethod("entries/entry/permissions/exclude/user", "excludeUser",0);
digester.addCallMethod("entries/entry/permissions/exclude/group", "excludeGroup",0);
digester.addSetNext("entries/entry/permissions/", "setPermissions", "com.sedodream.blog.dig.Permissions");
EntryCollection parsedValue = (EntryCollection)( digester.parse( this.inputFile ) );
return parsedValue;
}
That's only 17 lines of create the mapping and to actually build those objects! That is the strong point of the Digester.
You don't have to create crazy methods to deal with startElement and you don't need to bind to a specific XSD. The binding to a
an XSD is one thing that turned me on to the Digester, because many of the XML documents that I work with are a work in progress. It's quite
rare that their definition be set in stone. So I need a method to parse the files that is not bound to that. Also another cool thing, all the
parsing is in one place and easy to understand, after you get the hang of it that is. So if your XML file changes a lot, you still only have
17 lines of code to change! Now on to the XML file that describes these rules, here it is.
<?xml version="1.0"?>
<digester-rules>
<object-create-rule pattern="entries" classname="com.sedodream.blog.dig.EntryCollection" />
<object-create-rule pattern="entries/entry" classname="com.sedodream.blog.dig.Entry" />
<set-properties-rule pattern="entries/entry">
<alias attr-name="owner" prop-name="owner" />
<alias attr-name="created" prop-name="created" />
</set-properties-rule>
<pattern value="entries/entry">
<set-next-rule methodname="addEntry" />
<call-method-rule methodname="setOwner" pattern="owner"/>
<bean-property-setter-rule pattern="subject" propertyname="subject"/>
<set-properties-rule pattern="subject">
<alias attr-name="style" prop-name="subjectStyle"/>
</set-properties-rule>
<bean-property-setter-rule pattern="body" propertyname="body"/>
<set-properties-rule pattern="bodyStyle">
<alias attr-name="style" prop-name="subjectStyle"/>
</set-properties-rule>
<object-create-rule pattern="permissions" classname="com.sedodream.blog.dig.Permissions" />
<pattern value="permissions">
<pattern value="include">
<call-method-rule pattern="user" methodname="includeUser" paramcount="0" paramtypes="java.lang.String" />
<call-method-rule pattern="group" methodname="includeGroup" paramcount="0" paramtypes="java.lang.String" />
</pattern>
<pattern value="exclude">
<call-method-rule pattern="user" methodname="excludeUser" paramcount="0" />
<call-method-rule pattern="group" methodname="excludeGroup" paramcount="0" />
</pattern>
<set-next-rule methodname="setPermissions" paramtype="com.sedodream.blog.dig.Permissions" />
</pattern>
</pattern>
</digester-rules>
Ok, so at this point I could dive into how you should create these rules and what is what but I'm not going to do that. For a couple of reasons
When given the option to write the rules in code or in XML, always pick in XML. I thought that it was much easier to see how the rules related to my XML file when I was creating the XML file. In your case if you don't have to, I would disregard the code based rules all together. I think that you'll grasp the workings of the Digester much easier when writing the XML files and you'll be more likely to reduce the time you spend writing those rules. Also I didn't find much good documentation about the format of the XML rules so I had to resort to the digester-rules.dtd file which is included with the Digester distribution. If you can't find what you're looking for online after like 1 minute, I'd look there for sure. ConclusionsDespite liking the Digester and actually having fun learning it, I will continue to be cautious when faced with the decision to use it or not. Because there is no means to go from Java Object -> XML only XML -> Java Object. So in that light I'll be looking for some other options in the future, most likely the next one will be Castor, but probably not for a while. Oh wait I think I'd be more likely to evaluate using Hibernate for this task first. It is more close to a project that I'm working on currently. I'll be sure to let you know how that goes.Please let me know what you think of this entry and what's wrong with it. Always looking for feedback. About the source you can always get the latest version at my Dreamcatcher Project page. Just go to 'Version control - CVS' link on the left and you can either browse the source online or download it. Also I have made all the source available in zip at: example source for your convenience. You will find a build.xml file which is an ant build file. From that you can compile and run the examples. Note you'll need Java 5 for this. Related Resources
Relevant Environment Info
»
Related Topics >>
Open Source Comments
Comments are listed in date ascending order (oldest first)
|
||||||||||||||||||||||||||||||||||||
|
|