Home > Articles

Java Agents, Applets, and Applications

  • Print
  • + Share This

Java Agents, Applets, and Applications

In This Chapter

  • Setting Up the Java Environment

  • Java Standalone Applications

  • Java Applications and Multithreading

  • The Session Class

  • Java Agents, Servlets, Applets, and Applications

In this chapter, I present some important information about Java and some specific Java classes such as the Applet class, and show how Domino relates to these classes. This is an important chapter to read and understand before you read the rest of the chapters in Part III, "Using Java with Notes and Domino" as well as before Part IV, "The Domino Objects for Java." Both Part III and Part IV assume you understand the concepts in this chapter.

Setting Up the Java Environment

If you are serious about using Java with Domino, you should consider a separate third-party development environment for Java. Although Lotus has made great strides with release 5, Java support in Domino is suitable only for developing agents. To develop applets, servlets, or many other Java programs, you will need a third-party IDE. In Chapter 14, "Using the Domino Designer and Third-Party IDEs with Java," I describe two specific development tools: IBM's Visual Age for Java and Symantec's Visual Café.

There are many Java development environments, and you can probably choose any of them. Here are a few: IBM Visual Age for Java, Inprise (the company formerly known as Borland) Jbuilder, Symantec Visual Café, and Java Workshop from Sun. There are probably hundreds of other options, and you can even download Sun's Java Development Kit (JDK) free from the Web at http://www.java.sun.com. Sun's JDK package is extremely minimal, however, and you'll probably want a real development environment for serious work.

A Java Overview

Java was originally conceived by Sun Microsystems as a language for embedded controllers (for example, a device such as the one in your microwave oven). This language became extremely popular with the advent of the Web and because Netscape included it in its browser. It has quickly evolved, however, and now there are probably millions of Java programmers around the world.

Of course, you know that one of the main advantages of Java is that it is operating system–independent and hardware platform–independent. Sun's mantra is "write once, run anywhere." But how, exactly, does Java achieve this feat technically? The answer lies in another term that you might have heard: the Java Virtual Machine, or JVM. The JVM is a software program that simulates a real machine. The JVM accepts, as input, binary opcodes in files that have been prepared by a Java compiler. This set of binary opcodes corresponds to the machine-language codes that are used by traditional hardware, such as the Intel Pentium.

The binary codes are stored in files on the host operating system in class files. Groups of class files can be stored in a directory in the operating system, or they can be collected in a single file called an archive. Several kinds of archive files are available: JAR files, CAB files, and ZIP files. ZIP is a standard format for compressing a group of files and saving them as a single file. This extension is not normally used anymore, however, because it was confusing for some users who thought the ZIP files needed to be uncompressed. JAR files are the standard format for Java archives and are stored internally with the same format as ZIP files. CAB files (short for cabinet) were created by Microsoft and are used by its Internet Explorer and the Microsoft JVM.

Java achieves its machine and operating system independence by specifying the standardized format for class files, archives, and the machine operations contained in the class files. There are several implementations of Java Virtual Machines. Each of the major Web browsers, as well as Notes and Domino, contains a JVM, and you can run standalone JVMs as well. A standalone JVM comes with Sun's JDK. With a standalone JVM, you can write a Java application that does not depend on a Web browser.


Here is a tidbit for those of you interested in Java trivia that you can use to impress your friends. The creators of Java used a hexadecimal magic number in the first four bytes of a Java class file. This is so the JVM can do an integrity check on the file before trying to execute it. Because the magic number is an arbitrary number, they used the hexadecimal value CAFEBABE. Although this is a valid hexadecimal value, it's also pretty cute. Use a hexadecimal editor to look at a Java class file sometime. Then you can go impress your friends.


So now we have a JVM and a class file that contains binary opcodes. Is there anything else we need? Well, yes, of course. The class file that you have developed probably needs to allocate and manage resources, such as memory and data. It probably needs to interact with a user through a user interface. There should be some capability of communicating over a network, and you must have security programs. You probably don't want to write all this kind of code. Normally, these types of services are provided by an operating system. Well, we're in luck.

