GRC
HR
SCM
CRM
BI


Article

 

Advanced JCo Connection Pool Management

by Thomas G. Schuessler | SAPinsider

April 1, 2003

by Thomas G. Schuessler, ARAsoft SAPinsider - 2003 (Volume 4), April (Issue 2)
 



Thomas G. Schuessler,
ARAsoft

If you have already written an application with the SAP Java Connector (JCo), you will probably have used connection pools. In earlier versions of JCo, these pools had a fixed size and could not grow, so it was very important to set the size appropriately to avoid wait situations and exceptions due to insufficient connections being available. Since then, JCo has become more sophisticated in its pool management (you should be using at least JCo 2.0.7 now), and I would like to introduce you to the new possibilities.

Listen for Change
First I would like to discuss the PoolChangedListener that JCo offers (and has offered from the beginning). If you implement it in your application, the listener will be called whenever a change occurs to a pool. Listing 1 shows you the pertinent parts of the source code:

  • The class that will be the listener needs to implement interface JCO.PoolChangedListener. This implies that method poolChanged() exists. This method will be called whenever a change occurs to a pool.

  • Some part of your application — but not necessarily the same class that acts as the listener — must register the listener using method addPoolChangedListener().

The listener is usually used to collect data about pool utilization. Based on that data, you can then adjust the pool properties appropriately.

 
import com.sap.mw.jco.*;

public class ClassName implements JCO.PoolChangedListener {

  JCO.getClientPoolManager().addPoolChangedListener(this);
  
  public void poolChanged(com.sap.mw.jco.JCO.Pool pool) {
  
  // Do something useful here
  
  }
  
} 
Listing 1 Skeleton Code for Using a PoolChangedListener

Relevant Pool Properties
To be able to exploit the information available for a pool to maximum benefit, you have to understand the meaning of the various properties available for a JCO.Pool object.

The way JCo handles the pool has changed considerably from earlier versions. Originally, a pool contained only an internal array with a fixed maximum size. The size of this array is set when the pool is created, and is represented by property MaxPoolSize.

Nowadays, there is a second property, MaxConnections, that must be larger than or equal to MaxPoolSize. When the pool is created, MaxConnections and MaxPoolSize are set to the same value. If MaxConnections is larger, then additional connections can be created by calls to getClient(). JCo treats these additional connections differently when they are released back to the pool. While a connection in the internal array is kept open for a while (see property ConnectionTimeout), additional connections are closed as soon as they are released.

With this background, you should now be able to understand the descriptions of the relevant properties in Figure 1. Figure 2 contains the Set/Get methods for the properties shown in Figure 1.

Property Description
MaxConnections Maximum number of connections that can be allocated from the pool via method getClient(). The initial value for this property is set when the pool is created by a call to JCO.addClientPool().
MaxPoolSize Maximum number of connections kept in an internal array and kept open after they have been released. MaxPoolSize must be <= MaxConnections. Initially, the two properties are set to the same value. (The name for this property should really be something like MaxInternalArraySize, but this property existed before MaxConnections, and the name had to be kept for compatibility reasons.)
CurrentPoolSize Number of currently active (open) connections, i.e., connections logged on to an SAP Application Server.
NumUsed Number of connections currently in use, i.e., acquired by a call to getClient().
MaxUsed Maximum number of connections in use at the same time from the point when the pool was created, i.e., the high-water mark for NumUsed.
MaxWaitTime If all connections in the pool are currently in use (i.e., MaxConnections has been reached) and a new getClient() is issued, then the pool manager will wait for up to this value for a connection to become available (by another thread releasing it). If after this period still no connection has become available, an exception of type JCO.Exception with its group set to JCO.Exception.JCO_ ERROR_RESOURCE will be thrown. The maximum wait time is specified in milliseconds; the default value is 30 seconds.
ConnectionTimeout This applies only to open connections that are in the internal array of the pool and not currently in use. If a connection has not been requested by anybody for this time, this connection will be closed by JCo, thus reducing the number of open connections. Connection timeout is specified in milliseconds; the default value is 10 minutes.
TimeoutCheckPeriod This is the interval after which JCo checks for connections to be closed according to the ConnectionTimeout property. The timeout check period is specified in milliseconds; the default value is 1 minute.
Figure 1 Relevant Properties of JCO.Pool

Property Get Method Set Method
MaxConnections int getMaxConnections() void setMaxConnections(int max_connections)
MaxPoolSize int getMaxPoolSize() void setMaxPoolSize(int max_pool_size)
CurrentPoolSize int getCurrentPoolSize() N/A
NumUsed int getNumUsed() N/A
MaxUsed int getMaxUsed() N/A
MaxWaitTime long getMaxWaitTime() void setMaxWaitTime(long max_wait_time)
ConnectionTimeout long getConnectionTimeout() void setConnectionTimeout(long connection_timeout)
TimeoutCheckPeriod long getTimeoutCheckPeriod() void setTimeoutCheckPeriod(long timeout_check_period)
Figure 2 Get/Set Methods for the Properties in Figure 1

 

