11 Labeling Connections

This chapter provides information on how to label connections to increase performance:

This chapter includes the following sections:

What is Connection Labeling?

Applications often initialize connections retrieved from a connection pool before using the connection. The initialization varies and could include simple state re-initialization that requires method calls within the application code or database operations that require round trips over the network. The cost of such initialization may be significant.

Labeling connections allows an application to attach arbitrary name/value pairs to a connection. The application can request a connection with the desired label from the connection pool. By associating particular labels with particular connection states, an application can retrieve an already initialized connection from the pool and avoid the time and cost of re-initialization. The connection labeling feature does not impose any meaning on user-defined keys or values; the meaning of user-defined keys and values is defined solely by the application.

Some of the examples for connection labeling include role, NLS language settings, transaction isolation levels, stored procedure calls, or any other state initialization that is expensive and necessary on the connection before work can be executed by the resource.

Connection labeling is application-driven and requires the following:

Implementing Labeling Callbacks

A labeling callback is used to define how the connection pool selects labeled connections and allows the selected connection to be configured before returning it to an application. Applications that use the connection labeling feature must provide a callback implementation.

A labeling callback is used when a labeled connection is requested but there are no connections in the pool that match the requested labels. The callback determines which connection requires the least amount of work in order to be re-configured to match the requested label and then allows the connection's labels to be updated before returning the connection to the application.

Note:

Connection Labeling is not supported from client applications that use RMI. See "Using the WebLogic RMI Driver (Deprecated)" in Developing JDBC Applications for Oracle WebLogic Server.

Creating a Labeling Callback

To create a labeling callback, an application implements the oracle.ucp.ConnectionLabelingCallback interface. One callback is created per connection pool. The interface provides two methods as shown below:

public int cost(Properties requestedLabels, Properties currentLabels);

public boolean configure(Properties requestedLabels, Connection conn);

The connection pool iterates over each connection available in the pool. For each connection, it calls the cost method. The result of the cost method is an integer which represents an estimate of the cost required to reconfigure the connection to the required state. The larger the value, the costlier it is to reconfigure the connection. The connection pool always returns connections with the lowest cost value. The algorithm is as follows:

  • If the cost method returns 0 for a connection, the connection is a match (note that this does not guarantee that requestedLabels equals currentLabels). The connection pool does not call configure on the connection found and simply returns the connection.

  • If the cost method returns a value that is not 0 (a negative or positive integer), then the connection pool iterates until it finds a connection with a cost value of 0 or runs out of available connections.

  • If the pool has iterated through all available connections and the lowest cost of a connection is Integer.MAX_VALUE (2147483647 by default), then no connection in the pool is able to satisfy the connection request. The pool creates a new connection, calls the configure method on it, and then returns this new connection. If the pool has reached the maximum pool size (it cannot create a new connection), then the pool either throws an SQL exception or waits if the connection wait timeout attribute is specified.

  • If the pool has iterated through all available connections and the lowest cost of a connection is less than Integer.MAX_VALUE, then the configure method is called on the connection and the connection is returned. If multiple connections are less than Integer.MAX_VALUE, the connection with the lowest cost is returned.

There is also an extended callback interface oracle.ucp.jdbc.ConnectionLabelingCallback that has an additional getRequestedLabels() method. getRequestedLabels is invoked at getConnection() time when no requested labels are provided and there is an instance registered. This occurs when the standard java.sql.Datasource getConnection() methods are used that do not provide the label information on the getConnection() call.

Example Labeling Callback

The following code example demonstrates a simple labeling callback implementation that implements both the cost and configure methods. The callback is used to find a labeled connection that is initialized with a specific transaction isolation level.

Example 11-1 Labeling Callback

import oracle.ucp.jdbc.ConnectionLabelingCallback;  
import oracle.ucp.jdbc.LabelableConnection; 
import java.util.Properties; 
import java.util.Map; 
import java.util.Set;
import weblogic.jdbc.extensions.WLDataSource;
class MyConnectionLabelingCallback implements ConnectionLabelingCallback {
 
  public MyConnectionLabelingCallback()  { 
  }
  public int cost(Properties reqLabels, Properties currentLabels)  { 
    // Case 1: exact match 
    if (reqLabels.equals(currentLabels)) { 
      System.out.println("## Exact match found!! ##"); 
      return 0; 
    }
 
   // Case 2: some labels match with no unmatched labels 
    String iso1 = (String) reqLabels.get("TRANSACTION_ISOLATION");
    String iso2 = (String) currentLabels.get("TRANSACTION_ISOLATION"); 
    boolean match = 
      (iso1 != null && iso2 != null && iso1.equalsIgnoreCase(iso2)); 
    Set rKeys = reqLabels.keySet(); 
    Set cKeys = currentLabels.keySet(); 
    if (match && rKeys.containsAll(cKeys)) { 
      System.out.println("## Partial match found!! ##"); 
      return 10;
 
    } 
    // No label matches to application's preference. 
    // Do not choose this connection. 
    System.out.println("## No match found!! ##"); 
    return Integer.MAX_VALUE; 
  }
 