An entire library of programs has been written in Java, and the programs are included in archive files that are distributed with the Java environment. They perform many of the routine tasks that are normally provided by any operating system environment. There is only one problem: How does the JVM find these files? The answer is the CLASSPATH environment variable.


This section describing the CLASSPATH environment variable applies to version 1.1.x of the Java Development Kit. This is the version that ships with Notes and Domino. In Java version 2.0, class files are treated differently, as described in the next section.

The CLASSPATH environment variable is actually similar in concept to the PATH variable that you might remember from the old days. The CLASSPATH variable tells the JVM where to find additional classes that are not included in the currently running class. Standard classes for user interface and many other functions are included in these libraries. In addition to the standard libraries, you can write your own Java programs, store them in archives, and include them in the CLASSPATH. Lotus, in fact, has done this for many of the support functions required for Notes and Domino. Thus, to use these Lotus-written Java programs, you must include the Lotus archives in your CLASSPATH (for the Java development tool's use).

When Notes or Domino JVM is running, it actually uses an internal CLASSPATH variable. Notes and Domino do not use the CLASSPATH environment variable. Domino is automatically capable of finding its own Java programs, such as those that implement the Java Domino Objects. In addition, it is capable of automatically finding Java programs that are stored as agents within databases.

For your own custom classes that are not agents, however, Domino uses its own internal CLASSPATH variable. The internal class path is specified in the Notes.ini file and has the name JavaUserClasses. In order for Notes or Domino to be able to find any custom classes you write that are not stored within a database, you must be sure to modify the JavaUserClasses variable in Notes.ini. Here is an example:


You can specify more than one directory and separate them with semicolons.

If you get an error message during development that your classes cannot be found, check to make sure that you have set the JavaUserClasses variable in Notes.ini. Setting the regular CLASSPATH environment variable, although probably required for your Java IDE, will not be sufficient for Notes and Domino.

Java Development Kit Versions

If you program a Windows application in C++, there are three separate and distinct concepts to work with: the programming language itself (C++), the compiler tool, and the Windows Application Programming Interface (API). These same three concepts apply to Java programming. You need to know the Java programming language, you must have a particular Java programming/compiler tool, and you need a programming API. The programming API is supplied by Sun Microsystems in the Java Development Kit (JDK), but it is almost always also supplied by the Java tool vendor when you purchase a Java programming tool.

The Java Development Kit provides an API that contains many of the programming features of a windowing operating system such as Windows. This is perhaps one of the reasons why Microsoft wants to portray Java as just a programming language. Although Java is a language, the JDK supplies the capability to create windows and buttons, use networking, access databases, and many of the other features that we take for granted in Microsoft Windows. In addition, you can use the JDK on top of Windows, UNIX, Macintosh, or any other platform that supports the JVM. This includes Notes and Domino.

The JDK from Sun has undergone many revisions. At the time this is being written, two versions are available: JDK 1.1.x and JDK 2.0. The 1.1.x version is shipped with Notes and Domino due to the cycle of testing and quality assurance that goes into Domino before release. Java version 2.0 was announced by Sun on December 8, 1998, so there was not enough time to certify the Domino code with Java version 2.0, but I expect that it will be supported soon after it can be tested. Release 5.0.2 of Domino supported JDK 1.1.8, but this will definitely change over time, so refer to the release notes for your particular version of Domino for the current JDK version.

Many new capabilities are in version 2.0, including security enhancements and the inclusion of the Java Foundation Classes (JFC). The JFC includes the Swing components, the Java 2D graphics interfaces, drag-and-drop, accessibility, and many other application services. The Swing user interface components are an enhancement to the original Abstract Windowing Toolkit (AWT) found in version 1.1 of the JDK. Although the AWT still works for compatibility, the Swing set of components is essentially a replacement.

As mentioned, in version 2.0, the CLASSPATH environment variable holds a less prominent role. In version 1.1.x, the setting of this variable caused a lot of setup problems (and is why I described it in the previous section). With version 2.0, system classes are found automatically by the JVM.

Java Classes, Packages, and Archives

All programs in Java are a part of some class. Classes, as we have seen, are written in the Java source code language and then are translated to class files. Class files consist of machine-independent byte codes. The class file byte codes essentially represent machine operations to the Java Virtual Machine and are the instructions that get executed by the JVM.

As you might imagine, when you are doing large-scale development, you will quickly find that you need some methods to organize your class files, because you can quickly get hundreds of files to organize and manage.

Packages are hierarchical groupings of class files. They are logical groupings and can be implemented physically in different ways. One simple and common way to organize the files in a package is with an operating system file directory structure. You simply use the hierarchical nature of file folders (directories) containing other nested folders to implement a hierarchical structure.

In Java, names are specified by a combination of identifiers and periods. The rightmost name represents the classname. All the other qualifiers in the name represent the package. For example, in java.lang.Object, java.lang represents the package name, and the name Object represents the classname. In the name java.awt.event.ActionEvent, the name ActionEvent is the classname and java.awt.event is the package name. The Java naming convention uses an initial capital letter for class names and all lowercase letters for package names.

If you have the packages java.awt, java.awt.datatransfer, java.awt.event, java.awt.image, and java.awt.peer, you can imagine a directory folder structure that could accommodate this:


In this case, there can also be other packages below the java level, such as java.io, java.lang, and java.net. When you have such a directory structure, all the classes in the java.awt.event package, for example, are stored in the directory that corresponds to that package.

When you are working by yourself on a small project, this structure is probably fine. You have everything you need, and it is all visible and easily accessible. However, suppose you are developing a large system and there are hundreds of components. It soon becomes much harder to manage multiple user access to hundreds of different files. Because of this, archive files were developed.

The original archive file format for Java was a ZIP file. This type of file was a de facto standard around the Internet, and many or most PC users have some sort of program, such as pkzip, pkunzip, or winzip, to create and extract files from ZIP files. By using a ZIP format, all the class files can be incorporated in a single file in the operating system. Also, the directory structure within the file can be preserved so that you can still have the hierarchical nature of the packages.

It was soon discovered, however, that users of these ZIP files did not realize that you could use the files within the ZIP archive and that you did not need to unzip the files for them to be used by Java. So a new format was created called the Java Archive (JAR) file. This essentially was just another name for a ZIP file, and all the ZIP file utilities can be used to create and extract from these files also. The only difference is that a JAR file should also contain a manifest file, which is like a table of contents and enables the members of the JAR file to have attributes. The attributes are stored within the manifest file in the JAR.

Finally, Microsoft decided that it wanted a format that was unique to its products. It already had a format called CAB, which stands for cabinet. It incorporated the CAB file format with its Internet Explorer. CAB files have an advantage in that they have a better compression algorithm, so the files are smaller. They have a disadvantage in that the files are in a Microsoft proprietary standard format and might not be supported on platforms other than Windows. If a product does support the CAB file format, it probably provides the same functionality as the JAR format.

For package files that are widely distributed, the packages should follow a naming convention outlined in the Java language specification. If two packages from different sources by chance have the same name, a user might have a very limited ability to fix the problem because the source code might not be available. As a result, the following naming convention is used to name Java classes. If the company producing the Java code has an Internet domain name, the first two levels of the package name should use them in reverse order. For example:






The highest-level qualifiers of Java and Javax are reserved by JavaSoft for standard libraries and extensions, so you should never name your classes beginning with these names. If you do not want to follow the standard naming convention and your packages do not begin with the domain type, you should probably at least use your company name as the high-level qualifier, as in




Sun recommends that if you are creating packages, the first letter of your package should be lowercase. Classes, on the other hand, should typically begin with an uppercase letter. Thus, in the package java.applet, you find the class Applet. The fully qualified name of the class is java.applet.Applet.

There are no #include statements in Java. In C and C++, you use the #include statement to include additional source code modules. In Java, you use the import statement to accomplish a similar effect. The purpose of the Java import statement is slightly different than the #include statement of C++, however. The purpose of the Java import statement is to allow your programs to use a shorthand notation.

You can import a single class or an entire package. Here are some examples:

import java.awt.Graphics;
import java.applet.*;
import lotus.domino.*;

The first import statement is importing a single class, and the second two statements are importing entire packages. The last two import statements allow a shorthand for all the classes in the respective packages.

You could refer to the Applet class as

public class MyApplet extends java.applet.Applet

or, if you have done the import, you can refer to the class as

public class MyApplet extends Applet

You can always refer to classes by their fully qualified names, so importing classes is not strictly required in any program, but it can make the program much more legible. You do not need to import the java.lang package, because all methods in that package are imported by default. The controlling factor on whether a class is found is the class path.

Java Exception Handling

Like C++, Java uses exception handling to handle runtime errors that occur in programs. In C++, exceptions were added as an innovation after the language was already in use, and as a result, many C++ programs do not use exceptions. In contrast, Java has had exceptions since its origin, so you will probably find that most—if not all—Java programs use the exception-handling model. In fact, Java compilers will complain if an exception is possible but there is no code to handle the exception.

Exception handling involves the use of several different statements and objects. The essence of exception handling is that you group statements that might potentially cause an exception (including within called subroutines), and then if one occurs, you can catch it and handle it. Syntactically you use the try-catch statement for grouping. Here is the full syntax:

try {
  // This is the try block. Normal program statements are here
  // If an exception occurs, this block may be left early.
catch (Exceptiontype1 e1) {
  // This block catches exceptions of type Exceptiontype1
catch (Exceptiontype2 e2) {
  // This block catches exceptions of type Exceptiontype2
// More catch clauses can appear here

finally {
  // Here are statements that will be executed in all cases.
  // This block will execute whether or not there is an exception.

Exceptiontype1 and Exceptiontype2 represent classes that are derived from (that is, they extend either directly or indirectly) the Throwable class. I'll explain shortly how they are used.

You can have as many different types of exceptions as you want to handle. The finally clause does not appear within C++. This is a very useful clause for cleaning up anything you initialize in the try clause. It is better to clean up in the finally clause than a catch clause, because then the cleanup will occur in both the error and nonerror cases. In the error case, the finally clause will be executed after the catch clause.

An exception is created with the throw statement. The syntax for the throw statement is

throw expression;

The expression must result in an object of the class Throwable. All exceptions are extended from this class. You can create your own exception classes, and throw and catch the exceptions. This technique is useful whenever you have a program that might detect an error situation several levels deep within subroutines, but if an error occurs, you want the program to "unwind" to a higher-level routine for processing. Java provides a language mechanism to do this gracefully without resorting to return codes.

Any exceptions that are generated by Notes or Domino use the NotesException class. This class extends the java.lang.Exception class and contains two fields: id and text. You can refer to these fields within the exception handler (the catch block). Here is an example:

try {
  ... Statements ...
catch (NotesException e) {
  System.out.println("NotesException: " + e.id + " ... " + e.text);
catch (Exception e) {

This code prints out the Notes error code and message along with the standard Java stack trace. For exceptions other than a NotesException, only the stack trace is printed.


In release 4.6 of Notes and Domino, you used the getErrorCode method to extract the error code from the NotesException class. This method is no longer available. In release 5, you must use the id and text fields. Symbolic names for the codes may be found in the NotesError class.

  • + Share This
  • 🔖 Save To Your Account

Related Resources

There are currently no related titles. Please check back later.