Say Hello!

Before discussing the details of the API let us take a look at a very simple example that does nothing else than insert a friendly greeting into an existing database. The section describing the Tamino API package explains where you will find the example files used below; please refer also to the section "How To Create a Tamino Database" in the Tamino documentation. The following examples show you how to perform the most common operations on a database:

  • establish a connection to a Tamino database

  • obtain an access method to handle either XML or non-XML data

  • perform common operations such as insert, update, delete, as well as querying a database

  • use a local transaction mode

  • close a database connection

Four examples are provided that demonstrate these tasks:


XMLGreeting: Inserting an XML Document

The class XMLGreeting shown below accomplishes the following tasks that are typical for an application accessing data stored in a Tamino database:

  1. establish a connection to the existing Tamino database mydb

  2. obtain an access method to handle XML data using the Document Object Model (DOM)

  3. insert an XML document into the database

  4. query the database to retrieve the document inserted previously

  5. close a database connection

It is assumed that a database called mydb has already been created and is running. We use two string constants that hold the URI of the database and the XML instance to be inserted:

  // URI of the Tamino database, please edit accordingly
  public final static String DATABASE_URI = "http://localhost/tamino/mydb";

  // XML document to be written to the connected database
  public final static String XML = "<Greeting by='XMLGreetingApplication'>Hello World</Greeting>";

Please note that Tamino considers this as a valid XML document. Strictly speaking, this document satisfies all conditions of an XML document except that the XML declaration (<?xml version="1.0"?>) is missing.

We define xmlObject as an instance of TXMLObject. For representing the document structure, we choose DOM as one of several available object models. So xmlObject holds a DOM representation of that greeting document:

  // Put the XML content into a StringReader
  StringReader stringReader = new StringReader( XML );

  // Instantiate an empty TXMLObject instance using the DOM object model
  TXMLObject xmlObject = TXMLObject.newInstance( TDOMObjectModel.getInstance() );

  // Establish the DOM representation by reading the contents from the character input stream
  xmlObject.readFrom( stringReader );

Now we can go through the typical processing steps of a Tamino application:

  1. Establish a Connection
    Use a factory method of TConnectionFactory to instantiate a TConnection. A TConnection object effectively represents a Tamino database session. You can use the newConnection method to establish a connection with a database that is specified by DATABASE_URI:

      // Establish the Tamino connection
      TConnection connection = TConnectionFactory.getInstance().newConnection( DATABASE_URI );
  2. Obtain an Accessor
    With the help of an Accessor object you can access the data that is to be read from or written to a database. Here we instantiate a new TXMLObjectAccessor object that is bound to the database connection established in the previous step. There are two parameters specifying the type of access: the first is the collection into which data is to be stored (TAccessLocation); here it is the default collection ino:etc that is always present in a Tamino database. The second is the object model, which is DOM in this example:

      // Obtain a TXMLObjectAccessor with a DOM object model
      TXMLObjectAccessor xmlObjectAccessor = connection.newXMLObjectAccessor(
                                            TAccessLocation.newInstance( "ino:etc" ),
                                            TDOMObjectModel.getInstance() );
  3. Insert the XML Document
    The xmlObjectAccessor provides methods for performing queries and manipulating XML data such as inserting our TXMLObject instance into the default collection ino:etc. On insertion the XML object is assigned a unique ID (ino:id) that you can get by applying the object's method getId.

      // Invoke the insert operation
      xmlObjectAccessor.insert( xmlObject );
    
      // Show the ino:id of the document just inserted
      System.out.println( "Insert succeeded, ino:id=" + xmlObject.getId() );
  4. Query the Database
    The query method of an xmlObjectAccessor expects as arguments a non-empty X-Query expression. We construct a query expression that retrieves the XML object stored with the previously assigned ino:id (which is 1 for the first item stored in a database): /Greeting[@ino:id="1"]. Here Greeting is the name of the document's doctype that is returned by the method getDoctype(). You can access the result set returned by Tamino with an instance of TResponse. The getFirstXMLObject method retrieves the first element of the result set

      // Prepare to read the instance
      TQuery query = TQuery.newInstance( xmlObject.getDoctype() + "[@ino:id=" + xmlObject.getId() + "]" );
    
          // Invoke the query operation
          TResponse response = xmlObjectAccessor.query( query );
          if ( response.hasFirstXMLObject() ) {
            StringWriter stringWriter = new StringWriter();
            response.getFirstXMLObject().writeTo( stringWriter );
            System.out.println( "Retrieved following instance:" + stringWriter );
          }
          else
            System.out.println( "No instance found!" );
  5. Close the Connection
    The TConnection instance is also responsible for closing an open database connection. You can close the connection to the database mydb by using:

      connection.close();

