***  This package contains classes that provide Binary Compatibility only, not Source Compatibility  ***

Note:
Extension of the classes in this package is prohibited unless otherwise documented. Similarly, extension or implementation of the interfaces in this package is prohibited except as documented.

Package com.sas.services.connection

Service for making and managing connections to IOM servers.

See:
          Description

Interface Summary
ConnectionFactoryAdminInterface The administrator's interface to a connection factory.
ConnectionFactoryEventListener An interface implemented by factory users who want to be notified of important events such as factory shutdown.
ConnectionFactoryInterface User interface for connection factories.
ConnectionFactoryShellInterface Methods common to all connection factory interfaces.
ConnectionInterface The factory-managed connection handle.
ConnectionMetadataInterface Information about the connection.
 

Class Summary
BridgeServer A description of an IOM bridge protocol server.
Cluster A base class representing a cluster of IOM servers.
ConnectionFactoryConfiguration The base class for all connection factory configurations.
ConnectionFactoryEvent A class used to notify factory users of important events such as factory shutdown.
ConnectionFactoryManager A factory of connection factories.
Credential A base class for credentials that can be used to authenticate and authorize use of a connection factory.
FailoverCluster A failover cluster of IOM servers.
LoadBalancingCluster A load balancing cluster of IOM servers.
ManualConnectionFactoryConfiguration A connection factory configuration in which the servers, clusters, and puddles that the factory is to connect to are explicitly described.
PasswordCredential Login credentials for an IOM server.
Puddle A description of a puddle of IOM clusters.
SecurityPackageCredential A credential to use when requesting a security-package-authenticated connection to a server.
Server A base class for describing IOM servers.
TCPIPServer A base class to describe IOM servers that communicate with clients using a TCP/IP application protocol.
TrustedPeerCredential A credential to use when requesting a trusted peer connection to a server.
XMLConfigurationBuilder Converts XML configuration files produced by the Integration Technologies Configuration tool (ITConfig) into a ManualConnectionFactoryConfiguration object.
 

Exception Summary
ConnectionFactoryException The base class for all connection service exceptions.
ConnectionTimeoutException The connection factory throws a timeout exception when a connection request could not be completed before an administrative time limit expired.
CredentialsException Base class for exceptions thrown to indicate that something is wrong with credentials presented during a connection request.
FatalConnectionFactoryException A exception that is so severe that a factory which throws this exception can no longer be used.
LoginException The connection factory throws a login exception when a connection request cannot be granted because the connecting client cannot be authenticated or authorized.
WrongCredentialsException The connection factory throws a wrong credentials exception when a connection request cannot be granted because the credentials presented with the connection request were not from an authetication domain supported by the connection factory.
 

Package com.sas.services.connection Description

Service for making and managing connections to IOM servers.

Connection Service

Overview

The connection service allows Java programs to connect to IOM servers. In addition to basic connectivity, the connection service provides or supports more advanced connection management features such as connection pooling, failover, and load balancing through the connection factory.

There is also a simple manager of connection factories. The connection factory manager allows a user to obtain a connection factory with a desired configuration without needing to know whether or not such a factory already exists.

Connection factories are not remotable so they cannot be deployed or located via the discovery service.

The connection service supports only IOM Bridge Protocol. The basic steps for obtaining a connection to an IOM server are listed below:

The code fragments introduced in these basic steps are compiled into a simple, complete sample program here. The code fragments do not include exception handling for brevity.

More advanced topics are also covered:

Throughout this document, server refers to either an IOM Bridge server or an IOM object spawner configured to start a server. From the client's point of view, the server and spawner behave exactly the same so there is no point in distinguishing one from the other.

Basic Topics

These topics cover the fundamental steps in understanding and using the connection factory.

Create a Connection Factory Configuration

A connection factory configuration contains information necessary for a connection factory to create a connection to an IOM Bridge server. This information is stored separately from the factory itself so that it may be reused easily.

