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:
The class XMLGreeting
shown below accomplishes the
following tasks that are typical for an application accessing data stored in a
Tamino database:
establish a connection to the existing Tamino database
mydb
obtain an access method to handle XML data using the Document Object Model (DOM)
insert an XML document into the database
query the database to retrieve the document inserted previously
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:
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 );
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() );
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() );
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!" );
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.
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.
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:
establish a connection to the existing Tamino database
mydb
obtain an Accessor
instance
insert a new document:
<Greeting></Greeting>
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
leave the local transaction mode
query the updated document
delete document
close the connection
We use the same constants as before.
Establish a Connection
This is done the same way as in the previous example.
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() );
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() );
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.
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();
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;
Update the Database
Update the current document after changing some text.
// Invoke the update response = accessor.update( xmlObject ); System.out.println( "Update succeeded!" );
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; }
Leave the Local Transaction Mode
You must leave the local transaction mode by explicitly switching to
the auto commit mode:
connection.useAutoCommitMode();
Delete the Document
As final operation we delete the second document:
TResponse response = accessor.delete( query ); System.out.println( "Deleted the document!" );
Close the Connection
This is done the same way as before.
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.
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" );
Establish a Connection
This is already described in the previous examples.
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" ) );
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() );
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!" );
Close the Connection
This is done the same way as in the previous examples.
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
In this example the same tasks are performed as in
ProcessXMLGreeting
, except that non-XML data is
used.
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!