The example file contains additional code for error handling which is not relevant for the discussion of the API basics.

Running the Example

You need to include the .jar files TaminoAPI4J.jar, JavaTaminoAPIExamples.jar, xercesImpl.jar, xmlParserAPIs.jar, jdom.jar and log4j.jar in your system's class path, all of which are included in the distribution of the Tamino API (see the component profile). Then you can run the Java interpreter:

java com.softwareag.tamino.db.api.examples.greeting.XMLGreeting
Insert succeeded, ino:id=1
Retrieved following instance:<Greeting by="XMLGreetingApplication" ino:id="1">Hello World</Greeting>

Note:
Using JavaTaminoAPIExamples.jar only works if you have created a database called "mydb" on your local host. Otherwise you have to change the constant DATABASE_URI and recompile the code.

ProcessXMLGreeting: Operating in Local Transaction Mode

We extend and modify the example above and demonstrate how to operate in a local transaction mode. In addition to inserting data and querying the database, updating and deleting data are also demonstrated. We also use a different object model:

  1. establish a connection to the existing Tamino database mydb

  2. obtain an Accessor instance

  3. insert a new document: <Greeting></Greeting>

  4. The following tasks are performed in a local transaction mode:

    • retrieve first stored object

    • update objects in the database

    • commit the transaction if successful otherwise rollback

  5. leave the local transaction mode

  6. query the updated document

  7. delete document

  8. close the connection

We use the same constants as before.

  1. Establish a Connection
    This is done the same way as in the previous example.

  2. Obtain a JDOM Accessor
    The Accessor used here is instantiated in the same way as before, but in contrast to the first example it uses the JDOM object model.

      // Obtain the concrete TXMLObjectAccessor with an underyling JDOM object model
      accessor = connection.newXMLObjectAccessor( TAccessLocation.newInstance( collection ) ,
                                                  TJDOMObjectModel.getInstance() );
  3. Insert the XML Document
    Here we make use of TResponse. An object of that class is instantiated and stores the response from Tamino. The data will be inserted by calling the accessor's insert method.

      // TResponse represents an access response from Tamino.
      TResponse response = null;
    
      // Invoke the insert operation and obtain the response.
      response = accessor.insert( xmlObject );
    
      // Show the collection, doctype and id
      System.out.println( "Insert succeeded, ino:collection:" + xmlObject.getCollection() +
                          ", ino:doctype:" + xmlObject.getDoctype() + ", ino:id:" + xmlObject.getId() );
  4. Operate in a Transaction Block
    We use a transaction block to query and update the database. Normally, every operation is running inside its own transaction block, and with the end of the operation the implicit transaction ends (auto-commit). Here we enter a local transaction mode, perform a query and an update operation in one transaction, which is finished by either a commit or rollback.

    1. Open the Transaction Block
      For entering the local transaction mode, we instantiate TLocalTransaction and call the useLocalTransactionMode method to bind it to the currently open connection.

        TLocalTransaction localTransaction = null;
        // Switch to the local transaction mode
        localTransaction = connection.useLocalTransactionMode();
    2. Query the Database and Retrieve First Object
      Again we use a TResponse object. You can retrieve the first stored object by calling getFirstXMLObject.

        // Invoke the query to obtain the document and to lock it
        TResponse response = accessor.query( xpath );
      
        // Obtain the TXMLObject from the response
        TXMLObject xmlObject = response.getFirstXMLObject();
        if ( xmlObject == null )
           return;
    3. Update the Database
      Update the current document after changing some text.

        // Invoke the update
          response = accessor.update( xmlObject );
          System.out.println( "Update succeeded!" );
    4. Finish Transaction
      If every part of the transaction is successful, then commit the transaction:

        localTransaction.commit();

      If a TAcessorException is thrown, then a rollback is performed in the catch branch:

        catch (TAccessorException accessorException)  {
            showAccessFailure( accessorException );
            localTransaction.rollback();
            throw accessorException;
          }
  5. Leave the Local Transaction Mode
    You must leave the local transaction mode by explicitly switching to the auto commit mode:

      connection.useAutoCommitMode();
  6. Delete the Document
    As final operation we delete the second document:

      TResponse response = accessor.delete( query );
      System.out.println( "Deleted the document!" );
    
  7. Close the Connection
    This is done the same way as before.

Running the Example

You need to include the .jar files TaminoAPI4J.jar, JavaTaminoAPIExamples.jar, xercesImpl.jar, xmlParserAPIs.jar, jdom.jar and log4j.jar in your system's class path, all of which are included in the distribution of the Tamino API (see the component profile). Then you can run the Java interpreter:

