13 Labeling Connections

Label connections increase the performance of database connections. 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.

This chapter provides information on how to use label connections with WebLogic JDBC. The 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. 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

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. Learn how to create a labeling callback by implementing the oracle.ucp.ConnectionLabelingCallback interface.

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 13-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.

See, the registerConnectionLabelingCallback(ConnectionLabelingCallback callback) method for registering labeling callbacks. 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

WebLogic JDBC data sources provide two getConnection methods that are used for reserving a labeled connection from the pool.

The syntax of the two methods is:
  • public Connection getConnection(java.util.Properties labels)

  • public Connection getConnection(String user, String password, java.util.Properties labels)

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

Connections may have multiple labels, which each uniquely identify the connection based on specified criteria. Use the getUnmatchedConnectionLabels method to verify which connections do not match the requested label.

This method is used after a connection with multiple labels is reserved from the connection pool and is typically used by a labeling callback. SeegetUnmatchedConnectionLabels method.

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

You can remove a connection label by using the removeConnectionLabel method.

This method is used after a labeled connection is reserved from the connection pool. See removeConnectionLabel.

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 be able to identify high-cost connections and avoid using those connections when the number of connections is below a certain threshold. Using that information allows a connection pool to use new physical connections to serve connection requests from different tenants without incurring reinitialization 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.

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 connnection 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 connection 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 datasource 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 datasource 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 datasource system resource when the callback class is packaged in an application. A global datasource 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.