Generating Java code

After you've downloaded and built JaxMe, you're ready to use it. (See Building JaxMe for specific information.)

In this document, you'll do the following:

  1. Design the JaxMe schema
  2. Run the JaxMe code generator to generate Java code based on the JaxMe schema
  3. Run a test application to convert XML data into Java objects
  4. Run another test application to convert Java objects into XML data

1.  Designing the JaxMe schema

The first step is to create a JaxMe schema file that will serve as your mapping specification.  For a complete explanation of the JaxMe schema, see About the JaxMe Schema .

In this tutorial, we'll use the Address.xsd file that is in the JaxMe distribution.

A section of this JaxMe schema is shown here:

      <?xml version="1.0" encoding="iso-8859-1"?>
      <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
        targetNamespace="http://net/sourceforge/jame/namespaces/examples/Address"
      xmlns:jm="http://ispsoft.de/namespaces/jaxme/schema">
        <xs:annotation>
      <xs:documentation>
            A simple JaxMe example: Personal address collection.
          </xs:documentation>
          <xs:appinfo>
            <jm:defaults package="net.sourceforge.jaxme.address"/>
          </xs:appinfo>
        </xs:annotation>

        <xs:element name="Address">
          <xs:complexType>
            <xs:sequence>
              <xs:element name="Name">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="First"/>
                    <xs:element name="Middle" minOccurs="0"
                      maxOccurs="unbounded"/>
                    <xs:element name="Last"/>
                    <xs:element name="Initials" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="Postal">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Street"/>
                    <xs:element name="ZIP"/>
                    <xs:element name="City"/>
                    <xs:element name="State" minOccurs="0"/>
                    <xs:element name="Country" minOccurs="0"/>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="PhoneDetails" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Phone" minOccurs="0"
                        maxOccurs="unbounded">
                        <xs:complexType>
                  <xs:sequence>
                          <xs:element name="PhoneNumber"/>
                        </xs:sequence>
                        <xs:attribute name="type" use="required"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>
                </xs:complexType>
              </xs:element>
              <xs:element name="EmailDetails" minOccurs="0">
                <xs:complexType>
                  <xs:sequence>
                    <xs:element name="Email" minOccurs="0"
                maxOccurs="unbounded">
                      <xs:complexType>
                        <xs:sequence>
                          <xs:element name="EmailAddress"/>
                        </xs:sequence>
                        <xs:attribute name="type" use="required"/>
                      </xs:complexType>
                    </xs:element>
                  </xs:sequence>  
                </xs:complexType>
              </xs:element>
            </xs:sequence>
            <xs:attribute name="id"/>
          </xs:complexType>
        </xs:element>
      </xs:schema>
In this tutorial, we'll also be using the following XML document (Address.xml ), which is based on the JaxMe schema Address.xsd.
<?xml version="1.0"?>
<Address xmlns="http://net/sourceforge/jaxme/namespaces/examples/Address">
  <Name>
    <First>Jane</First>
    <Middle>Lee</Middle>
    <Middle>Chris</Middle>
    <Last>Doe</Last>
    <Initials>(JD)</Initials>
  </Name>
  <Postal>
    <Street>34 Main Street</Street>   
    <City>Boston</City>
    <State>MA</State>   
    <ZIP>02215</ZIP>
  </Postal>
  <PhoneDetails>
    <Phone type="Work">
    <PhoneNumber>555.5789</PhoneNumber>
    </Phone>
    <Phone type="Fax">
    <PhoneNumber>555.1212</PhoneNumber>
    </Phone>
  </PhoneDetails>
  <EmailDetails>
    <Email type="Private">
      <EmailAddress>jdoe@yourcompany.com</EmailAddress>
    </Email>
    <Email type="Office">
      <EmailAddress>josephdoe@mycompany.com</EmailAddress>
    </Email>
  </EmailDetails>
  </Address>

2.  Running the JaxMe code generator

Now that we have a JaxMe schema, we're ready to run the JaxMe code generator.

Run the following commands  (assuming bash):

        # set to the JaxMe distribution
        jaxme=~/JaxMe

        java -cp $jaxme/prerequisites/log4j.jar:$jaxme/dist/jaxme.jar \
           de.ispsoft.jaxme.generator.Main       Address.xsd \
           --sourceWriter=de.ispsoft.jaxme.generator.JavaSourceWriter

See Building JaxMefor a discussion of the prerequisite jars.

You can use an ant script to run the JaxMe code generator, as described in Writing an ant script.

