9. Java Developers Guide¶
9.1. Preface¶
9.1.1. Overview¶
This guide provides information about how to use the rasdaman database management system. The booklet explains usage of rasj, the rasdaman Java API.
Follow the instructions in this guide as you develop your application which makes use of rasdaman services. Explanations detail how, from within a Java program, to create databases, collections, and instances; how to retrieve from databases; how to manipulate and delete instances within databases; how to influence physical storage parameters; how to do transaction handling and other administrative tasks.
9.1.2. Audience¶
The information in this manual is intended for application developers.
9.1.3. Rasdaman Documentation Set¶
This manual should be read in conjunction with the complete rasdaman documentation set which this guide is part of. The documentation set in its completeness covers all important information needed to work with the rasdaman system, such as programming and query access to databases, guidance to utilities such as raswct, release notes, and additional information on the rasdaman wiki.
The rasdaman Documentation Set consists of the following documents:
Installation and Administration Guide
Query Language Guide
C++ Developer’s Guide
Java Developer’s Guide
raswct Developer’s Guide
the rasdaman wiki, accessible at www.rasdaman.org
9.2. Introduction¶
See the corresponding Introduction Section in the rasdaman Query Language Guide.
9.3. Terminology¶
See the corresponding Terminology Section in the rasdaman Query Language Guide.
9.4. Application Examples¶
9.4.1. Overview¶
This section contains an example of using the rasdaman Java API. The intention is, for the advanced programmer, to quickly get an overview on the programming style to be observed.
The source code can be found (slightly extended) in subdirectory
$RMANHOME/share/rasdaman/examples/java
of the rasdaman distribution directory.
For details on the operational semantics of the rasdaman data model the reader is strongly encouraged to study the rasdaman Query Language Guide.
9.4.2. Application Program Example Code¶
import rasj.*;
import rasj.odmg.*;
import org.odmg.*;
import java.util.*;
/** Example Java program for computing the avg cell value
* for each n-D 8-bit grey image in a given collection.
* set the server name with -server, the database name with -database,
* the collection name with -collection,
* the port number with -port, the user login with -user,
* the password with -passwd
*/
public class AvgCell {
public static void main(String[] args) {
String server = "localhost";
String base = "RASBASE";
String coll = "mr";
String port = "7001";
String user = "rasguest";
String passwd = "rasguest";
double sum;
for (int i = args.length - 1; i >= 0; i--) {
//System.out.println(args[i]);
if (args[i].equals("-server")) {
server = args[i + 1];
}
if (args[i].equals("-database")) {
base = args[i + 1];
}
if (args[i].equals("-collection")) {
coll = args[i + 1];
}
if (args[i].equals("-port")) {
port = args[i + 1];
}
if (args[i].equals("-user")) {
user = args[i + 1];
}
if (args[i].equals("-passwd")) {
passwd = args[i + 1];
}
}
//System.out.println(server+base+coll+port+user+passwd);
DBag resultBag = null;
RasGMArray result = null;
Transaction myTa = null;
Database myDb = null;
OQLQuery myQu = null;
try {
Implementation myApp = new RasImplementation(
"http://" + server + ":" + port);
((RasImplementation)myApp).setUserIdentification(user, passwd);
myDb = myApp.newDatabase();
System.out.println("Opening database ...");
myDb.open(base, Database.OPEN_READ_ONLY);
System.out.println("Starting transaction ...");
myTa = myApp.newTransaction();
myTa.begin();
System.out.println("Retrieving MDDs ...");
myQu = myApp.newOQLQuery();
myQu.create("select img from " + coll + " as img");
resultBag = (DBag)myQu.execute();
if (resultBag != null) {
Iterator iter = resultBag.iterator();
while (iter.hasNext()) {
result = (RasGMArray)iter.next();
System.out.println(result);
if (result.getTypeLength() != 1) {
System.out.println("skipping image because"
+ " of non-int cell type");
} else {
byte[] pixelfield = result.getArray();
sum = 0.0;
long size = result.getArraySize();
for (int i = 0; i < size; i++) {
sum += pixelfield[i];
}
System.out.println("Avarage over " + size + " pixels is "
+ ((sum / size) + 128));
}
}
System.out.println("All results");
}
System.out.println("Committing transaction ...");
myTa.commit();
System.out.println("Closing database ...");
myDb.close();
} catch (org.odmg.ODMGException e) {
System.out.println("An exception has occurred: " + e.getMessage());
System.out.println("Try to abort the transaction ...");
if (myTa != null) {
myTa.abort();
}
try {
System.out.println("Try to close the database ...");
if (myDb != null) {
myDb.close();
}
} catch (org.odmg.ODMGException exp) {
System.err.println("Could not close the database: "
+ exp.getMessage());
}
}
System.out.println("Done.");
}
}
Note
This sample program makes use of the mr
collection provided with the
rasdaman distribution package. See the rasdaman Installation and
Administration Guide to learn on how to create this collection as part
of the demonstration database.
9.5. rasj¶
9.5.1. Overview¶
The rasj package contains the API for Java-based access to the rasdaman database system. It relies on the ODMG standard which it implements to the extent that is necessary for raster data management.
The overall rasj package is subdivided into two packages, rasj
and
org.odmg
. The org.odmg
sub-package (see ODMG) implements the
general ODMG specifications while the rasj
sub-package implements
rasdaman specific features.
9.5.2. Class Hierarchy¶
Note
All class hierarchies are generated from the rasj javadoc,
which can be built in the java/
directory with
mvn javadoc:javadoc
This generates a javadoc
folder in the build directory
(build/java/target/site/apidocs/rasj
). Then, a commandline tool named w3m
is used to dump the tree structure in HTML format of a package to text in console, example:
w3m -dump build/java/target/site/apidocs/rasj/package-tree.html
The rasj
class hierarchy has the following structure.
* java.lang.Object
* rasj.RasFastScale (implements rasj.global.RasGlobalDefs)
* rasj.RasImplementation (implements org.odmg.Implementation)
* rasj.RasMInterval
* rasj.odmg.RasObject (implements rasj.global.RasGlobalDefs)
* rasj.RasGMArray (implements rasj.global.RasGlobalDefs)
* rasj.RasMArrayByte
* rasj.RasMArrayDouble
* rasj.RasMArrayFloat
* rasj.RasMArrayInteger
* rasj.RasMArrayLong
* rasj.RasMArrayShort
* rasj.RasPoint
* rasj.RasSInterval
* rasj.RasStorageLayout
* rasj.RasStructure
* rasj.RasType
* rasj.RasBaseType
* rasj.RasPrimitiveType (implements rasj.global.RasGlobalDefs)
* rasj.RasStructureType
* rasj.RasCollectionType
* rasj.RasMArrayType
* rasj.RasMIntervalType
* rasj.RasOIDType
* rasj.RasPointType
* rasj.RasSIntervalType
* java.lang.Throwable (implements java.io.Serializable)
* java.lang.Exception
* org.odmg.ODMGException
* org.odmg.QueryException
* org.odmg.QueryInvalidException
* rasj.RasQueryExecutionFailedException
* rasj.RasException
* rasj.RasDimensionMismatchException
* rasj.RasIndexOutOfBoundsException
* rasj.RasResultIsNoCellException
* rasj.RasResultIsNoIntervalException
* rasj.RasStreamInputOverflowException
* rasj.RasTypeInvalidException
* java.lang.RuntimeException
* org.odmg.ODMGRuntimeException
* rasj.RasConnectionFailedException
* rasj.RasRuntimeException
* rasj.RasClientInternalException
* rasj.RasIllegalULongValueException
* rasj.RasIllegalUShortValueException
* rasj.RasInvalidNameException
* rasj.RasTypeNotSupportedException
* rasj.RasTypeUnknownException
9.5.3. Interface Hierarchy¶
The complete rasj interface hierarchy has the following structure.
* org.odmg.Implementation
* rasj.RasImplementationInterface
9.6. ODMG¶
9.6.1. Overview¶
The ODMG classes implement classes defined in the ODMG standard providing functionality such as database open and close, transactions, querying, and unique identifiers, i.e., OIDs.
Don’t Use DArray
!
ODMG defines an interface DArray
which also is part of the ODMG
sub-package provided with the rasdaman distribution. These implement
only 1-D arrays; most important, however, DArray
is *not compatible*
with rasdaman arrays. Therefore, *do not use* class DArray
as a
rasdaman array, but use class RasGMArray
(and its subclasses) instead.
...But Do Use Dbag
!
Queries return multi-sets as results. A bag or multi-set contains an
arbitrary number of elements; like a set (and unlike a list), no
particular sequence is defined, and like a list (and unlike a set), the
same elements can occur multiply. The query result type, therefore, is
DBag
. See also Storage Layout.
9.6.2. Class Hierarchy¶
The complete org.odmg
class hierarchy has the following structure.
* java.lang.Object
* java.lang.Throwable (implements java.io.Serializable)
* java.lang.Exception
* org.odmg.ODMGException
* org.odmg.DatabaseNotFoundException
* org.odmg.DatabaseOpenException
* org.odmg.ObjectNameNotFoundException
* org.odmg.ObjectNameNotUniqueException
* org.odmg.QueryException
* org.odmg.QueryInvalidException
* org.odmg.QueryParameterCountInvalidException
* org.odmg.QueryParameterTypeInvalidException
* java.lang.RuntimeException
* org.odmg.ODMGRuntimeException
* org.odmg.ClassNotPersistenceCapableException
* org.odmg.DatabaseClosedException
* org.odmg.DatabaseIsReadOnlyException
* org.odmg.LockNotGrantedException
* org.odmg.NotImplementedException
* org.odmg.ObjectDeletedException
* org.odmg.ObjectNotPersistentException
* org.odmg.TransactionAbortedException
* org.odmg.TransactionInProgressException
* org.odmg.TransactionNotInProgressException
9.6.3. Interface Hierarchy¶
This is the org.odmg
interface hierarchy:
* org.odmg.Database
* org.odmg.Implementation
* java.lang.Iterable<T>
* java.util.Collection<E>
* org.odmg.DCollection
* org.odmg.DArray (also extends java.util.List<E>)
* org.odmg.DBag
* org.odmg.DList (also extends java.util.List<E>)
* org.odmg.DSet (also extends java.util.Set<E>)
* java.util.List<E>
* org.odmg.DArray (also extends org.odmg.DCollection)
* org.odmg.DList (also extends org.odmg.DCollection)
* java.util.Set<E>
* org.odmg.DSet (also extends org.odmg.DCollection)
* java.util.Map<K,V>
* org.odmg.DMap
* org.odmg.OQLQuery
* org.odmg.Transaction
9.6.4. How To Use¶
The following code piece demonstrates a typical retrieval situation: a database is opened with username and password, a transaction is started, and then a query is executed against that database.
Transaction myTa = null;
Database myDb = null;
OQLQuery myQu = null;
DBag resultSet = null;
RasGMArray result = null;
Implementation myApp = new RasImplementation("http://" + server + port );
((RasImplementation)myApp).setUserIdentification(user, passwd);
myDb = myApp.newDatabase();
myDb.open( database, Database.OPEN_READ_ONLY );
myTa = myApp.newTransaction();
myTa.begin();
myQu = myApp.newOQLQuery();
myQu.create( "select mr from mr" );
resultSet = (DBag) myQu.execute();
// ...result set processing...
myTa.commit();
myDb.close();
Database Login
The database name and the address of a running server manager must be indicated. Further optional parameters and their defaults are:
login (default:
"rasguest"
)password (default:
"rasguest"
)
Multiple ODMG Implementations
It is well possible to use several implementations - for example, from
different vendors - of the ODMG classes simultaneously. Like rasj, other
ODMG packages will provide an Implementation
class in their org.odmg
package. Instantiating one Implementation
for each package is the only
prerequisite to be done. The resulting code might look like the
following (incomplete) example fragment where two different
implementation classes are assumed, RasImplementation
and
Implementation2
; note that transactions for different implementations
are independent from each other.
Transaction myTa1 = null;
Database myDb1 = null;
Transaction myTa2 = null;
Database myDb2 = null;
Implementation rasApp1 = new RasImplementation( "http://" + server1 + ":" + port1 );
((RasImplementation)rasApp1).setUserIdentification(user, passwd);
myDb1 = myApp1.newDatabase();
myDb1.open( rasbase, Database.OPEN_READ_ONLY );
MyTa1 = myApp1.newTransaction();
myTa1.begin();
Implementation2 myApp2 = new Implementation2( "http://" + server2 + ":" + port2 );
((RasImplementation)myApp2).setUserIdentification(user, passwd);
myDb2 = myApp2.newDatabase();
myDb2.open( database2, Database.OPEN_READ_ONLY );
MyTa2 = myApp2.newTransaction();
myTa2.begin();
// ...now access both databases...
myTa1.commit();
myDb1.close();
myTa2.commit();
myDb2.close();
ODMG Functions Available
rasj does not implement ODMG fully (this would go beyond its purpose), rather it contains those functions necessary for rasdaman database access. When using the HTML hypertext documentation, clicking through the org.odmg package ultimately gets you to the rasdaman classes which implement the corresponding ODMG class. There, methods not available are marked as such.
Further Information
Details on how to process the query result can be found in Storage Layout. The example code makes use of the demonstration database whose set-up routines are part of the distribution package; find more on this topic in the rasdaman Installation and Administration Guide.
9.7. Points and Intervals¶
9.7.1. Overview¶
Point and interval handling is needed for indexing arrays, such as
indication of array boundaries. To this end, classes RasPoint
,
RasSInterval
, and RasMInterval
for n-dimensional points, 1-D
(“single-“) intervals, and n-dimensional (“multi-“) intervals resp. are
provided.
Value Ranges and Consistency Constraints
All points, 1-D and n-D intervals can span negative values as well. Furthermore, intervals can have any integer value as lower bound. This is in contrast to most programming languages where usually the lower bound is fixed to 0.
However, intervals obviously need to match some consistency criteria to
be valid. Foremostly, in a 1-D interval (class RasSInterval
) as well as
in an n-D interval (class RasMInterval
) the lower bound must not be
higher than the upper bound.
Further, operations between intervals of any type must yield a valid
interval again. Consider the union of two 1-D intervals s1
and s2
,
s1.unionWith( s2 )
Intervals s1
and s2
must be overlap or at least be adjacent, otherwise
the resulting interval would contain a hole (mathematically speaking, it
would not be simply connected). As such situations are not allowed for
intervals in rasdaman, corresponding exceptions will be thrown by rasj.
If nevertheless two intervals should be merged which are apart from each
other, then operation closureWith()
can be used. It will “fill” the gap
between the intervals so that a valid result interval comes out.
The HTML manual lists each possible situation. It is recommended to study this for getting an understanding of all valid and invalid interval combinations.
9.7.2. Class Hierarchy¶
* java.lang.Object
* rasj.RasPoint
* rasj.RasSInterval
* rasj.RasMInterval
Note
Class java.lang.Object
obviously has further subclasses, not just the
one shown here.
9.7.3. How To Use¶
Here are some sample code fragments showing usage of the point and interval classes:
RasPoint
// (1) point instantiation using string constructor:
RasPoint p1 = new RasPoint( "[ 3, 7 ]" );
// (2) point instantiation using numerical constructor:
RasPoint p2 = new RasPoint( 5, 0 );
// get point dimension:
int d = p2.dimension();
// test if points are equal:
boolean b = p1.equals( p2 );
RasSInterval
// create a 1-D intervals (100,200) and (-150,400), resp.:
RasSInterval s1 = new RasSInterval( 100, 200 );
RasSInterval s2 = new RasSInterval( "-150:400" );
// no "[" and "]" !
// get upper bound of interval:
long hiBound = s2.high();
// get lower bound of interval:
long loBound = s2.low();
// test if interval intersects with another interval
// (the return value shows the kind of intersection)
int j = s1.intersectsWith( s2 );
RasMInterval
// create new 2-D interval, set bounds to (-1,1) and (3,7):
RasMInterval m1 = new RasMInterval( "[ -1:1, 3:7 ]" );
// create a 4-D interval, leaving open array bounds for now:
RasMInterval m2 = new RasMInterval( 4 );
// get number of cells:
long noOfCells = m1.cellCount();
9.8. Multidimensional Arrays¶
9.8.1. Overview¶
Instances of RasGMArray
and its subclasses represent multidimensional
arrays. To handle arrays with different base types and geometries, the
“implements” relation of Java is used. With this approach, greyscale
images, RGB images etc. can all be treated as subclasses of the general
array class RasGMArray
.
Currently supported are types for integer arrays (e.g., grayscale images) of various cell size, as well as types for floating-point arrays with single and double precision. All of them allow arrays of any dimension and extent per dimension.
Class Hierarchy
* rasj.odmg.RasObject (implements rasj.global.RasGlobalDefs)
* rasj.RasGMArray (implements rasj.global.RasGlobalDefs)
* rasj.RasMArrayByte
* rasj.RasMArrayDouble
* rasj.RasMArrayFloat
* rasj.RasMArrayInteger
* rasj.RasMArrayLong
* rasj.RasMArrayShort
9.8.2. How To Use¶
A few code fragments will show appropriate usage of the array classes. To keep it brief and to the spot, we omit declarations and other standard steps; these can be looked up in the previous, complete coding examples.
Note: Current restriction
Queries can contain formal parameters, denoted by $1
, $2
, etc. (see
Query Language Guide for details). In the current rasj
implementation, only one MDD object can be bound per query (however,
it is possible to bind several scalar values). This limitation will be
overcome in future releases.
Example 1: compute summary data from array
The following code example retrieves all MDD objects from a sample collection and, fore each object, computes the average cell value. As a safeguard, averaging is carried out only in case of integer cells (i.e., greyscale pixels).
myQu = myApp.newOQLQuery();
myQu.create( "select mr from mr" );
DBag resultSet = (DBag) myQu.execute();
if (resultSet != null)
{
Iterator iter = resultSet.iterator();
while (iter.hasNext())
{
result = (RasGMArray) iter.next();
if(result.getTypeLength() != 1)
System.out.println("skipping image because of non-int cell type" );
else
{
byte[] pixelfield = result.getArray();
double sum = 0.0;
long size = result.getArraySize();
for(int i=0; i<size; i++)
sum += pixelfield[i];
System.out.println( "Average over " + size +
" pixels is " +
((sum/size)+128) );
}
}
}
Example 2: set up array object in main memory
The following code fragment instantiates a RasGMArray
object as a 2-D
greyscale image and fills it with values using the normal Java means:
// create 2-D MDD with cell length 1, i.e., type "byte":
RasGMArray myMDD = new RasGMArray(new RasMInterval( "[1:400,1:400]"), 1 );
// byte container for array data, matching in size:
byte[] mydata = new byte[160000];
// initialize array as all-black with two grey stripes:
for(int y=0; y<400; y++)
{
for(int x=0; x<400; x++)
{
if((x>99 && x<151) || (x>299 && x<351))
mydata[y*399+x]=100;
else
mydata[y*399+x]=0;
}
}
// now insert byte array into MDD object
// (sets only the pointer, no copying takes place!):
myMDD.setArray(mydata);
As for the last line containing the import of array data into the MDD
object, observe the following: There are specific get/set
functions for the various supported array types, e.g., getIntArray()
.
While the setArray()
and getArray()
methods always will work, they will
require data type conversion if the actual array cell type is not
“byte”. Therefore, it is most efficient to always use that operation
which respects the actual array data type.
The following code fragment instantiates a RasGMArray
object as a 2-D
greyscale image and fills it with values using the normal Java means:
Example 3: insert new array object into database
This example generates a new greyscale image collection named test in the database and inserts an image into this database collection.
Note that a new query object has to be generated for each query. It is not sufficient to just change the query string in the query object!
// set up query object for collection creation:
myQu.create( "create collection test GreySet" );
// set the object type name (used for server type checking):
myMDD.setObjectTypeName( "GreyImage" );
// finally, execute "create collection" statement:
myQu.execute();
// now create the insert statement:
myQu.create( "insert into test values $1" );
// let the server generate a new OID for the object to be
// inserted, and remember this OID locally:
myNewOID = myApp.getObjectId( myMDD );
// bind the MDD value which substitutes formal parameter $1:
myQu.bind( myMDD );
// ...and ship the complete statement to the server:
myQu.execute();
9.8.3. rasdaman Cell Types¶
The set of cell base types known to rasdaman encompasses the usual numeric types. Below find the table of types known, and the necessary information to map them to Java types.
Null values, i.e., values of cells which have not been assigned a value yet, always are the numerical zero value of the corresponding type. This extends in the obvious way to composite cells.
Rasdaman |
Length |
Description |
|
8 bit |
signed integer |
|
8 bit |
unsigned integer |
|
16 bit |
signed integer |
|
16 bit |
unsigned integer |
|
32 bit |
signed integer |
|
32 bit |
unsigned integer |
|
32 bit |
single precision floating point |
|
64 bit |
double precision floating point |
|
1 bit 1 |
true (nonzero value) false (zero value) |
9.8.4. rasdaman Types vs. Java Types¶
Java types do not 1:1 correspond to rasdaman types. This is due to the fact that the Java type system in some aspects is different from what the ODMG Standard prescribes. Below find the most important caveats.
Long Integer
Long integer values in rasdaman always have 4 bytes, in accordance with
the ODMG standard. The corresponding rasdaman types are Ras_Long
and
Ras_ULong
.
In rasj, the array type to be used for 4-byte integers is
RasMArrayInteger
which matches with the Java int
type occupying 4 bytes.
Mind that the Java type long
represents 8 byte quantities. If an MDD
object is passed to the database through rasj, a overflow test takes
place on each integer value. An exception is thrown on overflow.
Unsigned Integers
Special care should be taken with unsigned integers, as Java does not
support this. For example, for cells of type Ras_UShort
(2 bytes) the
array type RasMArrayInteger
(4 bytes) must be used to collate values,
according to the ODMG standard.
9.9. Storage Layout¶
9.9.1. Overview¶
At insertion time of an MDD object, several database-internal storage
parameters can be set to affect the way the object is stored in the
database. A RasStorageLayout
object, attached to a RasGMArray
MDD
object, will guide storage of this MDD object when passed to the server
through RasOQLQuery.execute()
.
9.9.2. Class Hierarchy¶
* java.lang.Object
* rasj.RasStorageLayout
9.9.3. How To Use¶
The following code fragment shows how to associate a storage layout object with an MDD object; the storage layout will be evaluated at insertion time of the MDD into the database.
// create 2-D MDD with cell length 1, i.e., type byte:
RasGMArray myMDD =
new RasGMArray(new RasMInterval( "[1:400,1:400]" ), 1 );
// assume that there is some byte array prepared, insert it:
myMDD.setArray( mydata );
// set image type name
myMDD.setObjectTypeName("GreyImage");
// add storage layout object:
RasStorageLayout myLayout = new RasStorageLayout();
// now you can set either TileSize or TileDomain; to this
// end, continue with Alternative 1 or 2, as described below
Alternative 1: set tile size
Having prepared the object as described above, now the tiling strategy can be set. Experience tells that a good size for tiles is 4 MB, but bear in mind that the optimal size for tiles depends on the actual user behaviour as well as various system parameters.
// define size of tiles as 128,000 bytes:
myLayout.setTileSize( 128000 );
myMDD.setStorageLayout( myLayout );
Alternative 2: set domain shape
As an alternative to setting the overall tile size, the domain can be prescribed. This is more exact, as it allows to define not only size, but also the extent per dimension. For example, if it is known from the user access patterns there are ten times as much vertical slices requested than are horizontal ones, then it may be a good strategy to define tiles with a vertical:horizontal ratio of 10 to 1.
// define tiles with spatial extent [1:1000,1:100]:
myLayout.setTileDomain("[1:1000,1:100]");
myMDD.setStorageLayout( myLayout );
Note
rasdaman also allows to set the storage and compression format, as well as client/server transfer format. However, currently the interface controlling these parameters is only available via the C++ interface, not yet via Java. In future versions format and compression control will be available via Java, too.
9.10. Collections and Queries¶
9.10.1. Overview¶
Bag versus Set
Queries return multi-sets as results. The corresponding query result
type is DBag
.
A bag or multi-set is a collection of elements similar to sets an
lists; like a set (and unlike a list), no particular sequence is
defined, and like a list (and unlike a set), the same elements can occur
multiply. While {1,2,3}
is an example for a set, [1,2,2,3]
is a bag
example; [1,2,3]
denotes the same bag as [3,2,1]
, because sequence is
irrelevant in a bag.
Let us clarify the difference with an example. A query which returns the object identifiers (OIDs) of some database objects, such as
select oid(a)
from a
never will contain duplicates, as OIDs are unique by definition On the other hand, requesting summary information on MDD objects may well lead to duplicates; for example, in a query like this:
select avg_cells(a)
from a
several objects may share the same maximum or average cell value. In the
latter case, it obviously is crucial to obtain duplicates also.
Therefore, the query result always is DBag
, which forms a particular
subclass of the general class DCollection
.
Nevertheless, we will use the term result set sometimes, as it is just common database speak.
Important Hint
Use org.odmg.DBag
, do not use rasj.odmg.RasBag
!
9.10.2. Class Hierarchy¶
* java.lang.Iterable<T>
* java.util.Collection<E>
* org.odmg.DCollection
* org.odmg.DArray (also extends java.util.List<E>)
* org.odmg.DBag
* org.odmg.DList (also extends java.util.List<E>)
* org.odmg.DSet (also extends java.util.Set<E>)
* java.util.List<E>
* org.odmg.DArray (also extends org.odmg.DCollection)
* org.odmg.DList (also extends org.odmg.DCollection)
* java.util.Set<E>
* org.odmg.DSet (also extends org.odmg.DCollection)
9.10.3. How To Use¶
The following code piece demonstrates how to use object sets in the typical case of querying the database and piecewise processing the result set:
OQLQuery myQu = myApp.newOQLQuery();
myQu.create( "select mr from mr" );
DBag resultSet = (DBag) myQu.execute();
if (resultSet != null)
{
Iterator iter = resultSet.iterator();
while ( iter.hasNext() )
{
RasGMArray result = (RasGMArray) iter.next();
// ...here now process result...
}
}
Synchronous query execution
When a query is sent to the rasdaman server it will be executed in completeness - a running query cannot be aborted 2. Care should be taken therefore not to start queries requiring resources beyond the capability of the server hardware and software environment, as the rasdaman service may be blocked for an indefinite time period.
9.10.4. Query Result Type¶
Database collections satisfy some criterion of homogeneity; this common property is expressed through the underlying type definition. Likewise, a collection returned as a query result has such an underlying common type definition. However, as queries dynamically describe and instantiate structures, this may not always adhere to some type existing in the database - sometimes the structure is new, so a type structure has to be generated “on the fly”. While such a type does not have a name, its structure is well defined through the query itself.
This dynamic typing is predefined in the ODMG standard to which rasj adheres, so further information can be obtained there.
To access cells from arrays in query result bags, accessor functions are
provided, such as getObject()
, getInteger()
. These functions are
supervised by the type checking mechanism, hence using a function on an
in appropriate type will cause an exception of type ClassCastException
.
Generally speaking, it is up to the application to know the result type structure of the query it has sent to the server.
9.11. OIDs¶
9.11.1. Overview¶
The class RasOID
manages object identifiers (OIDs) for persistent MDD
and collections.
9.11.2. Class Hierarchy¶
* java.lang.Object
* rasj.odmg.RasOID
Note
Class java.lang.Object
obviously has further subclasses, not just the
one shown here.
9.11.3. How To Use¶
The following code fragment prints the OID for each object in a query result set.
myQu = myApp.newOQLQuery();
myQu.create( "select mr from mr" );
DBag resultSet = (DBag) myQu.execute();
if (resultSet != null)
{
Iterator iter = resultSet.iterator();
while ( iter.hasNext() )
{
RasGMArray result = (RasGMArray) iter.next();
System.out.println( "<"
+ result.getOID().getSystemName() + "|"
+ result.getOID().getBaseName() + "|"
+ result.getOID().getLocalOID() + " >" );
// last statement is equivalent to:
// System.out.println( getObjectId( result ) );
}
}
9.12. Type Management¶
9.12.1. Overview¶
rasdaman allows to define new types during runtime of the system. This
is in contrast to programming languages where type structures are fixed
at compilation time. rasdaman, therefore, offers separate mechanisms to
maintain database types; these are provided through the RasType
class
and its subclasses. For each structure relevant in dealing with
persistent (i.e., database stored) entities, a corresponding type class
is provided.
Note
Right now, rasj does not allow to create and manipulate persistent types in the database; methods provided mainly serve to inquire the result type of a query for a maximum of code flexibility. Database type manipulation can be done through rasql queries, for more details see Type Definition Using rasql.
9.12.2. Class Hierarchy¶
* java.lang.Object
* rasj.RasType
* rasj.RasBaseType
* rasj.RasPrimitiveType (implements rasj.global.RasGlobalDefs)
* rasj.RasStructureType
* rasj.RasCollectionType
* rasj.RasMArrayType
* rasj.RasMIntervalType
* rasj.RasOIDType
* rasj.RasPointType
* rasj.RasSIntervalType
9.12.3. How To Use¶
The following code piece demonstrates how the type structure given by
some RasType
object can be evaluated and printed in a user-friendly
form.
// instantiate a sample MDD type object:
RasType rType = RasType.getAnyType( "marray <char, 1>" );
// Now let's forget again that we know rType, let's analyse.
// Check if the type object is some MDD type:
if (rType.getClass().getName().equals("rasj.RasMArrayType"))
{
// yes, it is an MDD; is it structured or simple?
if (rType.isStructType())
{
// yes, structured:
System.out.println( "Structured base type is: " +
rType.getBaseType() );
}
else
{
// no, atomic:
System.out.println( "Atomic base type is: " +
rType.getBaseType() );
}
}
else
{
// no, not an MDD at all.
System.out.println(
"type object doesn't describe an MArray." );
}
9.13. Exceptions¶
9.13.1. Overview¶
Exceptions serve to handle deviations from the desired flow of
operation. Several exceptions can be thrown by rasj classes; as a
general rule, all exceptions are subclassed from the general Java
exception class java.lang.Exception
. Exceptions are further grouped into
four main classes
org.odmg.Exception
java.lang.RuntimeException
rasj.RasException
rasj.RasRuntimeException.
See the HTML documentation for details on the exception class hierarchy.
9.13.2. Class Hierarchy (pruned)¶
* java.lang.Object
* java.lang.Throwable (implements java.io.Serializable)
* java.lang.Exception
* org.odmg.ODMGException
* rasj.RasException
* java.lang.RuntimeException
* org.odmg.ODMGRuntimeException
* rasj.RasRuntimeException
Note
All classes have further subclasses See Class Hierarchy and Class Hierarchy for more information.
9.13.3. Handling Exceptions in the Client¶
Catching an exception can be done, for example, as shown below. Obviously there are several ways doing this - however, a few rules should be obeyed:
Granularity of exception catching depends on the overall program structure and purpose. For example, for data insertion one may want to build not just one large transaction, but several smaller units which, in case of failure, can be rerun with less time expenditure.
Don’t forget to clean up program state during exception recovery - think of closing (aborting? committing?) transactions, closing the database, etc.
Sample exception handling code
The following code piece demonstrates simple exception handling. The whole database access code is wrapped into a try statement. In case of an exception, the corresponding catch statement attempts to abort the transaction (if any is open) and to close the database. If in the course of these actions another exception occurs (for example, because the communication line has broken down), an error message is generated and the program terminates.
try
{
Implementation myApp = new RasImplementation( "http://" + server + port );
((RasImplementation)myApp).setUserIdentification(user, passwd);
myDb = myApp.newDatabase();
myDb.open(base, Database.OPEN_READ_ONLY);
myTa = myApp.newTransaction();
myTa.begin();
// here do some work with the database
myTa.commit();
myDb.close();
}
catch ( java.lang.Exception e ) // catch any error
{
System.out.println( e.getMessage() );
try
{
if(myTa != null)
myTa.abort();
if(myDb != null)
myDb.close();
}
catch ( org.odmg.ODMGException exp ) // catch an abort
// or close error
{
System.err.println( "Cannot commit/close: " + exp.getMessage());
}
}
9.13.4. Exceptions in the Class rasj.RasException¶
The following exceptions are rasj specific:
RasDimensionMismatchException
The dimensions of the two operand objects do not match.
RasIndexOutOfBoundsException
The specified index is not within the bounds of the array indexed.
RasResultIsNoCellException
The operation result is no cell, but an array cell is expected at this
position. This happens, e.g., if the cast operator for casting to the
base type of class RasGMarray
is invoked on an object which is not
‘zero-dimensional’.
RasResultIsNoIntervalException
The result is no interval, but an interval is expected at this position.
RasStreamInputOverflowException
An initialization overflow occured. This happens, e.g., if the stream input operator is invoked more often than the object has dimensions.
RasTypeInvalidException
Access method does not fit base type.
9.13.5. Exceptions in the Class org.odmg.QueryInvalidException
¶
RasQueryExecutionFailedException
This exception extends ODMGQueryInvalidException
by offering direct
access to the rasdaman error number and the line, column and token in
the query string that produced the error.
9.13.6. Exceptions in the Class org.odmg.ODMGRuntimeException
¶
RasConnectionFailedException
This exception is raised when the connection to the server fails.
9.13.7. Exceptions in the Class rasj.RasRuntimeException
¶
RasClientInternalException
This runtime exception indicates an internal error on client side which cannot be solved by the user. In case of such an event, send a report to your dealer containing the complete error message and a precise description of the actions that lead to this exception.
RasTypeNotSupportedException
This exception is raised when the base type of a query result is not supported by the current version of the rasj package.
RasTypeUnknownException
This exception is raised when the base type of a query result is unknown on client-side.
RasInvalidNameException
This exception is thrown if an object name contains invalid characters.
RasIllegalULongValueException
Thrown if a RasMArrayLong is trying to be sent to the server where one or more cell values are out of the range of 32-bit unsigned integers.
RasIllegalUShortValueException
Thrown if a RasMArrayShort is trying to be sent to the server where one or more cell values are out of the range of 16-bit unsigned integers.
9.14. Compilation and Execution of Client Programs¶
9.14.1. Compiling Code Using rasj¶
Environment Variables
The CLASSPATH
variable - which is used by the Java compiler to locate
packages used - must be extended with the path for the rasj directory of
the rasdaman distribution. This can be done, e.g., with the following
command:
export CLASSPATH=$RMANHOME/lib/rasj.jar;$CLASSPATH
Alternatively, the -classpath
or -cp
option of javac
can be used to explicitly
make known the package locations to the Java compiler.
Further, the JDK class directory must be contained in CLASSPATH
, and the
JDK binaries directory must be contained in the PATH
variable.
Java sources making use of the rasj package are compiled and run as
usual. For example, a source file Lookup.java
containing class Lookup
would be compiled as
javac Lookup.java
Running it as an application would be done through this command line statement:
java Lookup
Sample Programs
Several sample Java programs are provided as part of the rasdaman
distribution; they are located in the $RMANHOME/share/rasdaman/examples/java
directory of the
distribution.
Web Servlets and Applications
rasj allows to build applications written in Java which can be web servlets as well as applications. See petascope for example Geo Services Guide.
Notes
Remember the uppercase/lowercase distinction of Java!
For all classes with package definitions - such as rasj.RasGMArray
- the
package name must be prefixed.
9.14.2. Java Version Compatibility Statement¶
rasj has been successfully tested with JDK versions 1.7+.
9.14.3. HTTP communication¶
rasj internally uses HTTP to communicate with the rasdaman server. By selecting individual URLs and ports in the database open statement (see ODMG), safe database access across firewalls is possible.
9.14.4. Copyright Note¶
rasj contains code for password encoding based on MD5.
Provision of this code is done in accordance with the GNU Library General Public License (see www.gnu.org).
9.14.5. Legal Note¶
Note that under some legislations usage and/or distribution of cryptography code may be prohibited by law. If you have obtained the abovementioned library in or from a region under such a legislation, whatever you do with it is fully under your own responsibility. Inform rasdaman GmbH about the source where you have it obtained from so that we can take action against any violator.
9.15. HTML Documentation¶
The implementation is described in extensive documentation integrated
with the source code from which a set of HTML files. This documentation
can be used with any Web browser. The entry point for the complete
documentation pages, including the rasj part, is doc/index.html
in the
rasdaman distribution directory (see Server Architecture).
ODMG Class Availability
Note that the org.odmg
package is taken verbatim from the ODMG standard.
rasdaman interface classes are derived as implementations of the
standard classes. However, only those classes have been implemented
which are necessary for rasdaman. If in doubt, the Implementation
section should be consulted where unavailable items are marked (due to
copyright restrictions, the ODMG text must remain unchanged).