 public boolean configure(Properties reqLabels, Object conn)  { 
    try { 
      String isoStr = (String) reqLabels.get("TRANSACTION_ISOLATION"); 
      ((Connection)conn).setTransactionIsolation(Integer.valueOf(isoStr)); 
      LabelableConnection lconn = (LabelableConnection) conn;
 
     // Find the unmatched labels on this connection 
      Properties unmatchedLabels = 
           lconn.getUnmatchedConnectionLabels(reqLabels); 
      // Apply each label <key,value> in unmatchedLabels to conn
 
     for (Map.Entry<Object, Object> label : unmatchedLabels.entrySet())  { 
        String key = (String) label.getKey(); 
        String value = (String) label.getValue();
 
        lconn.applyConnectionLabel(key, value);
 
      } 
    } catch (Exception exc) { 
      return false; 
    } 
    return true; 
  }
  
public java.util.Properties getRequestedLabels() {
    Properties props = new Properties();
  
 // Set based on some application state that might be on a thread-local, http session info, etc.
    String value = "value"; 
 
  
  props.put("TRANSACTION_ISOLATION", value);
  
  return props;
  } 
}

Registering a Labeling Callback

A WebLogic Server data source provides the registerConnectionLabelingCallback(ConnectionLabelingCallback callback) method for registering labeling callbacks. Only one callback may be registered on a connection pool. The following code example demonstrates registering a labeling callback that is implemented in the MyConnectionLabelingCallback class:

. . .
import weblogic.jdbc.extensions.WLDataSource;
. . . 
MyConnectionLabelingCallback callback = new MyConnectionLabelingCallback(); 
((WLDataSource)ds).registerConnectionLabelingCallback( callback );
. . .

You can also register the callback using the WebLogic Server Administration Console, see "Configure a connection labeling callback class" in Oracle WebLogic Server Administration Console Online Help.

Removing a Labeling Callback

You can remove a labeling callback by using one of the following methods:

  • If you have programmatically set a callback, use the removeConnectionLabelingCallback() method as shown in the following example:

    . . .
    import weblogic.jdbc.extensions.WLDataSource; 
    . . .
    ((WLDataSource)ds).removeConnectionLabelingCallback( callback );
    . . .
    
  • If you have administratively configured the callback, remove the callback from the data source configuration. See "Configure a connection labeling callback class" in Oracle WebLogic Server Administration Console Online Help

Note:

An application must use one of the methods to register and remove callbacks but not both. For example, if you register the callback on a connection using registerConnectionLabelingCallback(callback), you must use removeConnectionLabelingCallback() to remove it.

Applying Connection Labels

Labels are applied on a reserved connection using the applyConnectionLabel method from the LabelableConnection interface. Any number of connection labels may be cumulatively applied on a reserved connection. Each time a label is applied to a connection, the supplied key/value pair is added to the existing collection of labels. Only the last applied value is retained for any given key.

Note:

A labeling callback must be registered on the connection pool before a label can be applied on a reserved connection; otherwise, labeling is ignored. See Creating a Labeling Callback.

The following example demonstrates initializing a connection with a transaction isolation level and then applying a label to the connection:

. . .
String pname = "property1"; 
String pvalue = "value"; 
Connection conn = ds.getConnection(); 
// initialize the connection as required. 
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); 
((LabelableConnection) conn).applyConnectionLabel(pname, pvalue);
. . .

Reserving Labeled Connections

A WebLogic Server data source provides two getConnection methods that are used to reserve a labeled connection from the pool. The methods are shown below:

public Connection getConnection(java.util.Properties labels) throws SQLException;

public Connection getConnection(String user, String password, java.util.Properties labels) throws SQLException;

The methods require that the label be passed to the getConnection method as a Properties object. The following example demonstrates getting a connection with the label property1 value.

. . .
import weblogic.jdbc.extensions.WLDataSource;
. . . 
String pname = "property1"; 
String pvalue = "value"; 
Properties label = new Properties(); 
label.setProperty(pname, pvalue);
. . . 
Connection conn = ((WLDataSource)ds).getConnection(label);
. . .

