Using JTOpen / JT400 in agents

I’m using JTOpen to run as JDBC connection to out iSeries.

Here’s the agent code:

= = = Start of listing = = =

import java.sql.Connection;

import java.sql.DriverManager;

import lotus.domino.AgentBase;

import lotus.domino.AgentContext;

import lotus.domino.Session;

public class JavaAgent extends AgentBase {

public void NotesMain() {



	try {

		Session session = getSession();

		AgentContext agentContext = session.getAgentContext();



		Class.forName("com.ibm.as400.access.AS400JDBCDriver");



		Connection conn = DriverManager.getConnection(

				"jdbc:as400://xxx.xxx.xxx.xxx", "UserId", "password");



		System.out.println("Catalog: " + conn.getCatalog());

		System.out.println("Is closed? " + conn.isClosed());

		

	} catch (Exception e) {



		e.printStackTrace();



	}

}

}

= = = End of listing = = =

This code runs sort of OK the first time in Designer and

the Java console output looks like this:

= = = Start of listing = = =

Catalog: OurIseriesName

Is closed? false

Error cleaning up agent threads

= = = End of listing = = =

Note the error message “Error cleaning up agent threads”.

When I run the agent again, I get this error in the Java console:

= = = Start of listing = = =

java.lang.OutOfMemoryError

= = = End of listing = = =

And in the Agent completion message in Designer:

= = = Start of listing = = =

Started running agent ‘test2’ on 01/12/2009 13:29:15

ERROR: JVM: Attempt to retrieve Java agent attachments failed.

Ran Java Agent Class

Done running agent ‘test2’ on 01/12/2009 13:29:22

= = = End of listing = = =

I’ve scanned the usual places for information, but have found only vague references to multiple threads being created. Has anyone else seen this problem? I’ve extended the code to actually pull back data from the iSeries and this works OK the first time round, retrieving rows correctly. It seems that the first time this runs, something is not terminated correctly in the JVM.

This works fine in Eclipse using the same core code.

Subject: Close Connection

In the rdb processing class create method public void closeConnection(){

//Connection conn

//Statement stmt

try{

stmt.close();

conn.close();

}catch(SQLException e){

//some action

}

}

call this in the end of the processing

Subject: More code

Hi Igor - Thanks for your reply. I’ve extended the code to this. I think I’m shutting everything down OK, but I still get the error. The first time I run this agent, it returns the result set OK. The second time, it fails, requiring a restart of Notes as the JVM seems to crash.

= = = Start of code = = =

import java.sql.Connection;

import java.sql.DriverManager;

import java.sql.ResultSet;

import java.sql.Statement;

import lotus.domino.AgentBase;

import lotus.domino.AgentContext;

import lotus.domino.Session;

public class JavaAgent extends AgentBase {

public void NotesMain() {



	try {

		Session session = getSession();

		AgentContext agentContext = session.getAgentContext();



		System.out.println("Starting to open connection");

		Class.forName("com.ibm.as400.access.AS400JDBCDriver");



		Connection conn = DriverManager.getConnection(

				"jdbc:as400://xxx.xxx.xxx.xxx", "xxxxx", "xxx");



		System.out.println("Catalog: " + conn.getCatalog());

		System.out.println("Is closed? " + conn.isClosed());



		Statement stmt = conn.createStatement();

		ResultSet rs = stmt.executeQuery("SELECT * FROM xxx.xxx");



		while (rs.next())

			System.out.println(rs.getString(1));



		// Close the result set, statement and the connection

		rs.close();

		stmt.close();

		conn.close();



		System.out.println("Connection closed");



		agentContext.recycle();

		session.recycle();



	} catch (Exception e) {



		e.printStackTrace();



	} finally {



	}

}

}

= = = End of code = = =

Subject: Do not recycle your session

remove agentContext.recycle();

session.recycle();

Subject: This doesn’t seem to make any difference.

I only put those lines in to see if it would make nay difference. Either way, the problem remains.

Subject: Solution found

It seems that I’ve found a solution. I had actually put the JT400 jar file into a script library and then imported the script library into my agent. This made sense from a maintenance point of view, as I could then use templating to pass down new versions of the JT400.jar. The problem disappears when I import the jt400.jar archive file directly into the agent rather than as part of a scrpt library. Still don’t knoe why this should cause a problem, though :slight_smile:

Subject: This is still flaky

What I didn’t want to have to do is have the jt400.jar file in Notes/jvm/lib/ext. Putting it into a script file (by importing it as an archive) works once, but fails on subsequent attempts. Importing it directly into the agent works OK for multiple invocations of the agent, but fails when a copy of that agent is run (go figure!). It looks as though I’ll be going to use the solution mentioned at the beginning of this post. However, this seems to be a general problem - I don’t think it’s limited to just jt400, and I think that all the ways I’ve tried to integrate the jar file have been correct in principle. Can anyone else shed light on this? The ability to integrate external jars into a Notes project without having to put the jars into the server’s file system seems to be something that really we ought to be doing as good practice.

Subject: Code and configuration

Configuration:jt400 - you can use David’s solution

or add to notes.ini line

JAVAUSERCLASSES=libpath

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Code:

It works for years

public class IndexTarnsfer extends AgentBase {

    public void NotesMain() {

           

            String[] configParams = {param1,param2, param3};

            Configuration config ;

            SimpleLogger nlogger  ;

            NsfController dc  ;

            RdbController rc  ;

            TransferBean  index ;

           

            long counter= 0 ;        

            String logMsg = "";

            String startMessage        =        "Start processing Time=";

            



            NsfConfigFactory configFactory = new NsfConfigFactory();



            try {

                    Session session = getSession();

                    AgentContext agentContext = session.getAgentContext();



                   

                    config = configFactory.getNsfConfiguration(session,configParams );

                    nlogger = new NsfLogger(session , config);



                    startMessage = startMessage + DateTimeHelper.getCurrentDateTime();

                    dc = new NsfController(session , config, nlogger);

                    rc = new RdbController(config, nlogger);        

                   

                    index = dc.getIndex() ;

                    while(index.isValid() ){

                                    logMsg = rc.insertIndex(index);

                                 

                                    if(rc.isInserted()){

                                            dc.commit() ;        

                                            rc.resetStatus();                                                

                                    }

                                    counter++ ;

                                    index = dc.getIndex() ;

                           

                    }

                    startMessage=startMessage +"; End processing Time=" +  DateTimeHelper.getCurrentDateTime();

                    nlogger.runLog( startMessage + "; Processed=" + counter);

                   



                    rc.closeConnection();





            } catch(Exception e) {

                    e.printStackTrace();

            }

    }

}

and In the rdb processing class create method

public void closeConnection(){

//Connection conn

//Statement stmt

try{

stmt.close();

conn.close();

}catch(SQLException e){

//some action

}

}

Subject: Don’t import the jt400 jar

I solved a similar problem by not importing the jt400.jar into the agent. Try putting it in the Notes/jvm/lib/ext directory instead.

Subject: That’s interesting

Thanks for your reply, I’ll be trying that right away. Do you know why this makes a difference?

Subject: That seems to work OK.

That solution seems to work OK. I’m wondering ifit’s a problem with the class loader. By inserting the jt400.jar file in the /jvm/lib/ext directory, I’m loading everything at Notes initialisation rather than dynamically when I run the agent. It’s an effective solution, but it doesn’t allow the agent/database to be portable, as any target system needs the jt400.jar files in the /jvm/lib/ext location. Thanks for your help!