Java version 1.3 didn’t introduce much on this side so we will skip ahead to the focus of this entry. In Java 1.4 Sun included a much needed encoding and decoding framework for “JavaBeans”. I put JavaBeans in quotations because it is actually much more powerful than that. It will decode and encode virtually any Java class you wish because of how flexible it is. Essentially, it lets you write Java code in an XML file… much like the Spring IoC Framework. Let’s look at a simple configuration using the Spring Framework and then I will show you the equivalent in the JDK:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd"> <beans> <!-- example of list and map and idref and property values --> <bean id="cityFinder" class="com.tallsoft.springeg.CityScape" singleton="true"> <property name="cityMap"> <map> <entry key="LDN"><value>London</value></entry> <entry key="FFT"><value>Frankfurt</value></entry> </map> </property> </bean> <!-- example of list and depends on for creation ordering--> <bean id="region" class="com.tallsoft.springeg.RegionInfo" depends-on="cityFinder"> <property name="cityFinder"><idref local="cityFinder"/> </property> <property name="regions"> <list> <value>Europe</value> <value>America</value> </list> </property> </bean> </beans>
This is a relatively straight-forward configuration file that specifies two beans, one contains the other and each of them contains a complicated property. So what is this mysterious IoC framework that we are going to use in the JDK? It is none other than java.beans.XMLDecoder. When JavaSoft realized that serializing beans was a nasty business because of versioning issues they created this class and its brother the XMLEncoder to take its place. Instead of little “pickled” (nice name Sun) JavaBeans stored in .ser files you have .xml files with something that is vaguely human readable, at least as much as that Spring stuff is. So what does the translated system look like? Here we go:
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE javabeans SYSTEM "http://www.javarants.com/schemas/javabeans.dtd"> <java version="1.4.2" class="java.beans.XMLDecoder"> <object id="cityFinder" class="com.sampullara.jbioc.CityScape"> <void property="cityMap"> <object class="java.util.HashMap"> <void method="put"> <string>LDN</string> <string>London</string> </void> <void method="put"> <string>FFT</string> <string>Frankfurt</string> </void> </object> </void> </object> <object id="region" class="com.sampullara.jbioc.RegionInfo"> <void property="cityFinder"><object idref="cityFinder"/></void> <void property="regions"> <object class="java.util.ArrayList"> <void method="add"><string>Europe</string></void> <void method="add"><string>America</string></void> </object> </void> </object> </java>
Interestingly, the format for this file is slightly more powerful in some ways by being infinitely flexible, but it is missing some of the abstraction features like templates that the Spring framework has… at least I think so. I am going to be experimenting with it some more in coming days since I think I’d rather use something built into the JDK than add a ton of new frameworks. Here is the code for loading the config file:
XMLDecoder xmldecoder = new XMLDecoder(getClass().getResourceAsStream("/config.xml"), this); CityScape cityScape = (CityScape) xmldecoder.readObject(); RegionInfo regionInfo = (RegionInfo) xmldecoder.readObject();
Amazingly, Sun even has some good documentation on the femtocontainer. I would love to hear from people what other major features within the spring xml file would be nice to see implemented using this system rather than Spring or other containers. Next I am going to be looking at how modern Java users could reuse BeanContext for all their other container needs….
Here is the sample with a unit test and a build script.
Update: Here is a schema for the javabeans XMLDecoder for people who want better validation than the DTD.