java com.softwareag.tamino.db.api.examples.greeting.ProcessXMLGreeting
Insert succeeded, ino:collection:ino:etc, ino:doctype:Greeting, ino:id:2
Update succeeded!
Queried document:<Greeting ino:id="2" by="ProcessGreetingApplication">Hello World, updated :-)</Greeting>
Deleted the document!

Note:
As in the previous example, using JavaTaminoAPIExamples.jar only works if you have created a database called "mydb" on your local host. Otherwise you have to change the source code and recompile it.

NonXMLGreeting: Inserting Non-XML Data

This example is nearly the same as the first example, but this time we want to insert a non-XML document. In the Tamino API a clear distinction is made between handling of XML documents and non-XML documents. Since the application logic is the same as before, we concentrate on the differences with respect to non-XML documents.

Again, a string constant will hold the document to be inserted into the database:

  // Non-XML document to be written to the connected database
  public final static String NON_XML = "Greeting by='XMLGreetingApplication':Hello World";

Please note that this document is a non-XML document, although it pretty much looks like the document used in the previous examples. It lacks any XML elements and thus it neither has a necessary root element nor can it be well-formed. It is a non-XML document used for an image or video file, or a text file that does not comply with the XML standard.

We define nonXMLObject as an instance of TNonXMLObject. In non-XML data there is no structural representation for which an object model could be used. The second argument is the name of the collection. Since it is null, the default collection ino:etc will be used. The next argument is the doctype name ino:nonXML, followed by the document name NonXMLGreeting. The last argument is the content type text/plain.

  // Put the XML content into a StringReader
  StringReader stringReader = new StringReader( NON_XML );

  // Instantiate an empty TNonXMLObject instance
  TNonXMLObject nonXMLObject = TNonXMLObject.newInstance( stringReader ,
                                null ,
                                "ino:nonXML" ,
                                "NonXMLGreeting" ,
                                "text/plain" );
  1. Establish a Connection
    This is already described in the previous examples.

  2. Obtain an Accessor
    We have to instantiate an object from TNonXMLObjectAccessor. As the data is non-XML an object model is not needed:

      // Obtain a TNonXMLObjectAccessor
      TNonXMLObjectAccessor nonXMLObjectAccessor = connection.newNonXMLObjectAccessor(
                                                    TAccessLocation.newInstance( "ino:etc" ) );
    
  3. Insert the Non-XML Document
    There is a corresponding set of methods available for TNonXMLObjectAccessor instances so that inserting the non-XML document is analogous to inserting an XML document: it is also assigned a unique ID (ino:id) that you can retrieve after insertion:

      // Insert document and display its ino:id afterwards
      nonXMLObjectAccessor.insert( nonXMLObject );
      System.out.println( "Insert succeeded, ino:id=" + nonXMLObject.getId() );
  4. Query the Database
    Analogous to the XMLGreeting example. However, we now use a ByteArrayOutputStream instead of a StringWriter:

      // Instantiate TQuery 
      TQuery query = TQuery.newInstance( nonXMLObject.getDoctype() +
                                          "[@ino:id=" + nonXMLObject.getId() + "]" );
      // Invoke the query operation
      TResponse response = nonXMLObjectAccessor.query( query );
      if ( response.hasFirstNonXMLObject() ) {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        response.getFirstNonXMLObject().writeTo( outputStream );
        System.out.println( "Retrieved following instance:" + outputStream );
      }
      else
        System.out.println( "No instance found!" );
  5. Close the Connection
    This is done the same way as in the previous examples.

Running the Example

You need to include the .jar files TaminoAPI4J.jar, JavaTaminoAPIExamples.jar, xercesImpl.jar, xmlParserAPIs.jar, jdom.jar and log4j.jar in your system's class path, all of which are included in the distribution of the Tamino API (see the component profile). Then you can run the Java interpreter:

java com.softwareag.tamino.db.api.examples.greeting.NonXMLGreeting
Insert succeeded, ino:id=1
Retrieved following instance:Greeting by='XMLGreetingApplication':Hello World

ProcessNonXMLGreeting: Operating in Local Transaction Mode with Non-XML Data

In this example the same tasks are performed as in ProcessXMLGreeting, except that non-XML data is used.

Running the Example

You need to include the same .jar files as before. Then you can run the Java interpreter:

java com.softwareag.tamino.db.api.examples.greeting.ProcessNonXMLGreeting
Insert succeeded, ino:collection:ino:etc, ino:doctype:ino:nonXML, ino:id:2
Update succeeded!
Queried document, Content:Greeting by='XMLGreetingApplication':Hello World
Deleted the document!