Basic Requirements

All API application programs are required to perform specific basic operations that are common to all API programs. This section describes in detail the process of writing the shell of an application, and is aimed at programmers who are new to the Essbase API.


The Nested Program Model

When programming using the API, your code should adopt the nested programming model. In the nested programming model the code has calls to an initial function and a corresponding final function. The calls are arranged as a sandwich, with the code to perform some action in between as the filling. Consider the following example:

begin action 1
        begin action 2
                begin action 3
                        perform action 3
                end action 3
                begin action 4
                        perform action 4
                end action 4
        end action 2
end action 1

The implication of this arrangement is that you should ensure that you end every action or operation that you begin. Here is a more concrete example that uses real API actions:

Initialize the API
        Login to a server
                Connect to a database
                        Open a database outline
                                Browse the outline
                        Close the outline
                        Open a report
                                Modify & save the report
                        Close the report
                Disconnect from a database
        Logout from the server
Terminate the API

The example above illustrates the basic structure of any code that accesses the Essbase API.


Using Function Return Codes

One of the first things you need to know as an API developer is how to handle the status codes returned by API functions. In general, a zero return code indicates successful completion and a non-zero return code indicates an error. In the latter case, the program should abort the operation in progress and return to the default state, only calling those API functions that are needed to clean up. It is essential that every time a program makes a call to the API that it checks the return code and handles it properly.

The API provides a type declaration for status return codes (ESS_STS_T) and a constant declaration (ESS_STS_NOERR). The constant declaration can be used to test the status return codes from API functions in an implementation-independent way.

/* C Example of checking return value from an API function */
ESS_STS_T       sts;
if ((sts = EssSomeFunction (.....)) == ESS_STS_NOERR)
{
        do something else;
}
else
{
        process error;
}
' VB Example of checking return value from an API function */
Dim     sts as ESB_STS_T
if ((sts = EsbSomeFunction (.....)) == ESB_STS_NOERR)
        do something else
else
        process error
endif

The nested programming model is good for releasing resources if an Essbase function fails and returns an error return value. Consider the following example:

allocate resource 1
begin action 1
        allocate resource 2
        begin action 2
                action 2
        end action 2
        free resource 2
end action 1
free resource 1

Calling API Functions

Each API function has the prefix Ess (for C) or Esb (for Visual Basic) followed by a verb-object naming convention, for example, EssGetDatabaseInfo(). Some functions that relate to a specific area of the product have an additional prefix to indicate that relationship. For example, all the Outline API functions have EssOtl or EsbOtl prefixes, for example, EssOtlOpenOutline() and EsbOtlGetNextSibling().

All API functions take a series of arguments. The arguments are different for every function. But the arguments follow a logical sequence. The first argument to most functions is typically a handle, either an instance handle, a context handle, an outline handle, or a member handle. The term "handle" refers to an identifier that is used by the API to keep track of different objects in the system (just like a file handle). Different handles are returned by certain functions. Handles should then be stored in your program and passed to other API functions when required.

Handles are different in C and Visual Basic. For more information on the different types of API handles and their uses, refer to Using the C Main API and Using the Visual Basic Main API.

If there are any arguments to be passed in to a function, they typically come next in the sequence. Finally, if the function returns any values, the variables to store those returned values are passed in at the end of the argument list.

In the following examples, the first argument is a context handle (hCtx). The next two arguments (the application and database names, Sample and Basic), are passed in and the argument to be returned (the database information structure, ESX_DBINFO_T) is passed in at the end:

/* C Example of passing arguments to an API function */
ESS_STS_T       sts;
ESS_HCTX_T      hCtx;
ESS_PDBINFO_T   pDbInfo;
sts = EssGetDatabaseInfo (hCtx, "Sample", "Basic", &pDbInfo);
if (sts == ESS_STS_NOERR)
{
        do something;
}

' VB Example of passing arguments to an API function
Dim     sts as ESB_STS_T
Dim     hCtx as ESB_HCTX_T
Dim     DbInfo as ESB_DBINFO_T
sts = EsbGetDatabaseInfo (hCtx, "Sample", "Basic", DbInfo)
if (sts = ESB_STS_NOERR)
        do something
endif

Note that in the C example, the returned argument (pDbInfo) is passed to the function as a double indirection (a pointer to a pointer) by passing the address of a declared structure pointer variable (using the & operator). This variable is then assigned the address of a database information structure that is allocated internally by the API function.

In the Visual Basic example, the caller first allocates the structure (DbInfo) and passes it to the API function (implicitly by reference).


Initializing the API

All application programs must initialize the API (with EsxInit()) before using any other Essbase API functions. The program should perform the initialization only once, preferably during the program's startup sequence.