JavaSourceWriter generates Java sources that are based on the specific JaxMe schema given in this command (Address.xsd). JavaSourceWriter generates a subclass of JMAnyElement and a SAX2 ContentHandler that can parse XMLinstances of the given document type.

Note: When you run the code generator, the specific SourceWriter you choose will depend on your goals. For example, the JdbcJavaSourceWriter is used to read data from or write data to a relational table via JDBC.  See Reference and Javadoc for information about currently available SourceWriters.

To view the generated Java code, go to the directory that is specified for package in the JaxMe schema.  In this example (the JaxMe schema Address.xsd), the package specified is net/sourceforge/jaxme/address.

      <xs:appinfo>
         <jm:defaults package="com.mycompany.com"/>
      </xs:appinfo>
In this directory, you'll see the generated Java source code, including the following: You'll also see similar Java sources for the other JaxMe schema subelements such as Postal (ClsPostal.java). ClsPostal contains the variables eStreet, eZip, eCity, eState, and eCountry.

As you can see, the contents of a JaxMe schema are mapped to Java member variables.  In the above example, the instance of ClsAddress has a variable eName, which holds the details of the name from Address.xsd. The first name is eName.eFirst.

A simple element type in the JaxMe schema is mapped to java.lang.String. For example, ClsName contains public java.lang.String.eFirst. A complex element type in the JaxMe schema is mapped to the next level of Cls*.java. For example, ClsAddress contains ClsName eName.

The variable eName has a type ClsName. However, the type of eEmail is java.util.List. This element may occur multiple times and is used to represent a list of email addresses. The type of ePhone is also java.util.List.

A note about repetition and null values:  If minOccurs="0" then the reference may be null. If minOccurs="1" and maxOccurs="1" then the reference will not be null. If maxOccurs is greater than 1, then max will be java.util.List, and if minOccurs=0, then the reference may be null.

Internal members are named according to the following conventions: A JaxMe schema element XXX (such as Postal) is converted to Java member variable eXXX (such as ePostal). An attribute YYY (such as Type) is converted to Java member variable aYYY (such as aType).

3.  Reading XML data into Java objects

Next, you'll integrate the generated code into your Java application, which will read data from an XML document into Java objects.

In this tutorial, we'll use AddressPrinter.java as our test application (shown below). This application will take Address.xml as input, generate Java objects, and print the data.

JaxMe imports the Java source code that it had generated (see the preceding step in this procedure), instantiates ClsAddress, and uses the JMFileManager to set the SAX ContentHandler for reading elements.

To compile the application, you need to specify the classpath of jaxme-rt.jar; for example (assuming bash):

        # set to the JaxMe distribution
        jaxme=~/JaxMe

        javac -classpath   $jaxme/prerequisites/log4j.jar:$jaxme/dist/jaxme-rt.jar \
           -sourcepath .  AddressPrinter.java \

See Building JaxMefor a discussion of the prerequisite jars.

To run the application, you also need to specify the classpath of jaxme-rt.jar:

   # set to the JaxMe distribution
        jaxme=~/JaxMe

        java  -classpath    $jaxme/prerequisites/log4j.jar:$jaxme/dist/jaxme-rt.jar \
             AddressPrinter \

import net.sourceforge.jaxme.address.ClsAddress;
import net.sourceforge.jaxme.address.ClsAddressHandler;
import net.sourceforge.jaxme.address.ClsName;
import net.sourceforge.jaxme.address.ClsPostal;
import net.sourceforge.jaxme.address.ClsPhone;
import net.sourceforge.jaxme.address.ClsEmail;
import de.ispsoft.jaxme.JMFileManager;

