Welcome to JaxMe!

SourceForge.net Logo
JaxMe

- A Framework for Java/XML binding based on SAX2 -

The XmlDbManager - Access to an XML database through the xml:db API

The xml:db API is a specification on the use of an XML database from within Java. This is comparable to the JDBC API, which allows you the use of an SQL database. Unfortunately xml:db is very basic, compared to JDBC, but it allows the most important tasks:

  • Insert a document into the database (the document needs a preassigned ID)
  • Update an existing document or
  • Delete it from the database
  • Read documents from the database

The current implementation assumes, that a fixed attribute holds the documents ID. For example, this might be an attribute called "id". In the case of a Tamino database, it might be "ino:id".

Reading data from an XML database

First of all, any application accessing a database needs some basic configuration. In the case of xml:db, we need at least to specify a so-called driver and a collection. This is done in an XML file:

      <?xml version="1.0" encoding="UTF-8" ?>
      <JMManagerConfiguration
          xmlns="http://jaxme.ispsoft.de/namespaces/JMManagerConfiguration">
        <Defaults>
          <XmlDbManager>
            <Driver>org.exist.xmldb.DatabaseImpl</Driver>
            <URI>xmldb:exist://localhost:8081</URI>
            <!-- This is for the eXist database, in the case of
                    Xindice you would use, for example, the driver
                      org.apache.xindice.client.xmldb.DatabaseImpl
                    and the URI
                      xmldb:xindice:///db/
             -->
            <IdAttribute>ID</IDAttribute>
                <!-- By default this would be "id" -->
          </XmlDbManager>
        </Defaults>
        <Configuration
            localName="Session"
            namespaceURI="http://jaxme.ispsoft.de/namespaces/examples/Session">
          <ElementClass>de.ispsoft.jaxme.examples.session.ClsSession</ElementClass>
          <HandlerClass>de.ispsoft.jaxme.examples.session.ClsSessionHandler</HandlerClass>
          <ManagerClass>de.ispsoft.jaxme.XmlDbManager</ManagerClass>
        </Configuration>
      </JMManagerConfiguration>
    

Things you should note here:

  1. The configuration works much the same as the configuration of the JDBC access. See RDBMS.html for details on the JDBC configuration.
  2. Unlike the JDBC case, there is a generic manager for all document types (ManagerClass). Of course you still have the ability to derive your own subclass of XmlDbManager and configure that.

  3. As in the JDBC manager case, you do not need to use this XML file. You might as well create your own instance of XmlDbManager, configure that with setDriver(), setURI(), setJmAnyElementClassName() and setJmContentHandlerClassName() and be happy with it. This is more straightforward, but you pay in the long term, because finally you will find yourself implementing a similar configuration scheme. (Experience shows :-)
  4. The values given in the Defaults section can be overwritten in the document type specific section Configuration.

The recommended behaviour is naming the file de/ispsoft/jaxme/JMManagerFactoryImpl.xml and putting that file somewhere into your classpath. For example, the following program would write out all current HTTP sessions much like the "AddressPrinter":

import de.ispsoft.jaxme.examples.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionPrinter {
  public static void main(String[] args) throws Exception {
    System.setProperty("de.ispsoft.jaxme.JMManagerFactory.uri",
                       "resource:com/mycompany/Configuration.xml");
    JMManagerFactory factory = new JMFactory.getJMManagerFactory();
    JMManager manager = factory.getJMManager(ClsSession.NAMESPACE_URI,
                                             ClsSession.LOCAL_NAME);
    String query = "Session[LASTACTION + EXPIRETIME > NOW()]";
    for (java.util.Iterator iter = manager.select(query);
         iter.hasNext();  ) {
      ClsSession session = (ClsSession) iter.next();
      System.out.println(session.toXML());
    }
  }
}
    

You could also read the configuration from a file or URL by setting the following properties:

       de.ispsoft.jaxme.JMManagerFactory=de.ispsoft.jaxme.JMManagerFactoryImpl
       de.ispsoft.jaxme.JMManagerFactory.uri=file://c:\temp\Configuration.xml
or
       de.ispsoft.jaxme.JMManagerFactory=de.ispsoft.jaxme.JMManagerFactoryImpl
       de.ispsoft.jaxme.JMManagerFactory.uri=http://www..mycompany.com/Configuration.xml
And you could, of course, specify the property value from the command line and not within the program.For details, see the JMFactory documentation.

Writing data to an XML database

We'll now want to create a new HTTP session. It uses the same property file as before:

import de.ispsoft.jaxme.examples.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionAdd {
  public static void main(String[] args) throws Exception {
    JMManagerFactory factory = new JMFactory.getJMManagerFactory();
    JMManager manager = factory.getJMManager(ClsSession.NAMESPACE_URI,
                                             ClsSession.LOCAL_NAME);
    ClsSession session = (ClsSession) manager.create();
    session.eID = new Integer(126776);
    session.eIPADDRESS = "134.23.1.7";
    session.eLOGINTIME = new java.sql.Timestamp(System.currentTimeMillis());
    session.eLASTACTION = session.eLOGINTIME;
    session.eEXPIRETIME = new Short((short) 15*60);
    session.eCOOKIE = "jH63fGdx";
    session.eLANGUAGEID = new Integer(3);
    manager.insert(session);
    System.out.println("Document with ID " + session.eID + " was created.");
  }
    

A similar example, the update of a row:

import de.ispsoft.jaxme.examples.session.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionUpdate {
  public static void main(String[] args) throws Exception {
    JMManagerFactory factory = new JMFactory.getJMManagerFactory();
    JMManager manager = factory.getJMManager(ClsSession.NAMESPACE_URI,
                                             ClsSession.LOCAL_NAME);
    java.util.Iterator iter = manager.select("myprefix:Session[@ino:id=37]");
    if (iter.hasNext()) {
      ClsSession session = (ClsSession) iter.next();
      session.eLASTACTION = new java.sql.Timestamp(System.currentTimeMillis());
      manager.update(session);
    }
  }
}
   

And finally, as you have probably guessed, an example for deleting a row:

import de.ispsoft.jaxme.examples.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionDelete {
  public static void main(String[] args) throws Exception {
    JMManagerFactory factory = new JMFactory.getJMManagerFactory();
    JMManager manager = factory.getJMManager(ClsSession.NAMESPACE_URI,
                                             ClsSession.LOCAL_NAME);
    java.util.Iterator iter = manager.select("myprefix:Session[@ino:id=37]");
    if (iter.hasNext()) {
      ClsSession session = (ClsSession) iter.next();
      manager.delete(session);
    }
  }
}
   

Noticed that these examples looked quite the same as their JDBC counterparts did? Thats because the XmlDbManager is just another manager.