/* C Example of initializing the API */
ESS_STS_T       sts;
ESS_INIT_T      InitStruct;
ESS_HINST_T     hInst;
/* first clear the init structure (use API defaults) */
memset (&InitStruct, 0, sizeof (ESS_INIT_T));
sts = EssInit (&InitStruct, &hInst);

' VB Example of initializing the API
Dim     sts as ESB_STS_T
Dim     InitStruct as ESB_INIT_T
Dim     hInst as ESB_HINST_T
sts = EsbInit (InitStruct, hInst)

The API default settings are appropriate for most application programs. If you need to change the settings, refer to the EssInit() and/or EsbInit() for more information on setting the individual fields of the API initialization structure (ESS_INIT_T and ESB_INIT_T) in your program.

The instance handle (hInst) that is returned from EsxInit() should be saved within your program for subsequent API calls. This instance handle uniquely identifies your program and its associated resources to the API.

Would you like to see an actual Sample C API Program?

Would you like to see an actual Sample Visual Basic API Program?


Logging On to a Server

After the API is initialized, a program must log in to an Essbase server in order to perform any actions on that server. Generally, a login only needs to be performed when a specific action is requested by the user (typically a database connect operation). Note that a login to a server does not necessarily imply a connection to a specific application or database on that server; some administration operations do not require a connection to a particular database, and some do not even require connection to a server.

A login can be performed using EsxLogin(). For Microsoft Windows only, an encapsulated login dialog function, EsxAutoLogin(), is available. The dialog box displayed by this function is similar to the one used by the Administration Services and Spreadsheet Add-in interfaces. Optionally, the user can use the dialog box to select an application and a database to connect to (see Connecting to a Database, below). The user can also perform other operations, such as changing a password.

/* C Example of a login using the EssLogin function */
ESS_STS_T       sts;
ESS_HINST_T     hInst;
ESS_SVRNAME_T   Server = "Larch";
ESS_USERNAME_T  Username = "Joe User";
ESS_PASSWORD_T  Password = "secret";
ESS_ACCESS_T    Access;
ESS_HCTX_T      hCtx = ESS_INVALID_HCTX;
sts = EssLogin (hInst, Server, Username, Password, &Access, &hCtx);

' VB Example of a login using the EsbLogin function
Dim     sts as ESB_STS_T
Dim     hInst as ESB_HINST_T
Dim     Server as ESB_SVRNAME_T
Dim     Username as ESB_USERNAME_T
Dim     Password as ESB_PASSWORD_T
Dim     Access as ESB_ACCESS_T
Dim     hCtx as ESB_HCTX_T
Server = "Larch"
Username = "Joe User"
Password = "secret"
hCtx = ESB_INVALID_HCTX
sts = EsbLogin (hInst, Server, Username, Password, Access, hCtx)

The following is a similar example of logging in, this time using EsxAutoLogin(). When using this function, the user supplies all the relevant information (server name, user name, password, application, and database names) by entering the information into the appropriate fields of the dialog box:

/* C Example of a login using the EssAutoLogin function */
ESS_STS_T               sts;
ESS_HINST_T             hInst;
ESS_ACCESS_T            Access;
ESS_HCTX_T              hCtx = ESS_INVALID_HCTX;
sts = EssAutoLogin (hInst, ESS_NULL, ESS_NULL, ESS_NULL, ESS_NULL,
        ESS_NULL, AUTO_DEFAULT, &Access, &hCtx);
        
' VB Example of a login using the EsbAutoLogin function
Dim     sts as ESB_STS_T
Dim     hInst as ESB_HINST_T
Dim     Access as ESB_ACCESS_T
Dim     hCtx as ESB_HCTX_T
hCtx = ESB_INVALID_HCTX
sts = EsbAutoLogin (hInst, ESB_NULL, ESB_NULL, ESB_NULL, ESB_NULL,
        ESB_NULL, ESB_AUTO_DEFAULT, Access, hCtx)

See EssLogin(), EsbLogin(), EssAutoLogin(), and EsbAutoLogin() .

Note that, if string variables, instead of ESX_NULL, are passed to the function as the user-entered parameters, on return from the function those variables contain the values entered into the login dialog box by the user.

Your program should normally login once (at the start of a user session). However, if tying up unused server ports is a big issue, consider logging in at the start of each operation, and logging out at the end of each operation (see Logging Out). Note, however, that this process can slow down user response time significantly.

When using either EsxLogin() or EsxAutoLogin(), the returned login context handle (hCtx) should be saved within your program for subsequent API calls. The login context handle uniquely identifies that particular login to the API.

