Writing Java to build applications using IBM Lotus Domino Designer Oscar I. Hernandez IBM Software Group Staff Software Engineer, Lotus Notes/Domino Austin, TX August 2009 © Copyright International Business Machines Corporation 2009. All rights reserved. Summary: The objective of the article is to help the traditional LotusScript® developer, who typically has no hard-core development background, move to JavaTM. With little or no existing Java knowledge, this article will help you get started on developing Java applications in IBM® Lotus® Domino®. Table of Contents 1 Introduction.................................................................................................................. 2 2 Java language.............................................................................................................. 2 2.2 Line by line explanation ........................................................................................ 3 2.3 Java language basics........................................................................................... 4 2.4 Differences between LotusScript and the Java language .................................. 10 3 Examples................................................................................................................... 10 3.1 Example 1: Sending an email ............................................................................. 10 3.2 Example 2: Cycling through a Notes view........................................................... 16 3.3 Example 3: Generate a report with mail database information ........................... 21 4 Other essentials......................................................................................................... 30 5 Conclusion................................................................................................................. 31 6 Resources.................................................................................................................. 31 7 About the author ........................................................................................................ 31 1 1 Introduction For IBM Lotus Notes application developers, LotusScript and the LotusScript classes are invaluable when designing Notes applications. The LotusScript API allows you to interact programmatically with databases, documents, and even with design elements. As Javahas continued to emerge as a mainstream programming language, more and more Notes application developers are making the move to Java. This article is intended for LotusScript developers who want to start programming with Java in IBM Lotus Domino. It is assumed that the reader is an experienced LotusScript programmer. This document consists of three main sections: Java Language, Examples, and Other essentials. Java programmers may feel comfortable enough to jump into the Examples section, while beginners should review the Java Language section first. 2 Java language Released in 1995, Java is an object-oriented programming language that was created to address the need for platform independence. This was accomplished by compiling the Java source code into bytecodes, which could then be interpreted by any Java Virtual Machine (JVM) on any platform. Hence, as long there was a JVM implemented for the desired platform, it could run any Java application. For more information, visit The History of Java Technology. Java's syntax is similar to C, and its object-oriented implementation is similar to C++, making it an easy-to-learn language for C/C++ programmers. LotusScript developers, however, will find the Java syntax quite different from LotusScript. Since this article focuses on using Java in Lotus Domino, the examples presented will be in the context of Lotus Domino. Let’s begin with the classic "Hello World" example. When you create a new Java agent in Domino Designer, you received the template code on the left-hand side of table 1. The code on the right-hand side has been modified to accommodate the "Hello World" example. 2 Table 1. Hello World example Template Java Agent Code Hello World Java Agent Code import lotus.domino.*; import lotus.domino.*; public class JavaAgent extends AgentBase { public class JavaAgent extends AgentBase { public void NotesMain() { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) } } // (Your code goes here) System.out.println("Hello World!"); } catch(Exception e) { e.printStackTrace(); } } } } catch(Exception e) { e.printStackTrace(); } 2.2 Line by line explanation Let's examine the code, line by line: import lotus.domino.*; Java uses the import statement to include other Java classes. In this case, all the lotus.domino classes are available to the agent code. Java classes are usually contained within JAR files. There are several methods for making JAR files available to an agent. Refer to the “Using external JAR files with Java agents”paragraph in Section 4 of this paper for information on JAR files. public class JavaAgent extends AgentBase { Java is an object-oriented programming language. This line demonstrates that, when you create a Java agent, it creates a JavaAgent class, which will be the main class where you will write your Java code. You may also notice that the JavaAgent class extends the AgentBase class. Since Java is object-oriented, extending the AgentBase class gives us an entry point into the agent, which brings us to the next line. public void NotesMain() { The NotesMain method is the entry point to the agent. Here we override the AgentBase method definition with our own. try { In Java, error handling is handled through try and catch blocks. Methods that throw exceptions in Java must be surrounded by a try block, and every try block must have a corresponding 3 catch block. The try and catch blocks are required in the "Hello World" example because the getAgentContext method throws a NotesException. To see which Domino methods throw an exception, refer to their method signature in the Domino Designer Help file. Session session = getSession(); The getSession method from the AgentBase class allows us to create a session object. The Java Session class is similar to the LotusScript NotesSession class. AgentContext agentContext = session.getAgentContext(); The AgentContext class lets you get a handle to the current database (using its getCurrentDatabase method). In LotusScript, this additional class is not required to get a handle to the current database. // (Your code goes here) The thing to note with this line is that a single line comment begins with "//". For multiple line comments we use "/*" at the beginning and end with "*/" (similar to C++). System.out.println("Hello World!"); This is the Java method used to print to the console. To open the Java console in Notes, select Tools > Show Java Debug Console, from the menu. The System.out.println method is similar to the LotusScript Print method. } catch(Exception e) { This is the corresponding catch statement for the try above. e.printStackTrace(); In the catch block, you can opt to handle the exception as you wish; in this case, we are simply printing out the stack trace. 2.3 Java language basics Java provides eight primitive types: byte, short, int, long, char, float, double, and Boolean. Table 2 describes each type and indicates the LotusScript equivalent (if any). Table 2. Primitive types and LotusScript equivalents Java Primitive Type Java Description LotusScript Equivalent byte 8-bit signed two's complement integer (-128 to 127) Byte Similar: 8-bit Difference: unsigned (0 to 255) short 16-bit signed two's complement integer (-32,768 to 32,767) Integer Similar: 16-bit, signed (-32,768 to 32,767) int 32-bit signed two's complement integer (-2,147,483,648 to 2,147,483,647) Long Similar: 32-bit, signed (-2,147,483,648 to 2,147,483,647) long 64-bit signed two's complement N/A 4 integer (-9,223,372,036,854,775,808 to 9,223,372,036,854,775,807) char single 16-bit Unicode character N/A However, LotusScript does provide a String type which can contain multiple characters. float single-precision 32-bit IEEE 754 floating point Single Similar: single-precision 32-bit floating point double double-precision 64-bit IEEE 754 Double floating point Similar: double-precision 64-bit floating point Boolean true or false value Boolean Similar: true or false value Operators Java has a rich set of operators. Table 3 shows merely a subset of its operators along with the description and LotusScript equivalent. For a complete listing, visit the Java Tutorials Operators page. Table 3. Java operators Java Arithmetic Operator Description LotusScript Equivalent = Assignment = + Addition + ++ Increment N/A += Addition assignment N/A - Subtraction (also unary minus) - -- Decrement N/A -= Subtraction assignment N/A * Multiplication * *= Multiplication assignment N/A / Division / /= Division assignment N/A % Modulus Mod %= Modulus assignment N/A Java Relational Operator == Description Equal LotusScript Equivalent = 5 != Not equal <>, >< > Greater than > >= Greater than or equal to >=, => < Less than < <= Less than or equal to <=, =< Java Logical (bitwise) Operator Description LotusScript Equivalent & Bitwise And And | Bitwise Or Or ^ Bitwise exclusive Or Xor ~ Bitwise complement Not >> Shift bits right with sign extension N/A << Shift bits left N/A Java Logical (Boolean) Operator Description LotusScript Equivalent && Boolean And And || Boolean Or Or == Boolean equals Eqv ! Boolean Not Not Declaring a variable The syntax for declaring a variable in Java is the type, followed by the variable name: type variable_name; In Java, variable names can consist of letters, digits, and the underscore. Variable names are case sensitive and cannot begin with a digit: Java LotusScript int i; Dim i as Integer String s; Dim s as String 6 Creating a function There are two key differences regarding the function syntax between LotusScript and Java. First, the return type is placed in front of the function name (as opposed to LotusScript, in which it is placed at the end). Secondly, Java uses the return keyword to return the value from the function (see listing 1). Listing 1. Creating a function example return_type function_name(parameter_type1 parameter_name1, parameter_type2 parameter_name2) { //function code... return return_type_object; } Java LotusScript public int product(int x, int y) { return x*y; } Function product(x As Integer, y As Integer) As Integer product = x * y End Function Calling the function: int i = product(2,4); System.out.println(i); Calling the function: Dim i As Integer i = product(2, 4) Print i Creating a class The syntax for creating classes in Java is similar to that of LotusScript. Both use the class keyword with the private/public option, and both allow class members as well as class methods. Note, however, that the LotusScript class constructor uses the New keyword, while Java uses the name of the class with zero arguments (see listing 2 and table 4). Listing 2. Example of creating a class class class_name { type class_member1; type class_member2; .... class_name() //constructor { //constructor code } return_type class_method1(parameter list) { //method code 7 } return_type class_method2(parameter list) { //method code } .... } Table 4. Creating a class Java LotusScript public class Person { private String Name; private int Age; Public Class Person Private PName As String Private PAge As Integer Sub New PAge = 0 PName = "" End Sub public Person() { this.Name=""; this.Age=0; } Public Property Set Person_Name As String PName = Person_Name End Property public void SetName(String name) { this.Name = name; } Public Property Get Person_Name As String Person_Name = PName End Property public String GetName() { return this.Name; } Public Property Set Age As Integer PAge = Age End Property public void SetAge(int age) { this.Age = age; } Public Property Get Age As Integer Age = PAge End Property Sub AddYears (i As Integer) PAge = PAge + i End Sub public int GetAge() { return this.Age; } } End Class public void AddYears(int i) { this.Age = this.Age + i; } 8 Creating an Instance of the Class: Creating an Instance of the Class: Person p = new Person(); p.SetName("John Doe"); p.SetAge(20); Dim p As New Person p.Person_Name = "John Doe" p.Age = 20 System.out.println(p.GetName() + " " + p.GetAge()); Messagebox p.Person_Name & " " & Cstr (p.Age) p.AddYears(5); p.AddYears(5) System.out.println(p.GetName() + " " + p.GetAge()); Messagebox p.Person_Name & " " & Cstr (p.Age) Flow control statements To control the flow of your script, Java provides all the standard flow control statements you would expect from any programming language. Table 5 lists Java's most common flow control statements and their LotusScript equivalent. For further information on Java's flow control statements, visit the Java Tutorials Control Flow Statements page. Table 5. Java flow control statements Java Flow Control Statements LotusScript Equivalent if (condition) { //perform these statements } If condition Then 'perform these statements End If if (condition) { //perform these statements } else { //perform these statements } If condition Then 'perform these statements Else 'perform these statements End If switch (expr) { case c1: //perform these statements if expr == c1 break; case c2: //perform these statements if expr == c2 break; ... default: //perform these statements if expr != any of cases } Select Case expr Case c1 'perform these statements if expr = c1 Case c2 'perform these statements if expr = c2 ... Case Else 'perform these statements if expr <> any of the cases End Select while (condition) { //perform these statements } While condition 'perform these statements Wend do { Do While condition 'perform these statements Loop //perform these statements } while (condition); 9 for (initialization; termination; increment) { //perform these statements } For countVar = first To last 'perform these statements Next 2.4 Differences between LotusScript and the Java language LotusScript and Java are similar in that they are both are object-oriented programming languages. Besides the syntax, one of the main differences between the languages is that Java is strongly typed, while LotusScript is not. In Java, you must declare all variables (name and type) before they are used. This is not a requirement in LotusScript, although there is some type enforcement. Another major difference is that Java is case sensitive, while LotusScript is not. You should keep this in mind when writing Java code because p and P are two different variables, and setName and SetName are two different methods. Domino-specific differences Although the names may differ, most of the Domino classes provided for LotusScript are available in Java. In LotusScript, Domino classes begin with “Notes”; for example, the class for dealing with databases is “NotesDatabase”, and for documents it's “NotesDocument”. In Java, on the other hand, the names of the classes do not begin with “Notes”. Hence, the class for dealing with databases is just “Database”, and for documents it's “Document”. A major difference between the LotusScript and Java Domino classes is the UI classes. LotusScript provides the following classes for UI interaction: NotesUIWorkspace, NotesUIDatabase, NotesUIDocument, and NotesUIView These classes let you interact with the current database, document, or view open in Notes. In Java, however, there are no equivalent UI classes. For a complete listing of the Java Domino classes, refer to the Domino Designer Help file. 3 Examples Let's look at some common tasks that are performed using LotusScript and see how we can do the equivalent in Java. Our first example is sending an email message. 3.1 Example 1: Sending an email Take a minute to examine the LotusScript code in listing 3 below: Listing 3. Example LotusScript send email code 1 2 3 4 Dim session As New NotesSession Dim database As NotesDatabase Dim email As NotesDocument Dim sendto As String 10 5 6 Dim subject As String Dim body As String 7 8 9 10 11 Set database = session.CurrentDatabase Set email = database.CreateDocument sendto = "Enter_Email_Address_Here" subject = "Email sent by LotusScript code" body = "Text in body of email sent by LotusScript code" 12 13 14 15 16 Call email.ReplaceItemValue("Form", "Memo") Call email.ReplaceItemValue("SendTo", sendto) Call email.ReplaceItemValue("Subject", subject) Call email.ReplaceItemValue("Body", body) Call email.Send(False) Now let's code the above example in Java, starting off with the Java template code that is provided for us (see listing 4). Listing 4. Java template code import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) } catch(Exception e) { e.printStackTrace(); } } } In lines 1--6 of the LotusScript example in listing 3 above, we declare the session, database, email, sendto, subject, and body variables. Since the template code already provides us with a session object, let's declare the remaining variables (see listing 5). Listing 5. Declaring the remaining variables import lotus.domino.*; 11 public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; Document email; String sendto; String subject; String body; } catch(Exception e) { e.printStackTrace(); } } } In lines 7--11 from listing 3, we initialize our database, email, sendto, subject, and body variables (see listing 6). As mentioned earlier, we must use the agentContext object instead of the session object to get a handle to the current database. Also, we do not need the Set keyword in Java to set the variables. Listing 6. Initializing the variables import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; Document email; String sendto; String subject; 12 String body; database = agentContext.getCurrentDatabase(); email = database.createDocument(); sendto = "Enter_Email_Address_Here"; subject = "Email sent by Java code"; body = "Text in body of email sent by Java code"; } catch(Exception e) { e.printStackTrace(); } } } In lines 12--15 of listing 3, we replace the value of fields Form, SendTo, Subject, and Body, and finally, in line 16, we send the email. Notice Java does not require the Call keyword (see listing 7) when calling methods. Also, even though the replaceItemValue and send methods have the same spelling between LotusScript and Java, you must remember to use the correct case in Java (since Java is case sensitive). Listing 7. Setting the appropriate fields and sending the email import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; Document email; String sendto; String subject; String body; database = agentContext.getCurrentDatabase(); email = database.createDocument(); sendto = "Enter_Email_Address_Here"; subject = "Email sent by Java code"; body = "Text in body of email sent by Java code"; 13 email.replaceItemValue("Form", "Memo"); email.replaceItemValue("SendTo", sendto); email.replaceItemValue("Subject", subject); email.replaceItemValue("Body", body); email.send(false); } catch(Exception e) { e.printStackTrace(); } } } There are no more LotusScript lines left, but we still have some additional work to perform in our Java agent. Specifically, in Java, we must call recycle on all Domino objects (see listing 8). Calling recycle ensures that all the memory allocated for those objects is released. For more information on the recycle method, see the “The recycle() method” paragraph in Section 4. Listing 8. Calling recycle on Domino objects import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; Document email; String sendto; String subject; String body; database = agentContext.getCurrentDatabase(); email = database.createDocument(); sendto = "Enter_Email_Address_Here"; subject = "Email sent by Java code"; body = "Text in body of email sent by Java code"; email.replaceItemValue("Form", "Memo"); 14 email.replaceItemValue("SendTo", sendto); email.replaceItemValue("Subject", subject); email.replaceItemValue("Body", body); email.send(false); //recycle Java Domino objects if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (database !=null) database.recycle(); if (email !=null) email.recycle(); } catch(Exception e) { e.printStackTrace(); } } } Table 6 sums up this example comparison. Table 6. Side-by-side comparison of Example 1 LotusScript Java Example 1: Sending an Email Example 1: Sending an Email Dim session As New NotesSession Session session = getSession(); AgentContext agentContext = session.getAgentContext(); Dim database As NotesDatabase Dim email As NotesDocument Dim sendto As String Dim subject As String Dim body As String Database database; Document email; String sendto; String subject; String body; Set database = session.CurrentDatabase Set email = database.CreateDocument sendto = "Enter_Email_Address_Here" subject = "Email sent by LotusScript code" body = "Text in body of email sent by LotusScript code" Call email.ReplaceItemValue("Form", "Memo") Call email.ReplaceItemValue("SendTo", sendto) Call email.ReplaceItemValue("Subject", subject) Call email.ReplaceItemValue("Body", body) database = agentContext.getCurrentDatabase(); email = database.createDocument(); sendto = "Enter_Email_Address_Here"; subject = "Email sent by Java code"; body = "Text in body of email sent by Java code"; Call email.Send(False) 15 email.replaceItemValue("Form", "Memo"); email.replaceItemValue("SendTo", sendto); email.replaceItemValue("Subject", subject); email.replaceItemValue("Body", body); email.send(false); //recycle Java Domino objects if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (database !=null) database.recycle(); if (email !=null) email.recycl 3.2 Example 2: Cycling through a Notes view For our second example, we cycle through a Notes view (see listing 9). Though fairly simple, this example is very important when coding in Java since it demonstrates using the recycle method properly so as to prevent memory exceptions. Listing 9. LotusScript code for cycling through a view 1 2 3 4 Dim session As New NotesSession Dim database As NotesDatabase Dim view As NotesView Dim document As NotesDocument 5 6 7 Set database = session.CurrentDatabase Set view = database.GetView("Enter_View_Name_Here") Set document = view.GetFirstDocument 8 While (Not document Is Nothing) 'Process the document Print document.Created Set document = view.GetNextDocument(document) Wend 9 10 11 Starting out with the Java template, let's declare the database, view, and document variables (LotusScript lines 1--4 in listing 9). In addition to these three variables, we need a temporary Document. The temp Document variable is required in our while loop, to recycle the current document (see listing 10). Listing 10. Declaring database, view, and document variables import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { 16 try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; View view; Document document; Document temp; } catch(Exception e) { e.printStackTrace(); } } } Moving on to lines 5--7 (see listing 9), let's initialize our database, view, and document variables, as shown in listing 11. Listing 11. Initializing database, view, and document variables import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; View view; Document document; Document temp; database = agentContext.getCurrentDatabase(); view = database.getView("Enter_View_Name_Here"); document = view.getFirstDocument(); } catch(Exception e) { e.printStackTrace(); } 17 } } In lines 8--11 in listing 9, we cycle through each document in the view. Java has the same while keyword for the loop; however, we must use != instead of Not, and null instead of Nothing (see listing 12). Also, if we're to assign the same Domino variable multiple times in Java, we need to call recycle on it before the new assignment, to prevent memory leaks (hence the need for the temp variable). Listing 12. Cycling through each document in view import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; View view; Document document; Document temp; database = agentContext.getCurrentDatabase(); view = database.getView("Enter_View_Name_Here"); document = view.getFirstDocument(); while (document != null) { //Process the document System.out.println(document.getCreated()); temp = view.getNextDocument(document); // get the next document document.recycle(); // recycle the document we're done with document = temp; } } catch(Exception e) { e.printStackTrace(); } } 18 } We wrap up this example by calling recycle on all the other Domino objects we created, as shown in listing 13. Listing 13. Calling recycle on all other Domino objects import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database database; View view; Document document; Document temp; database = agentContext.getCurrentDatabase(); view = database.getView("Enter_View_Name_Here"); document = view.getFirstDocument(); while (document != null) { //Process the document System.out.println(document.getCreated()); temp = view.getNextDocument(document); // get the next document document.recycle(); // recycle the document we're done with document = temp; } if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (database !=null) database.recycle(); if (view != null) view.recycle(); 19 } catch(Exception e) { e.printStackTrace(); } } } Table 7 sums up this comparison. Table 7. Side-by-side comparison of Example 2 LotusScript Example 2: Cycling through a Notes View Dim session As New NotesSession Dim database As NotesDatabase Dim view As NotesView Dim document As NotesDocument Set database = session.CurrentDatabase Set view = database.GetView ("Enter_View_Name_Here") Set document = view.GetFirstDocument While (Not document Is Nothing) 'Process the document Print document.Created Set document = view.GetNextDocument (document) Wend Java Example 2: Cycling through a Notes View Session session = getSession(); AgentContext agentContext = session.getAgentContext(); Database database; View view; Document document; Document temp; (); database = agentContext.getCurrentDatabase view = database.getView ("Enter_View_Name_Here"); document = view.getFirstDocument(); while (document != null) { //Process the document System.out.println(document.getCreated()); temp = view.getNextDocument (document); // get the next document document.recycle(); // recycle the document we're done with document = temp; } if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (database !=null) database.recycle(); if (view != null) view.recycle(); 20 3.3 Example 3: Generate a report with mail database information Our last example is fairly extensive. Here we cycle through mail databases on a Domino server and create an email report with various items from from each mail file. First, take a moment to review the LotusScript example in listing 14. 21 Listing 14. LotusScript code example 1 2 3 4 5 6 7 Dim session As New Notessession Dim nab As New Notesdatabase("Enter_Server_Name_Here", "names.nsf") Dim reportDatabase As Notesdatabase Dim personDocument As NotesDocument Dim report As NotesDocument Dim view As NotesView Dim temp As String 8 9 Set reportDatabase = session.CurrentDatabase Set report = reportDatabase.CreateDocument 10 11 Call report.ReplaceItemValue("Form" , "Memo") Call report.ReplaceItemValue("Subject" , "Mail Applications Report") 12 Dim richTextItem As New NotesRichTextItem(report, "Body") 13 Set view = nab.GetView("People") 14 Set personDocument = view.GetFirstDocument 15 While Not personDocument Is Nothing 16 On Error Resume Next 17 Dim mailDatabase As New NotesDatabase(personDocument.mailserver(0), personDocument.mailfile(0)) 18 If mailDatabase.IsOpen Then 19 temp = "Mail Owner: " & personDocument.fullname(0) & " Size: " & Cstr(mailDatabase.size) & " _ bytes Template: " + mailDatabase.DesignTemplateName 20 Else 21 temp = "Could not open mail file for: " & personDocument.fullname(0) & " Server: " & personDocument.mailserver(0) & " , " & personDocument.mailfile(0) 22 End If 23 24 25 26 27 richTextItem.AppendText(temp) richTextItem.AddNewline(1) temp = "" Set personDocument = view.GetNextDocument(personDocument) Wend 28 Call report.Send(False, "Enter_Email_Address_Here") We start out with lines 1--7 (in listing 14), declaring the needed variables, and we initialize the nab Database variable. In Java, notice that we must use the session object to set nab (see listing 15). 22 Listing 15. Declaring the variables import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database nab; nab = session.getDatabase("Enter_Server_Name_Here","names.nsf"); Database reportDatabase; Document personDocument; Document report; Document tempDocument; View view; String temp; } catch(Exception e) { e.printStackTrace(); } } } The main difference between the LotusScript lines 8--14 (in listing 14) and the Java equivalent is the RichTextItem class; in Java, you need to use the createRichTextItem method of the Document class to create the rich text field (see listing 16). Listing 16. Initializing the variables and creating the report email import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) 23 Database nab; nab = session.getDatabase("Enter_Server_Name_Here","names.nsf"); Database reportDatabase; Document personDocument; Document report; Document tempDocument; View view; String temp; reportDatabase = agentContext.getCurrentDatabase(); report = reportDatabase.createDocument(); report.replaceItemValue("Form" , "Memo"); report.replaceItemValue("Subject" , "Mail Applications Report"); RichTextItem richTextItem; richTextItem = report.createRichTextItem("Body"); view = nab.getView("People"); personDocument = view.getFirstDocument(); } catch(Exception e) { e.printStackTrace(); } } } In lines 15--27 of listing 14, we do most of the work in the while loop. In Java, we use try/catch blocks for error handling instead of the On Error statement in LotusScript. Since the getDatabase method can throw an exception, we take advantage of the catch block to set the temp string variable (see listing 17). Another thing we must remember in Java is to use the recycle method within loops when reusing Domino variables. In this particular while loop, we must remember to recycle the mailDatabase and personDocument before each new assignment. Listing 17. Gathering the mail database information import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); 24 AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database nab; nab = session.getDatabase("Enter_Server_Name_Here","names.nsf"); Database reportDatabase; Document personDocument; Document report; Document tempDocument; View view; String temp; reportDatabase = agentContext.getCurrentDatabase(); report = reportDatabase.createDocument(); report.replaceItemValue("Form" , "Memo"); report.replaceItemValue("Subject" , "Mail Applications Report"); RichTextItem richTextItem; richTextItem = report.createRichTextItem("Body"); view = nab.getView("People"); personDocument = view.getFirstDocument(); while (personDocument != null) { Database mailDatabase; try { mailDatabase = session.getDatabase (personDocument.getItemValueString("MailServer"), personDocument.getItemValueString ("MailFile")); temp = "Mail Owner: " + personDocument.getItemValueString("FullName") + " Size: " + mailDatabase.getSize() + " _ bytes Template: " + mailDatabase.getDesignTemplateName(); mailDatabase.recycle(); } catch (Exception e) { temp = "Could not open mail file for: " + personDocument.getItemValueString("FullName") + " Server: " + personDocument.getItemValueString ("MailServer") + " , " + personDocument.getItemValueString("MailFile"); } richTextItem.appendText(temp); richTextItem.addNewLine(1); 25 temp = ""; tempDocument = view.getNextDocument(personDocument); personDocument.recycle(); personDocument = tempDocument; } } catch(Exception e) { e.printStackTrace(); } } } We wrap up this example by sending the email (line 28 of listing 14) and then recycling the rest of the Domino objects we created (see listing 18). Listing 18. Sending email and calling recycle on Domino objects import lotus.domino.*; public class JavaAgent extends AgentBase { public void NotesMain() { try { Session session = getSession(); AgentContext agentContext = session.getAgentContext(); // (Your code goes here) Database nab; nab = session.getDatabase("Enter_Server_Name_Here","names.nsf"); Database reportDatabase; Document personDocument; Document report; Document tempDocument; View view; String temp; reportDatabase = agentContext.getCurrentDatabase(); report = reportDatabase.createDocument(); report.replaceItemValue("Form" , "Memo"); report.replaceItemValue("Subject" , "Mail Applications Report"); RichTextItem richTextItem; richTextItem = report.createRichTextItem("Body"); 26 view = nab.getView("People"); personDocument = view.getFirstDocument(); while (personDocument != null) { Database mailDatabase; try { mailDatabase = session.getDatabase (personDocument.getItemValueString("MailServer"), personDocument.getItemValueString ("MailFile")); temp = "Mail Owner: " + personDocument.getItemValueString("FullName") + " Size: " + mailDatabase.getSize() + " _ bytes Template: " + mailDatabase.getDesignTemplateName(); mailDatabase.recycle(); } catch (Exception e) { temp = "Could not open mail file for: " + personDocument.getItemValueString("FullName") + " Server: " + personDocument.getItemValueString ("MailServer") + " , " + personDocument.getItemValueString("MailFile"); } richTextItem.appendText(temp); richTextItem.addNewLine(1); temp = ""; tempDocument = view.getNextDocument(personDocument); personDocument.recycle(); personDocument = tempDocument; } report.send(false, "Enter_Email_Address_Here"); if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (nab != null) nab.recycle(); if (reportDatabase !=null) reportDatabase.recycle(); if (personDocument !=null) personDocument.recycle(); if (report !=null) report.recycle(); if (view !=null) 27 view.recycle(); if (richTextItem !=null) richTextItem.recycle(); } catch(Exception e) { e.printStackTrace(); } } } Table 8 sums up the comparison. Table 8. Side-by-side comparison of Example 3 LotusScript Java Example 3: Generate a Report with Mail Database Information Example 3: Generate a Report with Mail Database Information Dim session As New Notessession Session session = getSession(); AgentContext agentContext = session.getAgentContext(); Dim nab As New Notesdatabase ("Enter_Server_Name_Here", "names.nsf") Database nab; nab = session.getDatabase ("Enter_Server_Name_Here","names.nsf"); Database reportDatabase; Dim reportDatabase As Notesdatabase Dim personDocument As NotesDocument Dim report As NotesDocument Document personDocument; Document report; Document tempDocument; View view; String temp; Dim view As NotesView Dim temp As String Set reportDatabase = session.CurrentDatabase Set report = reportDatabase.CreateDocument Call report.ReplaceItemValue("Form" , "Memo") Call report.ReplaceItemValue("Subject" , "Mail Applications Report") Dim richTextItem As New NotesRichTextItem (report, "Body") Set view = nab.GetView("People") Set personDocument = view.GetFirstDocument While Not personDocument Is Nothing On Error Resume Next Dim mailDatabase As New NotesDatabase( personDocument.mailserver(0), personDocument.mailfile(0)) If mailDatabase.IsOpen Then reportDatabase = agentContext.getCurrentDatabase(); report = reportDatabase.createDocument(); report.replaceItemValue("Form" , "Memo"); report.replaceItemValue("Subject" , "Mail Applications Report"); RichTextItem richTextItem; richTextItem = report.createRichTextItem ("Body"); view = nab.getView("People"); personDocument = view.getFirstDocument(); while (personDocument != null) { Database mailDatabase; try { mailDatabase = session.getDatabase( 28 temp = "Mail Owner: " & personDocument.fullname(0) & " Size: " & Cstr(mailDatabase.size) & " _ bytes Template: " + mailDatabase.DesignTemplateName personDocument.getItemValueString ("MailServer"), personDocument.getItemValueString ("MailFile")); temp = "Mail Owner: " + personDocument.getItemValueString ("FullName") + " Size: " + mailDatabase.getSize() + " _ Else bytes temp = "Could not open mail file for: " & Template: " + personDocument.fullname(0) & " mailDatabase.getDesignTemplateName(); Server: " & personDocument.mailserver(0) mailDatabase.recycle(); &" ," } catch (Exception e) { & personDocument.mailfile(0) temp = "Could not open mail file for: " + End If personDocument.getItemValueString ("FullName") + " Server: " + personDocument.getItemValueString richTextItem.AppendText(temp) ("MailServer") + " , " richTextItem.AddNewline(1) + personDocument.getItemValueString temp = "" ("MailFile"); Set personDocument = view.GetNextDocument(personDocument) } Wend Call report.Send(False, "Enter_Email_Address_Here") richTextItem.appendText(temp); richTextItem.addNewLine(1); temp = ""; tempDocument = view.getNextDocument (personDocument); personDocument.recycle(); personDocument = tempDocument; } report.send(false, "Enter_Email_Address_Here"); if (session !=null) session.recycle(); if (agentContext !=null) agentContext.recycle(); if (nab != null) nab.recycle(); if (reportDatabase !=null) reportDatabase.recycle(); if (personDocument !=null) personDocument.recycle(); if (report !=null) report.recycle(); if (view !=null) view.recycle(); if (richTextItem !=null) richTextItem.recycle(); 29 4 Other essentials Let's go over some other essential points relevant to our discussion of Java code and LotusScript. JVM versions. Unlike LotusScript, Java code is run on a Java Virtual Machine (JVM). Table 9 shows the JVM version that is shipped with the various Notes/Domino releases. Table 9. JVM and Notes/Domino versions Notes/Domino Version JVM Version 6.5.x 1.3.1 7.0.x 1.4.2 8.0.x 1.5.0 8.5 1.6.0 The JVM is installed during the normal client/server install and is independent from a JVM that can be installed on the operating system. The version is important when using classes provided by the JVM since there are differences between versions. The recycle() method. If you browse through the Domino classes in the Designer Help file, you will notice that each Java class has an additional method called the recycle method (there is no corresponding LotusScript method). The description of this method (from the Help file) states “The recycle method unconditionally destroys an object and returns its memory to the system.” We won't go into the importance of why you should call the recycle method because this topic is covered in detail in Lotus Support Technote #1097861, “Why it is important to use Recycle() method on every Java object.” Just remember that, to prevent memory leaks, you should ALWAYS call the recycle method on all Domino Java objects you create. Security exceptions. Since Java code is run on the JVM, there is an additional security layer for Java code that is not present when using LotusScript. Depending on the Java classes / methods being used, you may run into security exceptions such as the java.security.AccessControlException exception when running your Java code in Lotus Domino. If you do encounter security exceptions, you must explicitly grant access in the java.policy file of the JVM. For more information, see the Lotus Support Technote #1279509, “Security exceptions are encountered when developing Java agents.” Using external JAR files with Java agents. Similar to LotusScript .lss files, Java agents can use existing Java classes. If you have a JAR file with the Java classes you want to use, you can make these classes available to an agent by using one of the following three methods: 30 • Attach the JAR file to the agent itself: 1. Open the Java agent in Domino Designer and click “Edit Project”. 2. Select the directory in which the JAR file is located in the Base directory field. 3. Select and add the JAR file. • Copy the JAR file to the {Lotus Notes\Domino program directory}\jvm\lib\ext. • Use the JavaUserClasses Notes.ini variable; in your Notes or Domino Notes.ini file, add the variable and point to one or more JAR files, for example: JavaUserClasses=C:\jar_files\file1.jar;C:\jar_files\file2.jar NOTE: After making the JAR files available, you must use the import statement in the agent to refer to the specific class you want to use. 5 Conclusion Hopefully this paper has helped provide a bridge for the traditional Domino developer to begin developing Java agents in Domino Designer. The examples presented above can serve as template code in developing more extensive Java agents. Remember that the Domino Designer 8.5 Help file provides an extensive collection of Java examples for each Domino class. 6 Resources • The Java Tutorials • Lotus Domino Designer 8.5 Information Center, Java/CORBA Classes section • developerWorks Lotus Notes and Domino product page • IBM Lotus Notes/Domino 8.5 Forum • Lotus Notes and Domino wiki 7 About the author Oscar I Hernandez is a Staff Software Engineer with the IBM Lotus Technical Support organization. He is a member of the Application Development team for Lotus Notes/Domino and is an IBM Certified Advanced Application Developer. You can reach Oscar at [email protected]. 31 Trademarks • Domino, IBM, Lotus, LotusScript, and Notes are trademarks or registered trademarks of IBM Corporation in the United States, other countries, or both. • Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both. • Other company, product, and service names may be trademarks or service marks of others. 32