The simplest style of connection factory configuration is manual configuration. To create a manual configuration object, you must provide, at a minimum, the type of IOM server, the address of the machine hosting the server, and the port on which the server is listening for connections.

The manual configuration style can also be used to configure a factory for more advanced connection management. More discussion and examples are available in the encryption, failover, load balancing, and connection pooling sections.

Also, more sophisticated configuration styles are discussed in the alternate configuration styles section.

Here is an example of a connection factory configuration that would tell a connection factory how to connect to a workspace server (or spawner) on host foo.bar.abc.com at port 1234:

 String classID = Server.CLSID_SAS;
 String host = "foo.bar.abc.com";
 int port = 1234;
 Server server = new BridgeServer(classID,host,port);
 ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(server);
 

Create a Connection Factory Manager

The connection factory manager creates and manages connection factories. Each instance of a connection factory manager acts as a scope for mapping connection factory configurations to functional connection factories. When a factory user requests a factory from a factory manager, he passes a connection factory configuration object to the manager. The manager first searches a set containing all the factories that it previously created and that are still functional. If a factory is found that matches the desired configuration, the manager returns that factory. Otherwise, the manager creates and returns a new factory.

This design allows more than one factory user to share a single connection factory without a great deal of coordination on the part of the factory users. While connection factory sharing can greatly reduce resource usage, it also has the potential to create some complicated factory lifetime problems. These tradeoffs are discussed in detail in the factory sharing section.

If you do not want your connection factory to be shared with other factory users, or if you are just getting started with the connection service, and you don't want to worry about factory sharing yet, then you should create a factory manager for your own use. Here is a code fragment that shows how to create a connection factory manager. There's not much to it:

 ConnectionFactoryManager cxfManager = new ConnectionFactoryManager();
 

Create a Connection Factory

After you have created a connection factory configuration and a connection factory manager, you can use them to create a connection factory that matches the configuration.

As previously discussed, the connection factory manager maintains a set of connection factories, and, if one of these connection factories matches your configuration, that factory it returned. Otherwise, the connection factory manager creates a new connection factory and returns it. In this simple example, however, let's assume that the manager has not previosly created any factories.

 ConnectionFactoryConfiguration cxfConfig = ...
 ConnectionFactoryInterface cxf = cxfManager.getFactory(cxfConfig);
 

Create a Connection

You can use a properly configured connection factory to create connections to the desired server. All connections to IOM servers must be associated with a user identity (unless the server is configured not to require an identity - which should be rare). The identity is used to grant or deny permission for certain operations carried out over the connection (such as an attempt to read a file).

The simplest way to associate an identity with a connection is to provide a user name and a password that are valid on the server. Here is an example:

 ConnectionFactoryInterface cxf = ...
 String userName = "myName";
 String password = "mySecret";
 ConnectionInterface cx = cxf.getConnection(userName,password);
 

Connection Usage

Connections returned by the connection factory have a generic interface for communication with remote objects on the server. For convenience, the generic interface can typically be converted to a server-specific interface through a process called narrowing. Narrowing is equivalent to casting for remote object references.

The connection factory is bundled with the classes necessary to narrow a generic interface reference to a workspace server reference. Narrowing to other server interfaces will require additional software packages.

Here is sample code describing how to narrow to a workspace server interface:

 ConnectionInterface cx = ...
 org.omg.CORBA.Object obj = cx.getObject();
 com.sas.iom.SAS.IWorkspace iWorkspace = com.sas.iom.SAS.IWorkspaceHelper.narrow(obj);
 ...
 

Reference information for the workspace server interface can be found here.

Connection Destruction

When you are finished with a connection, you may immediately release any resources associated with the connection by closing the connection. If you do not perform this step, the Java garbage collector will eventually reclaim these resources. Note that a connection is a fairly expensive resource so it is recommended that you close the connection explicitly as soon as you are done with it.

 ConnectionInterface cx = ...
 ...
 cx.close();
 