public class AddressPrinter {
    public static void main(String[] args) throws Exception {
        // Instantiate a JMFileManager and set its SAX content handler
        // to the generated class ClsAddressHandler.  This glues the
        // reading of an XML input document to the parsing code.
        JMFileManager manager = new JMFileManager();
        manager.setJMContentHandlerClass(ClsAddressHandler.class);

        // Loop over XML documents within the file.  
        for (java.util.Iterator iter = manager.select("Address.xml");
             iter.hasNext();  ) {

            // Each iteration returns a generic iteration object,
            // which we must first cast to the generated class
            // ClsAddress.  Then we have access to its internal
            // members which automatically contain the file's XML
            // content.  

            ClsAddress ca = (ClsAddress) iter.next();
            System.out.println ("eName.eFirst = " + ca.eName.eFirst);


            if (ca.eName.eMiddle != null)
                System.out.println ("eName.eMiddle = " + ca.eName.eMiddle);

            System.out.println ("eName.eLast = " + ca.eName.eLast);

            if (ca.eName.eInitials != null)
                System.out.println ("eName.eInitials = " + ca.eName.eInitials);

            System.out.println ("ePostal.eStreet = " + ca.ePostal.eStreet);
            System.out.println ("ePostal.eCity = " + ca.ePostal.eCity);
            System.out.println ("ePostal.eZip = " + ca.ePostal.eZIP);

            if (ca.ePostal.eState != null)
                System.out.println ("ePostal.eState = " + 
                                    ca.ePostal.eState);

            if (ca.ePostal.eCountry != null)
                System.out.println ("ePostal.eCountry = " + 
                                    ca.ePostal.eCountry);
            
  
            if (ca.ePhoneDetails != null) {
                for (java.util.Iterator phoneIter = 
                         ca.ePhoneDetails.ePhone.iterator();
                     phoneIter.hasNext();  ) {
                    ClsPhone ePhone = (ClsPhone) phoneIter.next();


                    // Note: aType is a required attribute, so no need
                    // to check for null.
                    System.out.println 
                        ("ePhoneDetails.ePhone.aType = " +
                         ePhone.aType);

                    System.out.println 
                        ("ePhoneDetails.ePhone.ePhoneNumber = " +
                         ePhone.ePhoneNumber);
                }
            }


            if (ca.eEmailDetails != null) {
                for (java.util.Iterator eMailIter = 
                         ca.eEmailDetails.eEmail.iterator();
                     eMailIter.hasNext();  ) {
                    ClsEmail eMail = (ClsEmail) eMailIter.next();


                    // Note: aType is a required attribute, so no need
                    // to check for null.
                    System.out.println 
                        ("eMailDetails.eMail.aType = " +
                         eMail.aType);

                    System.out.println 
                        ("eMailDetails.eMail.eEmailAddress = " +
                         eMail.eEmailAddress);
                }
            }

        }
    }
}

4.  Writing XML data from Java objects

As our last step in this tutorial, we run the AddressCreator application to create XML data from Java objects.

Again, note that to compile and run the application, you need to specify the classpath of jaxme-rt.jar:

    java  -classpath prerequisites/log4.jar:dist/jaxme-rt.jar  AddressCreator.java
 

import net.sourceforge.jaxme.address.ClsAddress;
import net.sourceforge.jaxme.address.ClsEmail;
import net.sourceforge.jaxme.address.ClsEmailDetails;
import net.sourceforge.jaxme.address.ClsName;
import net.sourceforge.jaxme.address.ClsPhone;
import net.sourceforge.jaxme.address.ClsPhoneDetails;
import net.sourceforge.jaxme.address.ClsPostal;
import de.ispsoft.jaxme.JMFileManager;

public class AddressCreator {
    public static void main(String args[]) throws Exception {
        JMFileManager manager = new JMFileManager();
        ClsAddress addr = new ClsAddress();
        addr.eName = new ClsName();
        addr.eName.eFirst = "Jane";
        addr.eName.eLast = "Doe";

        addr.ePostal = new ClsPostal();
        addr.ePostal.eStreet = "34 Main Street";
        addr.ePostal.eCity = "Boston";
        addr.ePostal.eState = "MA" ;
        addr.ePostal.eZIP = "02215";

        addr.eEmailDetails = new ClsEmailDetails();
        addr.eEmailDetails.eEmail = new java.util.ArrayList();

        ClsEmail email = new ClsEmail();
        email.aType = "Private";
        email.eEmailAddress = "jdoe@yourcompany.com";
        addr.eEmailDetails.eEmail.add(email);

        email = new ClsEmail();
        email.aType = "Private";
        email.eEmailAddress = "josephdoe@mycompany.com";
        addr.eEmailDetails.eEmail.add(email);

        email = new ClsEmail();
        email.aType = "Private";
        email.eEmailAddress = "josephdoe@mycompany.com";
        addr.eEmailDetails.eEmail.add(email);

        addr.ePhoneDetails = new ClsPhoneDetails();
        addr.ePhoneDetails.ePhone = new java.util.ArrayList();

        ClsPhone ePhone = new ClsPhone();
        ePhone.aType = "Work";
        ePhone.ePhoneNumber = "555.6789";
        addr.ePhoneDetails.ePhone.add(ePhone);

        manager.setFileName("AddressOutput.xml");
        manager.insert(addr);
    }
}

NEXT     PREVIOUS  TABLE OF CONTENTS