Link to home
Start Free TrialLog in
Avatar of xoxomos
xoxomos

asked on

Code to change connection pooling

I've got this servlet from a WAS3.5 application using connection pooling.  WAS4.0 no longer supports com.ibm.servlet.connmgr.  I'd like to see the equivalent of this coded for WAS 4.0 preferably with Oracle connection pooling, but IBM is ok.  IBM has  a .pdf file at
http://www-3.ibm.com/software/webservers/appserv/whitepapers/connection_pool.pdf
and Oracle has it's at
http://technet.oracle.com/docs/products/oracle8i/doc_library/817_doc/java.817/a83724/connpoc2.htm

import java.io.*;
import java.util.*;
import com.ibm.eNetwork.ECL.*;
import com.objectspace.jgl.*;


/*
 * CSUHIBMConnectionBroker -- A broker for IBM 3270 connections.
 *
 * Creates and manages a pool of 3270 connections.
 *
 * At init time the max number of 3270 connections are established
 * along with timeout limits for age and idleness.
 *
 * Every five minutes the connections are validated.  As connections
 * exceed the maximum idle time they are removed from the connection
 * pool.  As connections exceed the maximum age they are disconnected
 * and restarted.
 *
 */


public class CSUHIBMConnectionBroker implements Observer, Runnable,
  CSUHIBMConstants
{
  private static final int MAX_NUMBER_OF_CONNECT_ATTEMPTS = 5;
  private static final int TIME_TO_WAIT_AFTER_INIT_FAILS = 10000;
  private static final int MILLISECONDS_TO_WAIT_IF_ALL_CONNECTIONS_ARE_BUSY = 600;

  private static final String className = "CSUHIBMConnectionBroker";
 
  private int connsInUse;               //
  private int minConns;                 // the minimum number of connections that are allowed
  private int maxConns;                 // the maximum number of connections that are allowed
  private long maxConnAge;              // the maximum age that a connection can reach
  private long maxConnIdleTime;         // the maximum time that a connection can be idle
  private long checkConnTime;           // elapsed time before the connections are checked by the housekeeping thread
  private long timeOutValue;            //

  private Properties connectionProperties;    // property object for the CSUHMainframe objects
  private MainframeQueue closedQueue;         //
  private MainframeQueue availableQueue;      //
 
  private CSUHAlarm timer;                      // the CSUHAlarm used to shut off and start registration
  private Thread runner;                        // the housekeeping thread
  private String userName;                      // the user name for the mainframe account
  private String passWord;                      // the password for the mainframe account
  private boolean regStatus;                    //
  private boolean forever;                      //

  // Matt: added these next two lines 03082001 for using the new csuh.properties file
  // see init() method below
  private static Properties config = new Properties();
  private static File configfile = new File("/ws/csuhcode/csuh.properties");

  private static String selectEnvironment;            
  private static String debug;            
  private static String currentTerm;            
  private static String useFakeMainframe;            
  private static String lookupOnly;            

  private static CSUHIBMConnectionBroker onlyInstance = null;

  private CSUHIBMConnectionBroker()
  {
    init();
  }


  public static CSUHIBMConnectionBroker instance()
  {
    if (onlyInstance == null)
      onlyInstance = new CSUHIBMConnectionBroker();

    return onlyInstance;
  }


  public void init()
  {
 
    System.out.print("Loading " + className + "...");

    maxConns = 15;
    minConns = 5;
    maxConnAge = (350 * 60 * 1000);
    maxConnIdleTime = (30 * 60 * 1000);
    checkConnTime = (15 * 60 * 1000);
    timeOutValue = (60 * 1000);

    try    
    { config.load(new FileInputStream(configfile)); }
    catch (Exception e)
    { System.err.println("CSUHIBMConnectionBroker: cannot read csuh.properties: " + e); }

    if(config.getProperty("environment").equalsIgnoreCase("test"))
    { selectEnvironment = "m"; }  // HAYWDTST
    else
    { selectEnvironment = "l"; }  // HAYWDPRD
   
    if(config.getProperty("debug").equalsIgnoreCase("yes"))
    { debug = "yes"; }
    else
    { debug = "no"; }
   
    if(config.getProperty("fakeMainframe").equalsIgnoreCase("yes"))
    {
      useFakeMainframe = "yes";
      System.out.println("Using fake mainframe responses.");
    }
    else
    { useFakeMainframe = "no"; }

    if(config.getProperty("lookup_only").equalsIgnoreCase("yes"))
    {
      lookupOnly = "yes";
      System.out.println("Starting in lookup-only mode.");
    }
    else
    { lookupOnly = "no"; }
   
   
    currentTerm = config.getProperty("myinfoterm");

    userName = config.getProperty("ztlkuser");
    passWord = config.getProperty("ztlkpass");
   
    availableQueue = new MainframeQueue();
    closedQueue = new MainframeQueue();

    regStatus  = false;
    forever = false;

    connectionProperties = new Properties();
    connectionProperties.put(ECLSession.SESSION_HOST, "sail.csuhayward.edu");
    connectionProperties.put(ECLSession.SESSION_HOST_PORT, "23");
    connectionProperties.put(ECLSession.SESSION_TYPE, ECLSession.SESSION_TYPE_3270_STR);
    connectionProperties.put(ECLSession.SESSION_AUTOCONNECT, ECLSession.SESSION_OFF);
    connectionProperties.put(ECLSession.SESSION_AUTORECONNECT, ECLSession.SESSION_OFF);

    if (runner == null)
    {
      runner = new Thread(this);
      runner.start();             // matt: run() method now starts
      timer = new CSUHAlarm(this);
    }

    System.out.println(className + " loaded.");
  }



  public void run()
  {
    long age;
    long idleTime;
    boolean closeConnection;
    boolean restartConnection;
    CSUHMainframe ibmMainframe;


    //switch (checkCurrentTime())
    switch (1)
    {    // 1 = ON here
   
      case OFF:
        regStatus = false;
        forever = false;
        break;
   
      case ON:
        if (bringUpAllConnections() == true)
        {
          regStatus = true;
          forever = true;
        }
        else
        {
          regStatus = false;
          forever = false;
        }
        break;
   
      case WAIT_TO_RUN:
        if (bringUpAllConnections() == true)
        {
          try
          {
            Thread.sleep(syncTime());
          }
          catch (InterruptedException ie) { }
          regStatus = true;
          forever = true;
        }
        else
        {
          regStatus = false;
          forever = false;
        }
        break;
    }


    while (forever)
    {

      try
      { Thread.sleep(checkConnTime); }
      catch (InterruptedException ie) { }

      for (int i = availableQueue.size(); (regStatus == true) && (i > 0); i--)
      {
        closeConnection = false;
        restartConnection = false;
       
        try
        { ibmMainframe = availableQueue.pop(); }
        catch (InvalidOperationException invalidOp)
        { break; }

        age = System.currentTimeMillis() - ibmMainframe.getCreateDate();
        idleTime = System.currentTimeMillis() - ibmMainframe.getLastUsedDate();        

        if (age > maxConnAge)
        { restartConnection = true; }

        if ((restartConnection == false) && (idleTime > maxConnIdleTime))
        {
          if (availableQueue.size() > minConns)
          { closeConnection = true; }
        }

        if ((closeConnection == false) && (restartConnection == false))
        {
          if (ibmMainframe.checkConnection() == true)
          { availableQueue.push(ibmMainframe); }
          else
          { closeConnection = true; }
        }
       
        if ((closeConnection == true) || (restartConnection == true))
        {
          try
          { ibmMainframe.logoff(); }
          catch (ECLErr ibmError) { }
          catch (CSUHMainframeException mainframeError) { }

          closeConn(ibmMainframe);

          if (restartConnection == true)
          {
            for (int j = 0; j < MAX_NUMBER_OF_CONNECT_ATTEMPTS; j++)
            {
              try
              {
                ibmMainframe = closedQueue.pop();
                openExistingConn(ibmMainframe);
                availableQueue.push(ibmMainframe);
                break;
              }
              catch(Exception e)
              {
                try
                {
                  Thread.sleep(TIME_TO_WAIT_AFTER_INIT_FAILS);
                }
                catch(InterruptedException ie) { }
              }
            }    
          }
        }
      }
    } // end of while loop
  } // end of run
 

  public CSUHMainframe getConnection() throws CSUHIBMBrokerException
  {
    boolean gotAConn = false;
    CSUHMainframe ibmMainframe = null;


    for (int i = 0; (gotAConn == false) && (i < MAX_NUMBER_OF_CONNECT_ATTEMPTS); i++)
    {

      try
      {
         ibmMainframe = availableQueue.pop();
         gotAConn = true;
      }
      catch (InvalidOperationException invalidOp) { }
 
      if ((gotAConn == false) && (closedQueue.isEmpty() == false))
      {
        try
        {
          ibmMainframe = closedQueue.pop();
          openExistingConn(ibmMainframe);
          gotAConn = true;
        }
        catch (InvalidOperationException invalidOp) { }
        catch (ECLErr ibmError) { }
        catch (CSUHMainframeException mainframeError) {closeConn(ibmMainframe);}
      }

      if ((gotAConn == true) && (ibmMainframe.checkConnection() == true))
      {
        ibmMainframe.setLastUsedDate(System.currentTimeMillis());
        incrementConnsInUse();
        incrementConnsInUse();
      }
      else
      {
        if (ibmMainframe != null)
        {
          closeConn(ibmMainframe);
          gotAConn = false;
        }
        try
        {
          Thread.sleep(MILLISECONDS_TO_WAIT_IF_ALL_CONNECTIONS_ARE_BUSY);
        }
        catch(InterruptedException ie) { }
      }
    }
 

    if (gotAConn == false)
    {
      throw new CSUHIBMBrokerException("All of the connections to the mainframe are currently in use.");
    }
    return ibmMainframe;
 
  } // end of getConnection


  public void freeConnection(CSUHMainframe ibmMainframe)
  {

    try
    {
      ibmMainframe.sendString(CLEAR_KEY);

      if (ibmMainframe.checkConnection() == true)
      {
        availableQueue.push(ibmMainframe);
      }
      else
      {
        throw new CSUHIBMBrokerException("checkConnection reported a faulty connection.");
      }
    }
    catch(Exception e)
    {
      closeConn(ibmMainframe); { }
    }
  } // end of freeConnection


  public boolean getRegistrationStatus()
  {
    return regStatus;
  }


  public void destroy()
  {

    timer.stopCSUHAlarm();

    regStatus = false;
    forever = false;
    if (runner.isAlive() == true)  // matt: returns true if thread started, and run() still going
    {
      try
      {
        runner.interrupt();
        runner.join(30000);
      }
      catch(InterruptedException ie) { }
    }

    closeDownAllConnections();
 
  } // end of destroy
 

  public void update(Observable obj, Object arg)
  {

    switch (((Integer)arg).intValue())
    {
      case OFF:
        regStatus = false;
        forever = false;
        if (runner.isAlive() == true)
        {
          try
          {
            runner.interrupt();
            runner.join();
          }
          catch(InterruptedException ie) { }
        }
        closeDownAllConnections();
        break;
      case ON:
        if (runner.isAlive() == false)
        {
          runner = new Thread(this);
          runner.start();
        }
        break;
    }
  }  


  // Matt: added 03071002 for a better OO way
  public static String getMainframeEnvironment()
  {
    if(selectEnvironment.equalsIgnoreCase("m"))
      { return "test"; }
    else { return "prod"; }
  }

  public static boolean getDebugSetting()
  {
    if(debug.equalsIgnoreCase("yes"))
      { return true; }
    else { return false; }
  }

  public static boolean getFakeMainframeSetting()
  {
    if(useFakeMainframe.equalsIgnoreCase("yes"))
      { return true; }
    else { return false; }
  }

  public static boolean getLookupSetting()
  {
    if(lookupOnly.equalsIgnoreCase("yes"))
      { return true; }
    else { return false; }
  }


  public static String getTerm()
  { return currentTerm; }

  private void closeDownAllConnections()
  {
    CSUHMainframe ibmMainframe = null;

    while (availableQueue.isEmpty() == false)
    {
      try
      {
        ibmMainframe = availableQueue.pop();
        ibmMainframe.logoff();
        closeConn(ibmMainframe);
      }
      catch (InvalidOperationException invalidOp) { }
      catch (ECLErr e) { }
      catch (CSUHMainframeException mainframeError) { }
    }
  }


  private boolean bringUpAllConnections()
  {
    long beginTime = System.currentTimeMillis();
    boolean connected = false;
    boolean sentinel = false;

    closedQueue.clear();
    availableQueue.clear();

    for (int i = 0; i < maxConns; connected = false, i++)
    {
      for (int j = 0; (connected == false) && (j < MAX_NUMBER_OF_CONNECT_ATTEMPTS); j++)
      {
        try
        {
          availableQueue.push(openNewConn(Integer.toString(i)));
          connected = true;
          sentinel = true;
        }
        catch(Exception e)
        {
          try
          {
            Thread.sleep(TIME_TO_WAIT_AFTER_INIT_FAILS);
          }
          catch(InterruptedException ie) { }
        }
      }
    }

    return sentinel;
  }


  private void closeConn(CSUHMainframe ibmMainframe)
  {
    ibmMainframe.closeConnection();
    closedQueue.push(ibmMainframe);
  } // end of closeConn


  private void openExistingConn(CSUHMainframe ibmMainframe) throws CSUHMainframeException, ECLErr
  {
    long beginTime = System.currentTimeMillis();

    ibmMainframe.refreshConnection(connectionProperties);
    ibmMainframe.startCommunication();
    ibmMainframe.login(userName, passWord, selectEnvironment);

    if (ibmMainframe.checkConnection() == true)
    {
      ibmMainframe.setLastUsedDate(System.currentTimeMillis());
      ibmMainframe.setCreateDate(System.currentTimeMillis());
    }
    else
    {
      throw new CSUHMainframeException("checkConnection reported a faulty connection.");
    }
  }


  private CSUHMainframe openNewConn(String id) throws CSUHMainframeException, ECLErr
  {
    CSUHMainframe ibmMainframe;
    long beginTime = System.currentTimeMillis();

    ibmMainframe = new CSUHMainframe(connectionProperties, timeOutValue, id);
    ibmMainframe.startCommunication();
    ibmMainframe.login(userName, passWord, selectEnvironment);

    if (ibmMainframe.checkConnection() == true)
    {
      ibmMainframe.setLastUsedDate(System.currentTimeMillis());
      ibmMainframe.setCreateDate(System.currentTimeMillis());
    }
    else
    {
      throw new CSUHMainframeException("checkConnection reported a faulty connection.");
    }
    return ibmMainframe;
  }


  private int checkCurrentTime()
  {
    GregorianCalendar myCal = new GregorianCalendar();
    long hour = myCal.get(myCal.HOUR_OF_DAY);
    long minute = myCal.get(myCal.MINUTE);
    long second = myCal.get(myCal.SECOND);
    long dayOfWeek = myCal.get(myCal.DAY_OF_WEEK);
   
    if ((dayOfWeek > 1) && (dayOfWeek <= 7)) // 1=Sunday, 7=Saturday
    {
      if ((hour > 6) && (hour < 19)) // 7 AM - 6:59 PM
      {
        return ON;
      }
      else if (hour == 6) // 6 AM - 6:59 AM
      {
        return WAIT_TO_RUN;
      }
      else
      {
        return OFF;
      }
    }
    else
    {
      return OFF;
    }
  }


  private long syncTime()
  {
    GregorianCalendar myCal = new GregorianCalendar();
    return ((60 - myCal.get(myCal.MINUTE)) * 60 * 1000) - (myCal.get(myCal.SECOND) * 1000);
  }
 
 
  private synchronized int incrementConnsInUse()
  {
    return connsInUse++;
  }


  private synchronized int decrementConnsInUse()
  {
    return connsInUse--;
  }


  private int totalConns()
  {
    return availableQueue.size() + closedQueue.size() + connsInUse;
  }




  class MainframeQueue
  {
 
    private Queue baseQueue;

    MainframeQueue()
    {
      baseQueue = new Queue(new Deque());
    }
   
    void push(CSUHMainframe ibmMainframe)
    {
      baseQueue.push(ibmMainframe);
    }
   
    CSUHMainframe pop()
    {
      return (CSUHMainframe) baseQueue.pop();
    }
   
    boolean isEmpty()
    {
      return baseQueue.isEmpty();
    }
   
    int size()
    {
      return baseQueue.size();
    }
   
    void clear()
    {
      baseQueue.clear();
    }
  }
} // end of CSUHIBMConnectionBroker
Avatar of Mick Barry
Mick Barry
Flag of Australia image