Connection Factory Destruction

When you are finished getting connections from a factory, you must destroy the factory. In general, the Java garbage collector will not reclaim resources associated with a connection factory until it also reclaims the connection factory manager that created the factory. The connection factory manager retains a reference to the connection factory so it may be reused and shared until is destroyed.

Factory destruction can be accomplished by calling the shutdown() and destroy() methods on the factory administration interface. The administration interface is obtained by calling getAdminInterface() on the factory.

The shutdown() and destroy() methods are more alike than they are different. Both cause a factory to release its resources and remove itself from its manager's factory set. Also, both cause a factory to disallow further connection requests. However, shutdown() is somewhat less forceful than destroy(). When shutdown() is called, any connections that have been allocated to users and have not yet been returned to the factory are allowed to remain open until they are returned. On the other hand, when destroy() is called, all open connections are immediately destroyed even if they are currently allocated to users.

shutdown() and destory() can be used in combination. Some applications may want to call shutdown() and then allow a period of time to pass to allow users to destroy any outstanding connections before calling destory().

In some cases it may be desirable to delay the destruction of a connection factory to allow the factory to be reused or shared. See the section on factory sharing for more details.

Here is an example of how to call shutdown() and destory().

 ConnectionFactoryInterface cxf = ...
 ...
 cxf.getAdminInterface().shutdown();
 ...
 cxf.getAdminInterface().destroy();
 

Simple Example Program

This sample program combines the code fragments from all the basic steps above.

 import com.sas.iom.SAS.IWorkspace;
 import com.sas.iom.SAS.IWorkspaceHelper;
 import com.sas.services.connection.*;
 public class SimpleExampleProgram
 {
      public static void main(String[] argv)
      {
           // create a connection factory configuration
           String classID = Server.CLSID_SAS;
           String host = "foo.bar.abc.com";
           int port = 1234;
           Server server = new BridgeServer(classID,host,port);
           ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(server);
           ConnectionFactoryManager cxfManager = new ConnectionFactoryManager();
           ConnectionFactoryInterface cxf = null;
           ConnectionInterface cx = null;
           try
           {
                // create a connection factory that matches the configuration
                cxf = cxfManager.getFactory(cxfConfig);
                // get a connection from the factory
                String userName = "myName";
                String password = "mySecret";
                cx = cxf.getConnection(userName,password);
           }
           catch (ConnectionFactoryException cfe)
           {
                cfe.printStackTrace();
                System.exit(1);
           }
           // narrow and use the connection
           org.omg.CORBA.Object obj = cx.getObject();
           IWorkspace iWorkspace = IWorkspaceHelper.narrow(obj);
           // use the connection
           // destroy the connection
           cx.close();
           // destroy the connection factory
           cxf.getAdminInterface().destroy();
      }
 }
 

Advanced Topics

Logging

Connection factories created by calling ConnectionFactoryManager.getFactory() use the java.util.logging package to write log messages. Two different logger names are used depending on the type of message.

Messages related to connection management are logged in a logger named com.sas.services.connection. Events that cause messages to be logged in this logger include allocations, deallocations, creations, and destructions. Most messages logged in this logger are logged at Level.FINE. Of course, error messages are logged at Level.SEVERE, and warnings are logged at Level.WARNING.

Messages related to connection usage are logged in a logger named com.sas.iom.orb. All IOM Bridge protocol-level communication between protocol peers is traced in this logger. Connection initialization tracing messages are logged at Level.FINE. Protocol packet tracing messages are logged at Level.FINER. Messages tracing the exchange of raw bytes between peers is logged at Level.FINEST. Logs that include messages from this logger can be extremely verbose.

