Open Exchange
Global Masters
InterSystems IRIS Data Platform 2019.3 / Application Development / Using the Native API for Java / Introduction to the Native API
Previous section   Next section

Introduction to the Native API

The Native API is a lightweight Java interface to the native multidimensional storage data structures that underlie the InterSystems IRIS™ object and SQL interfaces. The Native API allows you to implement your own data structures by providing direct access to global arrays, the tree-based sparse arrays that form the basis of the multidimensional storage model. The Native API is implemented in the com.intersystems.jdbc.IRIS class as an extension to the InterSystems JDBC driver (see “InterSystems Java Connectivity Options” in Using Java JDBC with InterSystems IRIS for details).
This chapter discusses the following topics:

Introduction to Global Arrays

An InterSystems IRIS™ global array, like all sparse arrays, is a tree structure rather than a sequentially numbered list. The basic concept behind sparse arrays can be illustrated by analogy to the Java package naming convention. Each class in a package is uniquely identified by a namespace made up of a series of identifiers. For example, consider a package containing only two classes, main.foo.SubFoo and main.bar.UnderBar. The five identifiers that make up these namespaces could be viewed as elements of a sparse array:
   main -->|--> foo --> SubFoo
           |--> bar --> UnderBar
Classes could be created that use the other possible namespaces (for example, main or main.bar), but no resources are wasted if those classes do not exist.
Like Java classes, the elements of a global array are uniquely identified by a namespace consisting of an arbitrary number of identifiers. All namespaces in the global array structure are referred to as nodes. A node must either contain data, have child nodes, or both. A node that has child nodes but does not contain data is called a valueless node.
The root identifier (like main in the Java package) is referred to as the global name. All other identifiers in the namespace are called subscripts. The complete namespace of the node (global name plus subscripts) is the node address.
In ObjectScript notation, a node address is symbolized by a circumflex (^) followed by the global name and a comma-delimited subscript list in parentheses. For example, given a global array using the same identifiers as the Java package example, the nodes in the array would be represented as follows:
   (valueless root node)   ^main
   (valueless node)           ^main("foo")
   (node with value)             ^main("foo","SubFoo") = <value>
   (valueless node)           ^main("bar")
   (node with value)             ^main("bar","UnderBar") = <value>
The root node of the array is simply ^main, with no subscript list. The two nodes containing data are ^main("foo","SubFoo") and ^main("bar","UnderBar"). Nodes ^main, ^main("foo") and ^main("bar") are all valueless.
All descendants of a given node are referred to as subnodes of that node. For example, ^main("foo","SubFoo") is a subnode of ^main("foo"), and all four subscripted nodes are subnodes of ^main.
The term node level refers to the number of subscripts in the subscript list. For example, ^main("bar","UnderBar") is a level 2 node. The address has a level 1 subscript ("bar"), and a level 2 subscript ("UnderBar").
For more detailed information on the structure of global arrays, see “Logical Structure of Globals” in Using Globals.

The NativeDemo Program

This section describes a Native API application that creates and accesses a global array. In NativeDemo, a new jdbc.IRISConnection object is created and connected to the USER namespace on the InterSystems IRIS server. The connection object is used to create an instance of the jdbc.IRIS class. The program adds a new global array with two nodes to the database, reads the new persistent values from the database, and then deletes them before closing the connection and terminating.
The NativeDemo Program
package nativedemo;
import com.intersystems.jdbc.*;
public class NativeDemo {
  public static void main(String[] args) throws Exception {
    String connStr = "jdbc:IRIS://";
    String user = "_SYSTEM";
    String password = "SYS";
    try {
      System.out.println("\nCreating the database connection... ");
      IRISConnection conn = (IRISConnection) java.sql.DriverManager.getConnection(connStr,user,password);
      System.out.println("Creating the IRIS instance... ");
      IRIS dbnative = IRIS.createIRIS(conn);

      dbnative.set("Hello world","globalArray","sub1");
      System.out.println("Created subnode ^globalArray(\"sub1\") with value \""
                         + dbnative.getString("globalArray","sub1") + "\"");
      System.out.println("Assigned value \"" + dbnative.getString("globalArray") + "\" to root node.");

      dbnative.kill(globalName);   // delete entire global array ^globalArray
    catch (Exception e) {
  }// end main()
} // end class NativeDemo
NativeDemo prints the following lines:
Creating the database connection...
Creating the IRIS instance...
Created subnode ^globalArray("sub1") with value "Hello world"
Assigned value "value2" to root node.
In this example, JDBC and Native API methods perform the following actions:
  • java.sql.DriverManager.getConnection() creates a new Connection, and the returned connection is cast to an IRISConnection object named conn. (jdbc.IRISConnection is the InterSystems implementation of the standard JDBC Connection class). The conn object provides a JDBC connection to the database associated with the USER namespace.
  • IRIS.createIRIS() creates a new instance of jdbc.IRIS named dbnative, which will access the database through conn.
  • IRIS.set() creates a new persistent node in the database. The call specifies value "Hello world", global name "globalArray", and subscript "sub1" creating subnode ^globalArray("sub1"). In the print statement, a call to IRIS.getString() queries the database and returns the value of the subnode.
  • Root node ^globalArray (with no subscripts) now exists because it contains a subnode, even though it does not contain a value. The second call to set() assigns string "value2" to ^globalArray. In the print statement, getString() returns the value of ^globalArray from the database.
  • IRIS.kill() deletes the specified node and all of its subnodes from the database. Since both nodes of the global array ^globalArray would persist in the database after the connection is closed, we delete the entire array at once by calling to kill() on root node ^globalArray.
  • This little program assumes that it has exclusive use of the system, so close() methods for both dbnative and conn are called. A real world application might be using several different IRISConnection objects, all of which would be closed because they all use the same underlying connection.
All of these methods are discussed in detail later in this book. See the next chapter (“Working with Global Arrays”) for details about specifying the subscripts of a node reference, creating a node, and changing a node value.
Previous section   Next section