Using Local Context Handles

If you are performing API administrative operations (such as file operations) on the client machine, you can use a dummy login context handle to represent a local login to the API. The dummy handle can be used like a server context handle, except that most server-specific and database-specific operations cannot be performed. Use EsxCreateLocalContext() to create a local context handle. Consider the following example:

/* C Example of creating a local context handle */
ESS_STS_T       sts;
ESS_HINST_T     hInst;
ESS_HCTX_T      hLocalCtx = ESS_INVALID_HCTX;
sts = EssCreateLocalContext (hInst, ESS_NULL, ESS_NULL, &hLocalCtx);

' VB Example of creating a local context handle
Dim     sts as ESB_STS_T
Dim     hInst as ESB_HINST_T
Dim     hLocalCtx as ESB_HCTX_T
hLocalCtx = ESB_INVALID_HCTX
sts = EsbCreateLocalContext (hInst, ESB_NULL, ESB_NULL, hLocalCtx)

Connecting to a Database

Many Essbase API functions (such as server administration, security, and outline maintenance) can be performed after the program has logged in. However, many database-related functions (for example, reporting or performing calculations) require that the program connect to a specific application and database. Use EsxSetActive() to identify a specific Essbase database. Logging in with EsxAutoLogin() also allows the identification of a specific database.

Note that the user must have sufficient privileges to access the database. A list of all applications and databases to which a particular user has access is returned by EsxLogin(), and can be obtained using EsxListDatabases().

If you connect to a database that is not running, Essbase automatically starts the database. It is not necessary to disconnect from a database. However, using the same login context handle to connect to another database will disconnect you from the original database. If you really need to be connected to two or more databases at once, your program needs to login multiple times (and manage each context handle independently).

/* C Example of connecting to a database */
ESS_STS_T       sts;
ESS_HCTX_T      hCtx;
ESS_APPNAME_T   AppName = "Sample";
ESS_DBNAME_T    DbName = "Basic";
ESS_ACCESS_T    Access;
sts = EssSetActive (hCtx, AppName, DbName, &Access);

' VB Example of connecting to a database
Dim     sts as ESB_STS_T
Dim     hCtx as ESB_HCTX_T
Dim     AppName as ESB_APPNAME_T
Dim     DbName as ESB_DBNAME_T
Dim     Access as ESB_ACCESS_T
AppName = "Sample"
DbName = "Basic"
sts = EsbSetActive (hCtx, AppName, DbName, Access)

The user's access level to the selected database is returned by EssSetActive (and by EsxAutoLogin()). This access level can be checked by using the security constant definitions that allow the application program to alter user options, by graying out menus, and so on.


Logging Out

After the user completes one or more database operations and finishes with Essbase, your program should log out from the server. Logging out can be done either as a result of an explicit user request or automatically (for example, after a specific sequence of actions is complete). All active connections should also be logged out before the program terminates and exits.

It is not always necessary for the program to log out after each data access operation. Whether to log out (and so release Essbase ports) or remain logged in (giving faster response to successive user requests) is a design judgment call.

/* C Example of logging a user out */
ESS_STS_T       sts;
ESS_HCTX_T      hCtx;
sts = EssLogout (hCtx);
hCtx = ESS_INVALID_HCTX;

' VB Example of logging a user out
Dim     sts as ESB_STS_T
Dim     hCtx as ESB_HCTX_T
sts = EsbLogout (hCtx)
hCtx = ESB_INVALID_HCTX

After logging out, do not use that same context handle. That will probably crash your program.

If you want to dispose of a local context handle, use EsxDeleteLocalContext():

/* C Example of deleting a local context handle */
ESS_STS_T       sts;
ESS_HCTX_T      hLocalCtx;
sts = EssDeleteLocalContext (&hLocalCtx);

' VB Example of deleting a local context handle
Dim     sts as ESB_STS_T
Dim     hLocalCtx as ESB_HCTX_T
sts = EsbDeleteLocalContext (hLocalCtx)

Terminating the API

At the very end of its execution, your program should terminate the API by calling EsxTerm(), to ensure the proper release of all API resources. This function also logs out all active server connections (if they are not already explicitly logged out by your program).

/* C Example of terminating the API */
ESS_STS_T       sts;
ESS_HINST_T     hInst;
sts = EssTerm (hInst);
hInst = ESS_INVALID_HINST;

' VB Example of terminating the API
Dim     sts as ESB_STS_T
Dim     hInst as ESB_HCTX_T
sts = EsbTerm (hInst)
hInst = ESB_INVALID_HINST

After terminating the API, do not attempt to make any more calls to API functions. If you make more calls your program will probably crash.