Messages logged in either logger are prefixed with a tag that indicates the individual connection factory manager, connection factory, or connection to which it relates. For example, all messages related to invocation number 3 of getFactory() on instance number 2 of ConnectionFactoryManager are prefixed with the tag (m2,g3). If that invocation is successful, a log message will indicate what unique tracking number the connection factory manager assigned to the resulting connection factory, say f5. Then all messages related to invocation number 11 of getConnection() on that connection factory are prefixed with the tag (f5,rB).

It is best to manipulate the Connection Service loggers using a logging.properties file. The default file is located in the jre/lib directory of a Java installation. The path to an alternate file can be specified as the value of Java system property java.util.logging.config.file. The java.util.logging API can also be used to manipulate loggers at runtime. However, that approach sometimes requires security permissions.

Here is a quick example of the properties needed in the logging.properties file to print connection factory messages in the console.

 handlers = java.util.logging.ConsoleHandler
 java.util.logging.ConsoleHandler.level = FINE
 java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
 com.sas.services.connection.level = ALL
 

Note that connection factories created by calling getFactory() on a subclass of ConnectionFactoryManager might use a different logging subsystem. For example, connection factories created by calling PlatformConnectionFactoryManager.getFactory() use the Logging Service from Foundation Services.

Encryption

You can configure connections to IOM servers to encrypt information passed over the connection. Several encryption algorithms are supported. Implementations for four of these algorithms, RC2, RC4, DES, and TripleDES, have been provided by RSA, and you must license and install the SAS/SECURE product on the server to use these algorithms. In addition, you must install a JAR file containing Java implementations of these algorithms in your Java environment. See SAS/SECURE documentation for more details.

SAS has implemented a fifth encryption algorithm called SASPROPRIETARY. Support for this algorithm is included in the IOM server and connection factory with no additional licensing or installation requirements. However, this implementation is slower and more easily defeated than the RSA implementations.

To take advantage of encrypted connections to approriately configured IOM servers through the connection factory, use the encryption attributes on the BridgeServer class. Here is an example of a configuration which will encrypt all information passed between the client and server using RC2 if it is available on the server, or SASPROPRIETARY if RC2 is not available. If the IOM server is not configured to support encryption, then the connection will fail.

 String classID = Server.CLSID_SAS;
 String host = "foo.bar.abc.com";
 int port = 1234;
 String cryptoAlgorithms = BridgeServer.ENCRYPTION_ALGORITHM_RC2 + "," + BridgeServer.ENCRYPTION_ALGORITHM_SASPROPRIETARY;
 BridgeServer server = new BridgeServer(classID,host,port,cryptoPolicy,cryptoAlgorithms,cryptoContent);
 server.setEncryptionPolicy(BridgeServer.ENCRYPTION_POLICY_REQUIRED);
 server.setEncryptionAlgorithms(cryptoAlgorithms);
 ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(server);
 

Failover

A connection factory can be configured to tolerate a limited degree of server failure and still honor all connection requests from users. To use this feature, you must provide a cluster of redundant IOM servers instead of a single IOM server. As long as at least one of the servers in the cluster is available, the connection factory will be able to honor connection requests for the cluster.

The connection factory also can recover from server failures. If a server in a cluster fails, then the connection factory will route subsequent connections to another server in the cluster. If that server later fails, then the connection factory will once again redirect subsequent requests to another server in the cluster including the original server if it is back up.

If a server fails, active connections to that server will not be rerouted to other servers in the failover cluster. Instead, requests over those connections will get IO exceptions or CORBA system exceptions. The failover feature applies only to requests for new connections.

Only one server in a failover cluster is used by the connection factory at a time. In other words, if the connection factory routes a connection to a server in a cluster, and that server never fails, no other servers in the cluster will be used by the factory. If you are interested in spreading connections across several servers, see the sections on load balancing and connection pooling.

Here is a code fragment demonstrating the use of failover clusters.

 String classID = Server.CLSID_SAS;
 Server server0 = new BridgeServer(classID,"foo0.bar.abc.com",1234);
 Server server1 = new BridgeServer(classID,"foo1.bar.abc.com",1234);
 Server[] servers = {server0,server1};
 Cluster cluster = new FailoverCluster(servers);
 ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(cluster);
 

