Abstraction Builder

Building simple and elegant programming abstractions

Schema Driven Nano Binding

| Comments

Nano is a light weight xml/json binding framework targeting Android platform, in this post, I will show you how to use Nano and the accompanying compiler tool mxjc together to do schema driven xml or json data binding - similar to the development process using JAXB and XJC.

The Big Picture

A picture is worth a thousand words, a typical schema driven xml data binding development includes two main phases:

  1. Build Time - in this phase, we authorize xml scheam or xsd first, the schema specifies the metadata of our business domain, this is the single source of truth, later code generation all depends on the scheam, only if the scheam changes, then we need to regenerate source code. With schema specified, we use the mxjc schema binding compiler to compile the scheam into Nano bindable classes, mxjc is based on JAXB xjc, so its usage is similar to xjc. Classes generated by mxjc will be annotated with Nano annotations, these annotations specify the mapping between pojo and xml, they will later be scanned by Nano binding framework to guide the real marshalling or unmarshalling at runtime.
  2. Runtime time - in this phase, we have Nano bindable domain class in hand, what’s left is to do marshalling or unmarshalling according to real needs, by leveraging Nano binding framework. Nano is a middle man between XML/JSON document and java object, when objects or pojos are fed into the Nano binding framework, it can marshall them or serialize them into either XML or JSON content, and when XML or JSON content is fed into the Nano binding framework, it can unmarshall or deserialize them into objects or pojos.

By the way, scheam driven development is good for some scenario with complex business domain, without formal schema and automated code generation, the manual written code base will be very hard to maintain. However, when your use case is simple, it’s not necessary to begin with scheam, just write your domian class then annotate with Nano annations is also workable.

A Zoo Sample

I’ve create an ant project to demo the scheam driven developmeng with Nano and mxjc, you can find the project here, you can download the whole project and run it with Ant(suppose you have Ant installed).

Belew is the Ant build file which includes all scheam driven development stets mentioned above:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" standalone="yes"?>

<project basedir="." default="run">
  <property name="sample.home" value="." />
  <path id="classpath">
    <pathelement path="classes" />
    <fileset dir="${sample.home}" includes="lib/mxjc/*.jar" />
    <fileset dir="${sample.home}" includes="lib/nano/*.jar" />
  </path>
  <taskdef name="mxjc" classname="com.leansoft.mxjc.MXJCTask">
    <classpath refid="classpath" />
  </taskdef>

  <!--compile Java source files-->
  <target name="compile" description="Compile all Java source files">
    <echo message="Compiling the schema..." />
    <mkdir dir="gen-src" />
    <mxjc schema="schema/zoo.xsd" package="com.leansoft.nano.zoo" destdir="gen-src" removeOldOutput="yes">
      <produces dir="gen-src/com/leansoft/nano/zoo" includes="**/*.java" />
    </mxjc>
    <echo message="Compiling the java source files..." />
    <mkdir dir="classes" />
    <javac destdir="classes" debug="on">
      <src path="src" />
      <src path="gen-src" />
      <classpath refid="classpath" />
    </javac>
  </target>

  <target name="run" depends="compile" description="Run the sample app">
    <echo message="Running the sample application..." />
    <java classname="com.leansoft.nano.sample.ZooExample" fork="true">
      <classpath refid="classpath" />
    </java>
  </target>

  <target name="clean" description="Deletes all the generated artifacts.">
    <delete dir="gen-src" />
    <delete dir="classes" />
  </target>
</project>

mxjc provides an Ant task called MXJCTask, similar to xjc ant task, mxjc ant task can also auto-generate source from scheam driven by Ant.

Following the xml scheam(xsd):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <xsd:element name="zoo" type="zooInfo"/>
  <xsd:element name="comment" type="xsd:string"/>
  <xsd:complexType name="zooInfo">
    <xsd:sequence>
      <xsd:element name="zooName" type="xsd:string"/>
      <xsd:element name="zooId" type="xsd:int"/>
      <xsd:element name="animals" type="Animals"/>
    </xsd:sequence>
  </xsd:complexType>

  <xsd:complexType name="Animals">
    <xsd:sequence>
      <xsd:element name="animal" minOccurs="1" maxOccurs="unbounded">
        <xsd:complexType>
          <xsd:sequence>
            <xsd:element name="animalName" type="xsd:string"/>
            <xsd:element name="animalType" type="xsd:string"/>
          </xsd:sequence>
        </xsd:complexType>
      </xsd:element>
    </xsd:sequence>
  </xsd:complexType>
</xsd:schema>

The XML document which we are going to read and print in console:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?xml version="1.0"?>
<zoo>
  <zooName>Vandalur Zoo</zooName>
  <zooId>12321</zooId>
  <animals>
    <animal>
      <animalName>Lion</animalName>
      <animalType>Wild</animalType>
    </animal>
    <animal>
      <animalName>Dog</animalName>
      <animalType>Domestic</animalType>
    </animal>
    <animal>
      <animalName>White Tiger</animalName>
      <animalType>Wild</animalType>
    </animal>
  </animals>
</zoo>

Following is the main java code to read the xml file, output some content, and then write the whole objects into json output.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
package com.leansoft.nano.sample;

import java.io.FileInputStream;
import java.util.List;

import com.leansoft.nano.IReader;
import com.leansoft.nano.IWriter;
import com.leansoft.nano.NanoFactory;
import com.leansoft.nano.zoo.Animals;
import com.leansoft.nano.zoo.ZooInfo;
import com.leansoft.nano.zoo.animals.Animal;

public class ZooExample {
  
  public static void main(String[] args) {
      try {
          
          IReader xmlReader = NanoFactory.getXMLReader();
          
          ZooInfo zooInfo = xmlReader.read(ZooInfo.class, new FileInputStream("xml/zoo.xml"));
          
          System.out.println("Output after xml read - ");
          System.out.println("Zoo Name: " + zooInfo.getZooName());
          System.out.println("Zoo Id: " + zooInfo.getZooId());
      
          Animals animals = zooInfo.getAnimals();
          List<Animal> animalsList = animals.getAnimal();
      
          for (Animal animal : animalsList) {
              System.out.println("\t" + animal.getAnimalName());
              System.out.println("\t\t" + animal.getAnimalType());
          }
          
          IWriter xmlWriter = NanoFactory.getJSONWriter();
      
          System.out.println("Output after json write - ");
          xmlWriter.write(zooInfo, System.out);
      
          
      } catch(Exception e) {
          e.printStackTrace();
      }
  }

}

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Output after xml read -
Zoo Name: Vandalur Zoo
Zoo Id: 12321
  Lion
      Wild
  Dog
      Domestic
  White Tiger
      Wild
Output after json write -
{"zoo": {
    "animals": {"animal": [
        {
            "animalName": "Lion",
            "animalType": "Wild"
        },
        {
            "animalName": "Dog",
            "animalType": "Domestic"
        },
        {
            "animalName": "White Tiger",
            "animalType": "Wild"
        }
    ]},
    "zooId": 12321,
    "zooName": "Vandalur Zoo"
}}

Conclusion

When used properly, scheam driven development can greatly improve agaility in development, and just as I have showed in the post, Nano with mxjc supports scheam driven development smoothly, you may tell me that you would rather choose JAXB to do scheam driven development, I admit that JAXB is more mature and feature-rich than Nano, but one cool thing of Nano is it supports Android platform while JAXB does not, Nano is just tailored for Android platform, in later posts, I will show you how to practice scham driven data binding on Android platform, it’s facinating, stay tuned.

Comments