It is also possible to use the standard java.sql.Datasource getConnection() methods. In this case, the label information is not provided on the getConnection() call. The interface oracle.ucp.jdbc.ConnectionLabelingCallback is used:

java.util.Properties getRequestedLabels();

getRequestedLabels is invoked at getConnection() time when no requested labels are provided and there is an instance registered.

Checking Unmatched labels

A connection may have multiple labels that each uniquely identifies the connection based on some desired criteria. The getUnmatchedConnectionLabels method is used to verify which connection labels matched from the requested labels and which did not. The method is used after a connection with multiple labels is reserved from the connection pool and is typically used by a labeling callback. The following code example demonstrates checking for unmatched labels:

. . .
String pname = "property1"; 
String pvalue = "value"; 
Properties label = new Properties(); 
label.setProperty(pname, pvalue);
. . . 
Connecion conn = ((WLDataSource)ds).getConnection(label); 
Properties unmatched =  
   ((LabelableConnection)connection).getUnmatchedConnectionLabels (label); 
. . .

Removing a Connection Label

The removeConnectionLabel method is used to remove a label from a connection. This method is used after a labeled connection is reserved from the connection pool. The following code example demonstrates removing a connection label:

. . .
String pname = "property1"; 
String pvalue = "value"; 
Properties label = new Properties(); 
label.setProperty(pname, pvalue); 
Connection conn = ((WLDataSource)ds).getConnection(label);
. . . 
((LabelableConnection) conn).removeConnectionLabel(pname);
. . .

Using Initialization and Reinitialization Costs to Select Connections

Some applications require that a connection pool to be able to identify high-cost connections and avoid using those connections to serve requests when the number of connections is below a certain threshold. This allows a pool to use brand-new physical connections to serve connection requests from different tenants without incurring re-initialization overhead on other tenant connections already in the pool.

WebLogic Server provides the following connection properties to identify high cost connections:

  • ConnectionLabelingHighCost—When greater than 0, connections with a cost value equal to or greater than the property value are considered high-cost connections. The default value is Integer.MAX_VALUE.

    For example, if the property value is set to 5, any connection whose calculated cost value from the labeling callback is equal to or greater than 5 is considered a high-cost connection.

  • HighCostConnectionReuseThreshold—When greater than 0, specifies a threshold of the number of total connections in the pool beyond which Connection Labeling is allowed to reuse high-cost connections in the pool to serve a request. Below this threshold, Connection Labeling either uses an available low-cost connection or creates a brand-new physical connection to serve a request. The default value is 0.

    For example, if set to 20, Connection Labeling reuses high-cost connections when there are no low-cost connections available and the total connections reach 20.

For more information on configuring configuration properties:

Considerations When Using Initialization and Reinitialization Costs

This section provides additional considerations when selecting connections based on connection costs:

  • Valid callback registration activates Connection Labeling. Once registered, the connection pool checks for new threshold values at regular intervals and determines:

    • if a connection has a cost that is equal to or greater than ConnectionLabelingHighCost.

    • If the number of total connections accounts for the number of active connection creation requests, including restrictions for MinCapacity and MaxCapacity.

  • Any labeled connection with cost value of Integer.MAX_VALUE is not reused, even if a new threshold is reached.

  • There is no requirement not to reuse connections without labels (stateless) in the pool to serve connection requests with labels (labeled requests). Once the HighCostConnectionReuseThreshold is reached and Connection Labeling is activated, the pool continues to favor connections without labels (stateless) over creating new physical connections.

Using Connection Labeling with Packaged Applications

WebLogic Server allows callbacks, such as labeling and connection initialization, in EAR or WAR files used by a packaged application.

To define an application-packaged callback class in a data source configuration:

  • Define the data source as part of the application.

    For example, if the callback implementation classes are packaged in a WAR or defined as part of a shared library that is referenced by the application, the EAR file contains application packaged data source configurations that reference the callback class names in their module descriptors.

  • Specify the application WAR file (that contains the callback implementations) as part of the application classloader hierarchy in the weblogic-application.xml file.

    For example:

    . . .
    <classloader-structure>
      <module-ref>
        <module-uri>appcallbacks.war</module-uri>
      </module-ref>
    </classloader-structure>
    

Considerations When using Labelled Connections in Packaged Applications

WebLogic Server does not support specifying a connection labeling callback or connection initialization callback in the module descriptor for a globally scoped data source system resource when the callback class is packaged in an application. A global data source requires that callback implementation classes be on the WebLogic classpath. However, you can workaround this restriction for an application callback that is packaged in a WAR or EAR by having the application register the callback at runtime using the WLDataSource interface in the Java API Reference for Oracle WebLogic Server.