All servers in a cluster are expected to be configured in a similar manner such that they can be used interchangeably by the factory. In particular, all servers must have the same class ID and the same authentication domain. If they do not, the Cluster constructor will throw an IllegalArgumentException.

The connection factory uses clustered servers in the order that they appear in the server array. In the above example, the connection factory will use the IOM server on host foo0.bar.abc.com until it fails, and only then will it attempt a connection to the server on host foo1.bar.abc.com.

Load Balancing

The connection factory supports IOM spawners that distribute load across a cluster IOM servers. When the connection factory connects to a load balancing spawner, the spawner may instruct the connection factory to reconnect to another machine hosting a less-loaded IOM server. The reconnection is transparent to the connection factory user.

From the perspective of a connection factory user, a load balancing cluster is very much like a failover cluster; indeed, a load balancing cluster includes all the fault tolerance features of a failover cluster. However, load balancing clusters require additional configuration on the server side (not covered here).

Here is a code fragment demonstrating the use of load balancing clusters.

 String classID = Server.CLSID_SAS;
 Server server0 = new BridgeServer(classID,"foo0.bar.abc.com",1234);
 Server server1 = new BridgeServer(classID,"foo1.bar.abc.com",1234);
 Server[] servers = {server0,server1};
 Cluster cluster = new LoadBalancingCluster(servers);
 ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(cluster);
 
Important note: Load balancing clusters require a additional configuration on the server side (not covered here).

Connection Pooling

The connection factory can use a pool of reusable connections to IOM servers to server connection requests. Connection pooling can dramatically reduce the average time Java programs must wait while the connection factory makes connections to servers. However, the effectiveness of connection pooling depends on reusing connections. Therefore, Java programs that make frequent use of connections for brief periods are most likely to benefit from connection pooling. For example, a web application that, at a user's request, gets a connection from a connection factory, uses the connection to compute some value based on the user's input, and then disposes of the connection would be likley to benefit from connection pooling.

Because the connection factory reuses connections, the ConnectionInterface.close() method has a different behavior for pooling factories compared to non-pooling factories. Instead of destroying the connection when the close() method is called, the factory may simply refresh it. The refresh operation reinitializes the state of the connection without all the overhead of disconnecting and reconnecting.

Having reusable connections implies that, sometimes, the connection factory will make a connection to an IOM server before it knows what user will use the connection. The connection factory employs a two-tiered security model to ensure that a factory user is authorized to use a connection. When configuring a factory for pooling, you not only provide a Credential object that the factory will use when it connects to an IOM server, but you also provide the identities of users that are allowed to use the connections. The two-tiered security model allows the connection factory to make connections in advance of connection requests, and it also reduces the number of user accounts that must be maintained on the IOM server.

Note that, for the manual connection factory configuration, a user identity is specified using a PasswordCredential object that encapsulates the user's user name and password. The user may not always wish to expose his or her user name and password to the person who configures the connection factory. Therefore, it is expected that the manual connection factory configuration for pooling will only be used in situations where this exposure is not a concern. Connection factory configurations using LDAP, SAS Metadata Server, or SAS Foundation Services (discussed later) do not have this exposure.

Connection pools are subdivided into puddles, and each pool has at least one puddle. A puddle is an association of one or more IOM servers with a login which will be used by the factory to make connection to the servers. You may want to subdivide a pool into more than one puddle for either of two reasons. First, if you want the factory to pool connections to servers that belong to different authentication domains, you will need one puddle for each domain because each puddle can have only one login. Second, if you want to provide different levels of permission to different users, you can set up several puddles, each with the same set of servers, and associate different logins with varying degrees of permission on the servers with each puddle. Then you can use the two-tiered security model to determine which users will be authorized to use which puddle.

