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
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:
- Create a factory configuration
- Create a connection factory manager
- Create a factory with the desired configuration
- Create a connection
- Narrow and use the connection
- Destroy the connection
- Destroy the factory
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:
- Logging
- Encryption
- Failover
- Load Balancing
- Connection Pooling
- Connection Factory Sharing
- Alternate Configuration Styles
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 callingConnectionFactoryManager.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);
|
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.-
ClassDescriptionA description of an IOM bridge protocol server.A base class representing a cluster of IOM servers.The administrator's interface to a connection factory.The base class for all connection factory configurations.A class used to notify factory users of important events such as factory shutdown.An interface implemented by factory users who want to be notified of important events such as factory shutdown.The base class for all connection service exceptions.User interface for connection factories.A factory of connection factories.Methods common to all connection factory interfaces.The factory-managed connection handle.Information about the connection.The connection factory throws a timeout exception when a connection request could not be completed before an administrative time limit expired.A base class for credentials that can be used to authenticate and authorize use of a connection factory.Base class for exceptions thrown to indicate that something is wrong with credentials presented during a connection request.A failover cluster of IOM servers.A exception that is so severe that a factory which throws this exception can no longer be used.Encapsulates the host and port information for a single server instance.Wraps multiple
HostPortPairinstances into one object.A load balancing cluster of IOM servers.The connection factory throws a login exception when a connection request cannot be granted because the connecting client cannot be authenticated or authorized.A connection factory configuration in which the servers, clusters, and puddles that the factory is to connect to are explicitly described.Utility class to create SAS metadata server cluster definitions.Login credentials for an IOM server.A description of a puddle of IOM clusters.A credential to use when requesting a security-package-authenticated connection to a server.A base class for describing IOM servers.A base class to describe IOM servers that communicate with clients using a TCP/IP application protocol.A credential to use when requesting a trusted peer connection to a server.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.Converts XML configuration files produced by the Integration Technologies Configuration tool (ITConfig) into aManualConnectionFactoryConfigurationobject.A server that IOM Bridge for Java will start and connect to.