Welcome to JaxMe!

SourceForge.net Logo
JaxMe

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

The Tamino Manager - Access to a Tamino database

The InoManager, which is responsible for accessing the Tamino database, can

  • Insert a document into the database
  • Update an existing document or
  • Delete it from the database
  • Read documents from the database
Currently it cannot
  • Authenticate itself with a user name and password (mainly because Java comes with no BASE64 implementation, we need to provide our own)
  • Use transactions, isolation levels and locking modes; this requires an API which is beyond the scope of the JMManager. Technically there is no problem, so stay tuned.
  • Use the official Tamino4J API internally; the current implementation uses a SAX2 handler. Of course, the JaxMe implementation is faster and has a much smaller memory foot print: It sits on SAX2 directly. :-)

Deleting a document requires a document ID. The default implementation uses the ino:id. This behaviour can hardly be recommended, but there is no other possible key for a default implementation. Thus it is suggested that you use your own key (for example an attribute myid, which all documents must have) and derive some subclass from the InoManager.

Reading data from a Tamino database

First of all, like any application using Tamino, we have to specify some values, in particular the Tamino database URL (including the collection!). This is done in an XML file:

      <?xml version="1.0" encoding="UTF-8" ?>
      <JMManagerConfiguration
          xmlns="http://jaxme.ispsoft.de/namespaces/JMManagerConfiguration">
        <Defaults>
          <InoManager>
            <DbURL>http://127.0.0.1/tamino/test</DbURL>
            <User>sa</User>
            <Password/>
            <ManagerClass>de.ispsoft.jaxme.tamino.InoManager</ManagerClass>
          </InoManager>
        </Defaults>
        <Configuration
            localName="Session"
            namespaceURI="http://jaxme.ispsoft.de/namespaces/examples/Session">
          <ElementClass>com.mycompany.session.ClsSession</ElementClass>
          <HandlerClass>com.mycompany.session.ClsSessionHandler</HandlerClass>
        </Configuration>
      </JMManagerConfiguration>
    

Things you should note here:

  1. The configuration works much the same than the configuration of the JDBC access.
  2. Unlike the JDBC case, there is a generic manager for all document types. In particular, you don't need the XsdJdbcSchemaReader or the JdbcJavaSourceWriter. The standard XsdSchemaReader and the JavaSourceWriter will do.

    Of course you still have the ability to derive your own subclass of InoManager and configure that. And, as the JDBC reader and writer are upwards compatible, you can still use these, if you like.
  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 InoManager, configure that with setDbURL(), 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.

The recommended behaviour is putting the XML file somewhere into your classpath. Assuming, that your configuration file is in com/mycompany/Configuration.xml, you could write the following program, that writes all current HTTP sessions to System.out, much like the "AddressPrinter":

import com.mycompany.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 = "myprefix:Session[LASTACTION + EXPIRETIME > " +
      JMAnyElement.formatDate(new java.util.Date());
    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 changing the property value to

      file://c:\temp\Configuration.xml
    
or
      http://configurations.company.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.

Tamino and SAX2

The current Tamino version (3.1.1.4, as of this writing) is not namespace aware. That means, you either have not to use namespaces at all (the exception being the ino: prefix, of course) or you have to make sure, that the same prefixes are used for any single instance of a given document type, that is stored in the database.

For example, did you notice that there already was a problem in the previous example? We formulated a query for documents of type Session in the namespace http://jaxme.ispsoft.de/namespaces/examples/Session. But the query was asking for documents of type myprefix:Session, assuming silently that this prefix is used for the namespace.

The former works without any additional caveats, but the latter requires some additional support. The best way is specifying a list of namespace prefixes and URI's in the manager configuration. Whenever the manager needs to convert a namespace into a prefix, it uses the list. Let's take a look at an example:

      <?xml version="1.0" encoding="UTF-8" ?>
      <JMManagerConfiguration
          xmlns="http://jaxme.ispsoft.de/namespaces/JMManagerConfiguration">
        <Defaults>
          <InoManager>
            <DbURL>http://127.0.0.1/tamino/test</DbURL>
            <User>sa</User>
            <Password/>
            <ManagerClass>de.ispsoft.jaxme.tamino.InoManager</ManagerClass>
            <Namespaces>
              <Namespace prefix="s"
                uri="http://jaxme.ispsoft.de/namespaces/examples/Session"/>
              <Namespace prefix="" uri=""/>
            </Namespaces>
          </InoManager>
        </Defaults>
        <Configuration
            localName="Session"
            namespaceURI="http://jaxme.ispsoft.de/namespaces/examples/Session">
          <ElementClass>com.mycompany.session.ClsSession</ElementClass>
          <HandlerClass>com.mycompany.session.ClsSessionHandler</HandlerClass>
        </Configuration>
      </JMManagerConfiguration>
    

With one exception, this is the same configuration than above. The exception is a list of namespaces in the defaults section. You may use a namespace list in both the default and the document type specific section. If both lists are present, they will be concatenated unless the node Namespaces has an attribute reset="true". For example:

      <JMManagerConfiguration
          xmlns="http://jaxme.ispsoft.de/namespaces/JMManagerConfiguration">
        <Defaults>
          <InoManager>
            <Namespaces>
              <Namespace prefix="x" uri="uriOfX"/>
            </Namespaces>
          </InoManager>
        </Defaults>
        <Configuration localName="a" namespaceURI="uriOfA"/>
        <Configuration localName="b" namespaceURI="uriOfB">
          <Namespaces>
            <Namespace prefix="y" uri="uriOfY"/>
          </Namespaces>
        </Configuration>
        <Configuration localName="c" namespaceURI="uriOfC">
          <Namespaces reset="true"s>
            <Namespace prefix="z" uri="uriOfZ"/>
          </Namespaces>
        </Configuration>
      </JMManagerConfiguration>
    

This example configures three different namespace lists for a, b and c: The first element, a has the prefix x configured, which it inherits from the defaults section. The second element, b has an additional prefix y, but the third element, c, has only the prefix z, because it resets the default prefix list.

Writing data to a Tamino database

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

import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionAdd {
  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);
    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);
    String id = session.getAttribute(InoResponseHandler.INO_RESPONSE2_URI,
                                     "id");
    System.out.println("Document with ID " + id + " was created.");
  }
    

A similar example, the update of a row:

import com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionUpdate {
  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);
    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 com.mycompany.session.ClsSession;
import de.ispsoft.jaxme.*;

public class SessionDelete {
  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);
    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 Tamino manager is just another manager.