Here is a code fragment demonstrating how to configure a factory for connection pooling. The pool will be subdivided into two puddles. One puddle will be allowed read/write access to some file on the server, and the other will have only read access.

 String classID = Server.CLSID_SAS;
 Server server = new BridgeServer(classID,"foo.bar.abc.com",1234);
 Credential writerLogin = new PasswordCredential("writer","writerPW");
 Credential writerUser = new PasswordCredential("writerUser","writerSecret");
 Set authorizedWriters = new HashSet(1);
 authorizedWriters.add(writerUser);
 Puddle writerPuddle = new Puddle(server,writerLogin);
 writerPuddle.setUserCredentials(authorizedWriters);
 Credential readerLogin = new PasswordCredential("reader","readerPW");
 Credential readerUser = new PasswordCredential("readerUser","readerSecret");
 Set authorizedReaders = new HashSet(1);
 authorizedReaders.add(readerUser);
 Puddle readerPuddle = new Puddle(server,readerLogin);
 readerPuddle.setUserCredentials(authorizedReaders);
 Puddle[] puddles = {writerPuddle,readerPuddle};
 ConnectionFactoryConfiguration cxfConfig = new ManualConnectionFactoryConfiguration(puddles);
 

If a user presents the "writerUser" credentials to the factory created in the example above, he will get a connection from the "writerPuddle". Likewise, if a user presents the "readerUser" credentials to the factory created in the example above, he will get a connection from the "readerPuddle".

Connection Factory Sharing

In some cases it may be desirable to allow a connection factory to be reused or shared with other factory users. Factory reuse and sharing can be particularly useful for factories that pool connections. The cost of initializing a pooling factory can be quite high compared to the cost of fetching a connection from an existing connection pool. In addition, sharing a pooling factory across a large number of users provides an opportunity to serve the users with a relatively small number of connections.

Connection factory managers facilitate reuse and sharing because, whenever a user tries to create a factory with a configuration that is equal to the configuration of an existing factory, the manager returns the existing factory instead of creating a new one. Of course, all factory users must have access to the same connection factory manager instance. The connection service provides a default connection manager that can be used for this purpose. The default manager is very convenient because a reference to it is stored in the static field ConnectionFactoryManager.defaultManager. However, it may facilitate broader sharing than you desire. You can always create your own connection factory manager and make it available only to certain factory users.

Despite the advantages of reusing and sharing a connection factory, care must always be taken to destory the factory when it is no longer needed. Otherwise, some potentially expensive resources may by tied up longer than necessary. Typically, that requires a call to shutdown() or destroy() (or both). There are some exceptions. If a connection factory encounters a fatal error, then the method executing at the time the fatal error is discovered will throw a FatalConnectionFactoryException, and the factory will destroy itself. Also, a factory created using an alternate configuration style may be able to destroy itself.

A good example of a situation where factory sharing works well is in a web application server. If several web applications running in the server require connections to the same IOM servers, it is often advantageous for all the web applications to share a single connection pooling factory. In this case, the shared factory could be created when the web application server starts up, and it would not be destroyed until the web application server terminates.

Alternate Configuration Styles

You may configure a connection factory using information stored in a metadata server. Doing so allows you to separate the task of developing a Java client program from the task of administering IOM servers.

Factory usage is not different for single servers, failover clusters, load balancing clusters, and connection pools. Furthermore, the factory will tell you what authentication domains are expected so you will not need to query the metadata server to find what authentication domains particular servers belong to.

JNDI

See Connection Factory Configuation using JNDI.

SAS Metadata Server

See Connection Factory Configuation using SAS Metadata Server.

SAS Foundation Services

See Connection Factory Configuation using SAS Foundation Services.


***  This package contains classes that provide Binary Compatibility only, not Source Compatibility  ***

Note:
Extension of the classes in this package is prohibited unless otherwise documented. Similarly, extension or implementation of the interfaces in this package is prohibited except as documented.


Copyright © 2009 SAS Institute Inc. All Rights Reserved.