That code doesn't really do any handling of connection pooling, it simply returns a IBMConnMgr instance for getting connections.
What exactly is it you want?

Avatar of xoxomos
xoxomos

ASKER

You're right.  I think this is the pooling code.  I want to see what code would look like using Oracle connection pooling.  Doesn't have to be completely working, just what direction coding changes should take.
Avatar of xoxomos

ASKER

What's happening is, I have a bunch of servlets running under Websphere 3 that i attempted to run under Websphere 4.  Eventually i came across the documentation that the com.ibm.servlet package from Visual Age 4 that is deprecated in 3 is no longer supported in 4.  I'm looking at the Oracle and IBM sites that dealing  with connection pooling trying to get an idea how to go about making the change that will allow them to run under Websphere 4.
ASKER CERTIFIED SOLUTION
Avatar of Mick Barry
Mick Barry
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of xoxomos

ASKER

OK i'll see.  Do you mean for instance
 private static String poolName   = "JdbcOracle"; // pool name from WebSphere application manager
   private static boolean waitRetry = true; // waitRetry - try again if all connections are busy?
   private static String jdbcDriver = "oracle.jdbc.driver.OracleDriver"; // Java class for the JDBC driver
   private static String url        = "jdbc:oracle:thin:@127.0.0.1:1521:REG"; // database connection url
   private static String user       = "webreg"; // user
   private static String password   = "jackson"; // password

i would instead
ds.setURL(url)
                     ds.setUser(user);
                     ds.setPassword(pass);
??
yes, let me know how you go.

Thanks for the points :)

http://www.objects.com.au/staff/mick
Brainbench MVP for Java 1
http://www.brainbench.com
Avatar of xoxomos

ASKER

What's happening is, I have a bunch of servlets running under Websphere 3 that i attempted to run under Websphere 4.  Eventually i came across the documentation that the com.ibm.servlet package from Visual Age 4 that is deprecated in 3 is no longer supported in 4.  I'm looking at the Oracle and IBM sites that dealing  with connection pooling trying to get an idea how to go about making the change that will allow them to run under Websphere 4.