I saw a post on Lotus developerWorks asking for help on creating an imported Java agent. Since I have seen this question so many times I finally decided to create an example.
I case you didn’t know you can create Java agents in two ways in Domino Designer:
- Write the agent in Domino Designer (this is the most common way to write a Java agent).
- Import compiled code into Domino Designer.
This example will focus on the latter.
When creating an agent with imported code you must make sure that one of the classes extend the lotus.domino.AgentBase class. When the agent is run in Notes an instance of this class is created and the NotesMain() method is called. As you can see in the first screenshot I have written a simple agent in Eclipse. The class (dk.heisterberg.lekkim.blog.TestAgent) extend lotus.domino.AgentBase and have some simple Java code in he NotesMain() method. Apart from being a requirement, one of the advantages of extending AgentBase is that you do not have to worry about threads and how to get a Session object (you can simply call getSession() as shown in the example).
Once you have compiled the agent (automatically done if using Eclipse) you create a zip-/jar-file with the compiled classes. Make sure to include the entire package hierarchy if you are using packages. Then create an agent in Domino Designer, set the type to “Imported Java” and click the “Import Class Files…” as shown below.
In the dialog box you select the zip-/jar-file you created and add it to the right pane. Then, and this is the important point here, specify the class that extend the lotus.domino.AgentBase class in the “Base class” field. Remember to include the package name if you are using packages.
Click OK and verify the choices you made in the dialog box has been set correctly.
Give the agent a name, set the desired agent trigger and save the agent. That’s it!
The example database is available for download.
I noticed you are using Eclipse for Java development. Just wanted to mention a great tool for simplyfing creation and maintenance of Java code for Notes/Domino: http://www.domiclipse.com.
Because of your help, I created the Java Agent and imported my jar file, I have one more question, In my base class I am getting information from XML file and I also impoted the xml file, but getting following error,
2006-03-01 19:00:33,781 INFO main.EdvisorToBlueGroup (EdvisorToBlueGroup.java:62) – START ………….
2006-03-01 19:00:33,981 FATAL main.EdvisorToBlueGroup (EdvisorToBlueGroup.java:89) – Configuration Error: Invalid properties file!
2006-03-01 19:00:33,981 INFO main.EdvisorToBlueGroup (EdvisorToBlueGroup.java:90) – System terminates with errors.
java.lang.SecurityException: Exit with code 0
at COM.ibm.JEmpower.applet.AppletSecurity.failSecurity(AppletSecurity.java:573)
at COM.ibm.JEmpower.applet.AppletSecurity.failSecurity(AppletSecurity.java:563)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1416)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1386)
at java.lang.SecurityManager.checkExit(SecurityManager.java:785)
at java.lang.Runtime.exit(Runtime.java:119)
at java.lang.System.exit(System.java:746)
at com.ibm.cal.edvisor.tstb.main.EdvisorToBlueGroup.NotesMain(EdvisorToBlueGroup.java:36)
at lotus.domino.AgentBase.runNotes(Unknown Source)
at lotus.domino.NotesThread.run(NotesThread.java:218)
Error cleaning up agent threads
Here is part of my java class..
private static Logger logger = Logger.getLogger(EdvisorToBlueGroup.class);
private static final String DEFAULT_CONFIG = “configuration.properties”;
private String configurationFile = DEFAULT_CONFIG;
private final static int SYSTEM_SUCCESS = 0;
private final static int FATAL_SYSTEM_ERROR = 1;
/**
* The facade method that should be called to use Edvisor To Blue Group.
* @return system return code
*/
public int execute() {
DatabaseAccessController database = null;
Iterator trackIDsIterator = null;
int applicationRetries = 0;
int applicationWaitTime = 0;
try {
logger.info(“START ………….”);
ConfigurationReaderBean prop = new
ConfigurationReaderBean(getConfigurationFile());
logger.info(“START 1 ———————“);
logger.info(“Configuration properties file loaded.”);
ResourceFactory.getInstance().createObject(prop);
logger.info(“End ……………..”);
logger.info(“START 2 ———————“);
logger.info(“Resource file loaded.”);
Resource resource = ResourceFactory.getInstance().getResource();
logger.info(“START 3 ———————“);
DatabaseAccessFactory.getInstance().createObject(resource);
logger.info(“START 4 ———————“);
logger.info(“Database access created.”);
logger.info(“START 5 ———————“);
database =
DatabaseAccessFactory.getInstance().getDatabaseAccessController();
trackIDsIterator = resource.getTrackIDs();
applicationRetries = resource.getApplicationRetries();
logger.info(“Application retries for each track ID: ” +
applicationRetries);
applicationWaitTime = resource.getApplicationWaitTime();
logger.info(“Application wait time between each retry for each track ID:” + applicationWaitTime);
} catch (ConfigurationException ce) {
logger.fatal(“Configuration Error: ” + ce.getMessage());
logger.info(“System terminates with errors.”);
Thanks for all help..
Lisa John
You have to understand that Domino agent runs under a specialized Java SecurityManager (COM.ibm.JEmpower.applet.AppletSecurity) that enforces the agent security model. The SecurityManager for example enforce that you cannot read or write a file on disk from an agent not allowed access to restricted operations (see the second tab of the agent properties). It also enforce that you do not use operations that are illegal from a Domino point of view such as System.exit().
My recommendation is to set the agent to run with full priviledges for starters to see if that solves the problem. That is normally the easiest way to see if the problems are SecurityManager related. In your case I guess they are due to the reference to COM.ibm.JEmpower.applet.AppletSecurity in the stacktrace.
You cannot install your own SecurityManager so don’t even try to go down that path… 🙂
/lekkim
Hi Lekkim
Thanks for your in-depth response.
For the agent i am using the following setting for Security.
Set Runtime Security Level: 3. Allow Restricted Operations with full administration right.
Default access for viewing and running this agent: checked ->All readers and above
Checked->All public Access user to view and run this agent
One question, When I was running this Java Utility using batch file from command prompt, I was using the xml for resource. Following is XML file.
———————
LOCAL
Lead_ops_rx_copy.nsf
bluepages.ibm.com;
bluegroups.ibm.com
10
10
true
3
60
30
true
87256E670071031B
true
My Basic Blue Group
ljohn@Lever.com
12345
0
2006
12
31
—————————-
and following is configuraiton.properties file
………………….
# This configuration is to determine what kind of
# resource will be used to configure the system.
# Currently only XML resource file is supported.
# Only XML resource is supported
ConfigurationReader.Resource.Type=XML
# The following two fields are for future extensions
ConfigurationReader.Resource.Server=
ConfigurationReader.Resource.Path=
# This file is the path/filename of the resource
ConfigurationReader.Resource.File=C:/EdvisorToBlueGroup/resource.xml
…………………………..
If you see the error after the line
(EdvisorToBlueGroup.java:62) – START …………. 2006-03-01 19:00:33,981 FATAL
It look like it is not reading the XML and I included the xml in jar file, but some how when running the agent it not reading the info from the XML,
could you please let me know how it can read xml in java agent, should it different in Notes then stand alone java apps.
Thanks for help.
Well there is nothing special about reading property or xml-files from a Java agent as long as the file is packaged with the agent. You simply load the resource as a stream (see text in bold):
import lotus.domino.*; import java.util.*; import java.io.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); Properties p = new Properties(); InputStream in = this.getClass().getClassLoader().getResourceAsStream("lekkim.properties"); p.load(in); System.out.println(p.getProperty("firstname") + " " + p.getProperty("lastname")); } catch(Exception e) { e.printStackTrace(); } } }This is code from a standard Java agent not allowed to use restricted operations and it runs without any issues. I have simply added a properties file (lekkim.properties) to the agent using the “Edit Project” button. I’m using a normal Java agent to test this.
My guess is that the stacktrace you are seeing is not from trying to read the files but from another source. If you look at the stacktrace the problem is your call to java.lang.System.exit() which is illegal in Notes.
If it was me I would break down the agent into some smaller parts and make sure that you can read the properties file correctly. Then try using your bean to get and parse the xml-file. Take small steps to get acquinted with the environment.
Hi Lekkim
With you suggestion I removed the
System.exit().
and now I am not getting any error related to security.
But now I am getting the
“Error cleaning up agent threads” error
and I treid to figure out class where I am getting, but I am unable to found the class, do please put some light on this error.
Thanks a lot.
Lisa
Your agent is probably is creating some additional threads to the one (NotesThread) created as part of extending lotus.domino.AgentBase. If you have multiple threads in your agent make sure that the one creating the lotus.domino.Session class is the last one to be terminted. One solution is to use a separate ThreadGroup.
The error normally occurs because a thread is still running when the Domino Amgr is terminating the agent thread.
/lekkim
Hi Lekkim
Could you please let me know that what is requirement from Notes java agent to connect to SSL if user already have the userid and password to SSL site, I have seen a post http://bob-obringer.com/A557B7/blog.nsf/dx/01292005231041DOM848.htm?opendocument&comments
and I followed this but it did not help.
Could you please about this.
Thanks
Hi Lekkim
In my previous mail, I mention that while connecting to ssl site I am getting error and following is error
java.lang.SecurityException
java.lang.SecurityException
at java.lang.SecurityManager.checkPermission(SecurityManager.java:603)
at COM.ibm.JEmpower.applet.AppletSecurity.checkSecurityPermission(AppletSecurity.java:1265)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1450)
at COM.ibm.JEmpower.applet.AppletSecurity.checkPermission(AppletSecurity.java:1386)
at java.lang.SecurityManager.checkSecurityAccess(SecurityManager.java:1711)
at java.security.Provider.check(Provider.java:356)
at java.security.Provider.put(Provider.java:318)
at com.ibm.jsse.JSSEProvider.(Unknown Source)
at com.ibm.swat.password.cwa2.(cwa2.java:68)
at com.ibm.cal.edvisor.tstb.bluegroup.BlueGroupConnection.(BlueGroupConnection.java:35)
at com.ibm.cal.edvisor.tstb.bluegroup.BlueGroupRequest.(BlueGroupRequest.java:43)
at com.ibm.cal.edvisor.tstb.bluegroup.BlueGroupUpdate.executeUpdate(BlueGroupUpdate.java:50)
at com.ibm.cal.edvisor.tstb.main.EdvisorToBlueGroup.execute(EdvisorToBlueGroup.java:123)
at com.ibm.cal.edvisor.tstb.main.EdvisorToBlueGroup.NotesMain(EdvisorToBlueGroup.java:35)
at lotus.domino.AgentBase.runNotes(Unknown Source)
at lotus.domino.NotesThread.run(NotesThread.java:218)
Could you please look into it.
Regards
Lisa
My guess is that the java.lang.SecurityException is thrown because you didn’t add the necessary lines to the java.security file as mentioned on http://bob-obringer.com or because you didn’t restart Domino or Notes in between.
/lekkim
Hi Lekkim
I will appreciate if you provide the answer to the following questions about java agent.
1) When using the Edit Project button and looking for Shared Java Libraries the list of databases points to my local machine. How do I get this list to point to the Server on which I am developing? I need this so we can shared code for all developers to use.
2) Using the Edit project I added all the jar files and compile the agent, then still I need to add the JavaUserClasss parameter in Notes.ini or I need to put the jar files in ext folder in server.
3) I have the XML file in file system, which I impoted in agent , how I can use the xml file using the notes form and create the xml from notes.
Thanks for the help.
Lisa I get this question quite a lot so I’ll write a blog post about the issue about where the different Java class files should go tonight or over the weekend. Hope that is ok.
Hi Lekkim
Did you have a time to write some thing about following……..I don’t want to be pushy
When using the Edit Project button and looking for Shared Java Libraries the list of databases points to my local machine. How do I get this list to point to the Server on which I am developing? I need this so we can shared code for all developers to use.
Thanks
Lisa
Well I wrote a piece on managing external dependencies which is basically what you’re asking about.
You cannot share script libraries among different databases, that is databases with different replica id. There are of causes ways around this but using the normal approach it isn’t possible. If using the same database the list of script libraries should be the same on the server as on the local machine unless you did something with your replication.