Optimal Values for MaxConnections and MaxPoolSize
How should you use properties MaxConnections and MaxPoolSize in your application(s)? The benefit of including a connection in the internal array is that when the next thread needs a connection, JCo will not have to open a new connection to SAP (a relatively expensive process); instead it reuses an existing open connection not currently in use. The downside is that each open connection requires resources in the SAP Gateway and the SAP Application Server. Hence, my recommendation is to set MaxPoolSize to a value large enough that, under a typical workload, no additional connections are required.

MaxConnections should be big enough to accommodate peak activity periods, but not so big that it creates problems with the SAP Gateway. Finding the optimum values for these two properties for your own application(s) will take a little bit of effort. Using a PoolChangedListener, you can collect the data you need to determine your adjustments to these properties.

A Sample Program
Listing 2 contains a simple test program that tries to open and use 10 connections. MaxConnections is set to 20, while MaxPoolSize is a relatively modest 5. The assumption behind these values would be that during most of the day there will be no requirement for more than 5 connections and peak activity will not require more than 20.


import com.sap.mw.jco.*;

public class PoolSizeDemo implements JCO.PoolChangedListener {

static final String POOL_NAME = "ARAsoft";

static final int maxTest = 10;
JCO.Client[] mConnections = new JCO.Client[maxTest];

  public PoolSizeDemo() {
    JCO.Pool pool = null;
    try {
      OrderedProperties logonProperties =
        OrderedProperties.load("/logon.properties");

      JCO.addClientPool(POOL_NAME,
			    5,
                      logonProperties);
      pool = JCO.getClientPoolManager().getPool(POOL_NAME);
      pool.setMaxConnections(20);

      JCO.getClientPoolManager().addPoolChangedListener(this);

      for (int i = 0; i < mConnections.length; i++) {
        mConnections[i] = JCO.getClient(POOL_NAME);
        System.out.println("<<< Using connection " +
                         String.valueOf(i+1) + ": " +
                         mConnections[i].getAttributes()
                                       .getPartnerRelease());
      }
    }
    catch (Exception ex) {
      ex.printStackTrace();
    }
    finally {
      for (int i = 0; i < mConnections.length; i++) {
        JCO.releaseClient(mConnections[i]);
      }
    }
  }

  public void poolChanged(com.sap.mw.jco.JCO.Pool pool) {
    System.out.println(getPoolInfo(pool));
  }

  private String getPoolInfo(com.sap.mw.jco.JCO.Pool pool) {
    return "Information for connection pool:\t" +
             pool.getName() + "\n" +
           "   Maximum number of connections:\t" +
             pool.getMaxConnections() + "\n" +
           "   Max. number of pooled connections:\t" +
             pool.getMaxPoolSize() + "\n" +
           "   Number of active (open) connections:\t" +
             pool.getCurrentPoolSize() + "\n" +
           "   No. of connections currently in use:\t" +
             pool.getNumUsed() + "\n" +
           "   Max. number of connections in use:\t" +
             pool.getMaxUsed();
  }

  public static void main(String[] args) {
    PoolSizeDemo app = new PoolSizeDemo();
  }
}
Listing 2 Source Code of Program PoolSizeDemo

In this sample program, all the PoolChangedListener does is print out information about the relevant pool properties. You can easily enhance this to write records to some log file instead, and use this data to fine tune the MaxPoolSize for your applications.

Figure 3 shows you some of the output from running the test program.

Figure 3 Partial Output of Program PoolSizeDemo

Conclusion

The new pool management capabilities in JCo allow you to use resources on the SAP Gateway and SAP Application Server more efficiently than before. Make sure that you take advantage of the new MaxConnections property and use a PoolChangedListener to gather data that enables you to find optimal values for MaxConnections and MaxPoolSize.


Thomas G. Schuessler is the founder of ARAsoft (www.arasoft.de), a company offering products, consulting, custom development, and training to a worldwide base of customers. The company specializes in integration between SAP and non-SAP components and applications. ARAsoft offers various products for BAPI-enabled programs on the Windows and Java platforms. These products facilitate the development of desktop and Internet applications that communicate with R/3. Thomas is the author of SAP’s BIT525 “Developing BAPI-enabled Web Applications with Visual Basic” and BIT526 “Developing BAPI-enabled Web Applications with Java” classes, which he teaches in Germany and in English-speaking countries. Thomas is a regularly featured speaker at SAP TechEd and SAPPHIRE conferences. Prior to founding ARAsoft in 1993, he worked with SAP AG and SAP America for seven years. Thomas can be contacted at thomas.schuessler@sap.com or at tgs@arasoft.de.

An email has been sent to:






More from SAPinsider



COMMENTS

Please log in to post a comment.

No comments have been submitted on this article. Be the first to comment!


SAPinsider
FAQ