# JAddin Java Framework for HCL Domino (Open Source)

Java Toolkit for developers writing HCL Domino Server Add-ins

<a href="/download/download" class="button primary">Free Download</a>

{% hint style="info" %}
Follow development at Mastodon [#DominoJAddin](https://swiss.social/tags/dominojaddin)

This tool is also shown on the [*HCL Domino Marketplace*](https://hclsofy.com/domino)
{% endhint %}

## Introduction

The open-source JAddin framework serves as a lightweight and user-friendly layer between the HCL Domino RunJava task and your Java application code. It simplifies the creation of Java server tasks by abstracting the complexities of HCL Domino add-in development, such as message queue handling, thread management, console communication, and resource cleanup. Written entirely in Java, JAddin supports all HCL Domino versions and platforms starting from version 9.0.1 FP8 and above.

### **Code Example**

```java
public class HelloWorld extends JAddinThread {

	// Declarations
	boolean mustTerminate = false;
	
	// This is the main entry point. When this method returns, the add-in terminates.
	public void addinStart() {
		
		logMessage("Started");
		
		// Stay in main loop until main thread JAddin signals termination by calling addinStop() or issued Thread.interrupt()
		while (!addinInterrupted() && !mustTerminate) {
			logMessage("User code is executing...");
			waitMilliSeconds(5000L);
		}
		
		logMessage("Terminated");
	}

	// This method is called by the JAddin main thread when the console command 'Quit' or 'Exit' is entered or during
	// Domino server shutdown. Here you must signal the addinStart() method to terminate itself and to perform any cleanup.
	public void addinStop() {
		logMessage("Termination in progress");
		mustTerminate = true;
	}
	
	// This method is called by the JAddin main thread for any console command entered. It should return quickly to
	// avoid blocking the Domino message queue.
	@Override
	public void addinCommand(String command) {
		logMessage("Command entered: " + command);
	}
}
```

### **HCL Domino Console**

```
> Load RunJava JAddin HelloWorld
21.06.2025 14:01:26   JVM: Java Virtual Machine initialized.
21.06.2025 14:01:26   RunJava: Started JAddin Java task.
21.06.2025 14:01:26   HelloWorld: Started
21.06.2025 14:01:26   HelloWorld: User code is executing...
21.06.2025 14:01:31   HelloWorld: User code is executing...
21.06.2025 14:01:36   HelloWorld: User code is executing...
21.06.2025 14:01:41   HelloWorld: User code is executing...
> Tell HelloWorld Quit
21.06.2025 14:01:50   HelloWorld: Termination in progress
21.06.2025 14:01:51   HelloWorld: Terminated
21.06.2025 14:01:53   RunJava: Finalized JAddin Java task.
21.06.2025 14:01:54   RunJava shutdown.
```

### **Prerequisites**

* HCL Domino 9.0.1 FP8 or higher (Java Virtual Machine 1.8+ requirement)

### Credits

Photo by [Markus Spiske](https://unsplash.com/ja/@markusspiske?utm_source=unsplash\&utm_medium=referral\&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/de/s/fotos/java-programming?utm_source=unsplash\&utm_medium=referral\&utm_content=creditCopyText)

### **Author**

This framework was created to support projects that require the use of HCL Domino server add-ins. If you encounter any issues or have suggestions for improvement, please feel free to reach out.

You may contact me thru my email address <andy.brunner@k43.ch>.

### **Unlicense (see** [**Wikipedia:Unlicense**](https://en.wikipedia.org/wiki/Unlicense)**)**

> Created with love and passion in the beautiful country of 🇨🇭 Switzerland. This software is intended to be used for good—not evil. And to the best of my knowledge, no animals were harmed in its creation. 😊


# Installation

How to install the JAddin framework

## 1. Prerequisites <a href="#id-1-prerequisites" id="id-1-prerequisites"></a>

* HCL Domino 9.0.1 FP8 or higher (Java Virtual Machine 1.8+ requirement)

{% hint style="warning" %}
To avoid out-of-memory errors in the Java Virtual Memory (JVM), make sure the JVM heap size is set to at least 256 MB in the Notes.ini on the HCL Domino server, e.g. `JavaMaxHeapSize=256MB`
{% endhint %}

## 2. Installation <a href="#id-2-installation" id="id-2-installation"></a>

* [Download](/download/download) and unzip the installation package.
* Copy the `JAddin.class` and `JAddinThread.class` from the installation package to your development environment.
* Copy the `notes.jar` file from your HCL Notes or HCL Domino installation to your development environment.

## 3. Application Distribution <a href="#id-3-application-distribution" id="id-3-application-distribution"></a>

To distribute and install your add-in, you must create a JAR container which includes:

* a valid `MANIFEST.MF` file&#x20;
* The framework files `JAddin.class` and `JAddinThread.class`.
* Your application class (e.g. `AddinName.class`)

### **MANIFEST.MF**

Make sure that the last line of the file is terminated with a newline character.

```
Manifest-Version: 1.0
Class-Path: .
Main-Class: AddinName
```

### **JAR container**

There are several tools available to create JAR containers. The easiest way is to use the command line.

`jar cvmf MANIFEST.MF AddinName.jar AddinName.class JAddin.class JAddinThread.class`

This example creates a new `AddinName.jar` file with the application `AddinName.class` and the two JAddin framework files.

### **Install Application**

Copy the JAR container to the `domino/ndext` directory. This directory is automatically searched by the RunJava task for any Java classes to load.

## 4. Run Application <a href="#id-4-run-application" id="id-4-run-application"></a>

There are several ways to start the application:

#### **Option 1: Program Document**

The easiest and recommended way is to add a program document in the HCL Domino directory.

![Sample Program Document](https://3024637945-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-MRfU0Pp7UVc4GlFJVf7%2F-MS2yab1ES7SDHSvQ0Pw%2F-MS2zHU04KU0Fkt-BN01%2FJAddin-Program-Document.png?alt=media\&token=fd02130a-3318-4999-bbce-990a67739fe1)

#### **Option 2: Console Command**

Enter the command `Load RunJava JAddin AddinName` in the HCL Domino console.

```
> Load RunJava JAddin HelloWorld
21.06.2025 14:01:26   JVM: Java Virtual Machine initialized.
21.06.2025 14:01:26   RunJava: Started JAddin Java task.
21.06.2025 14:01:26   HelloWorld: Started
21.06.2025 14:01:26   HelloWorld: User code is executing...
21.06.2025 14:01:31   HelloWorld: User code is executing...
21.06.2025 14:01:36   HelloWorld: User code is executing...
21.06.2025 14:01:41   HelloWorld: User code is executing...
> Tell HelloWorld Quit
21.06.2025 14:01:50   HelloWorld: Termination in progress
21.06.2025 14:01:51   HelloWorld: Terminated
21.06.2025 14:01:53   RunJava: Finalized JAddin Java task.
21.06.2025 14:01:54   RunJava shutdown.
```

#### **Option 3: Notes.ini**

You may change the line starting with `ServerTask=` to include the task to be started, e.g.

`ServerTasks=Replica,Router,Update,RunJava JAddin AddinName,AMgr,...`


# Debugging Tips

Hints and tips on the usage of the JAddin framework

## Common Error Messages

| Error Message                                                                                                               | Possible Reason                                                                                                                                                             |
| --------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `RunJava: Can't find class AddinName lotus/notes/addins/jaddin/AddinName in the classpath. Class names are case-sensitive.` | The RunJava task was unable to load the class. Make sure that it is written with exact upper and lower case characters and it can be found by the RunJava class loader      |
| `JAddin: Unable to load Java class AddinName`                                                                               | The JAddin framework was unable to load the application class. Make sure that it is written with exact upper and lower case characters.                                     |
| `RunJava: Can't find stopAddin method for class AddinName.`                                                                 | The application class must be loaded thru the JAddin framework and not directly from RunJava. Use the command `Load RunJava JAddin AddinName` to start your application.    |
| `RunJava JVM: java.lang.NoClassDefFoundError: AddinName (wrong name: addinname)`                                            | The user class name in the command and the internal name do not match. Most likely you have not typed the name with correct upper and lower case characters.                |
| `Out of memory`                                                                                                             | All Java add-ins execute in a single Java Virtual Machine (JVM) in RunJava. The Domino Notes.Ini parameter `JavaMaxHeapSize=xxxxMB` may be used to increase the heap space. |

## HCL Domino Statistics <a href="#id-3-domino-statistics" id="id-3-domino-statistics"></a>

During execution, the JAddin maintains statistics and status information. They can be displayed with the `Show Stat AddinName` command:

```
> Show Stat HelloWorld
  HelloWorld.Domino.Platform = 6.2 (Windows 8)
  HelloWorld.Domino.Version = Release 14.5|June 06, 2025 (Windows/64)
  HelloWorld.JAddin.StartedTime = 2025-06-21T12:03:39Z
  HelloWorld.JAddin.VersionDate = 2025-06-21
  HelloWorld.JAddin.VersionNumber = 2.2.1
  HelloWorld.JVM.HeapLimitKB = 262'144
  HelloWorld.JVM.HeapUsedKB = 20'775
  HelloWorld.JVM.Version = 21.0.6 (IBM Corporation)
  8 statistics found
```

## Console Help Command

The framework supports a number of special commands:

```
> Tell HelloWorld Help!
21.06.2025 14:04:17   JAddin: Quit!       Terminate the add-in thru the framework
21.06.2025 14:04:17   JAddin: Debug!      Enable the debug logging to the console
21.06.2025 14:04:17   JAddin: NoDebug!    Disable the debug logging to the console
21.06.2025 14:04:17   JAddin: Heartbeat!  Manually start heartbeat processing (automatically done every 15 seconds)
21.06.2025 14:04:17   JAddin: Help!       Displays this help text
```

## Debugging

For a detailed problem determination, you may use the built-in debugging features.

### Enable/Disable Debug

| Domino Console Command                 | Description                                      |
| -------------------------------------- | ------------------------------------------------ |
| `Load RunJava JAddin AddinName Debug!` | Start add-in in debug mode                       |
| `Tell AddinName Debug!`                | Start the debug mode while the add-in is running |
| `Tell AddinName NoDebug!`              | Stop the debug mode while the add-in is running  |

{% hint style="warning" %}
While active debugging adds a significant amount of data to the console log and to the log.nsf database, it can be helpful in finding the root of a problem.&#x20;
{% endhint %}

### Debug Output

The debug output is written to the HCL Domino console and includes the name of the Java method with the source line number issuing the message.

```
> Load RunJava JAddin HelloWorld Debug!
21.06.2025 14:05:01   JVM: Java Virtual Machine initialized.
21.06.2025 14:05:01   RunJava: Started JAddin Java task.
21.06.2025 14:05:01   JAddin: Enter 'Tell HelloWorld NoDebug!' to disable debug logging
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(430)                     JAddin framework version 2.2.1 / 2025-06-21
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(431)                     OS platform: 6.2 (Windows 8)
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(432)                     JVM version: 21.0.6 (IBM Corporation)
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(433)                     HelloWorld will be called with parameter: null
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(436)                     Creating and opening the Domino message queue
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(470)                     Loading Java class HelloWorld
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(491)                     Calling HelloWorld.addinInitialize()
21.06.2025 14:05:01   HelloWorld: DEBUG: HelloWorld.addinInitialize(108)      Entered addinInitialize()
21.06.2025 14:05:01   HelloWorld: DEBUG: HelloWorld.addinInitialize(127)      Domino version: Release 14.5 June 06, 2025 (Windows/64)
21.06.2025 14:05:01   JAddin: DEBUG: JAddin.runNotes(501)                     Calling HelloWorld.start()
21.06.2025 14:05:01   HelloWorld: DEBUG: HelloWorld.runNotes(875)             Entered runNotes()
21.06.2025 14:05:01   HelloWorld: DEBUG: HelloWorld.runNotes(888)             Calling HelloWorld.addinStart()
21.06.2025 14:05:01   HelloWorld: Started
21.06.2025 14:05:01   HelloWorld: User code is executing...
21.06.2025 14:05:06   HelloWorld: User code is executing...
21.06.2025 14:05:11   HelloWorld: User code is executing...
> Tell HelloWorld Quit
21.06.2025 14:05:15   JAddin: DEBUG: JAddin.getCommand(236)                   Termination in progress
21.06.2025 14:05:15   JAddin: DEBUG: JAddin.runNotes(539)                     JAddin termination in progress
21.06.2025 14:05:15   JAddin: DEBUG: JAddin.runNotes(544)                     Calling HelloWorld.addinStop()
21.06.2025 14:05:15   HelloWorld: Termination in progress
21.06.2025 14:05:16   HelloWorld: Terminated
21.06.2025 14:05:16   HelloWorld: DEBUG: HelloWorld.addinCleanup(62)          Entered addinCleanup()
21.06.2025 14:05:16   JAddin: DEBUG: JAddin.sendQuitCommand(673)              Sending Quit command to Domino message queue
21.06.2025 14:05:16   JAddin: DEBUG: JAddin.waitForThreadStop(765)            HelloWorld has terminated
21.06.2025 14:05:16   JAddin: DEBUG: JAddin.addinCleanup(123)                 Entered addinCleanup()
21.06.2025 14:05:16   JAddin: DEBUG: JAddin.waitForThreadStop(765)            HelloWorld has terminated
21.06.2025 14:05:16   JAddin: DEBUG: JAddin.addinCleanup(140)                 Freeing the Domino resources
21.06.2025 14:05:17   RunJava: Finalized JAddin Java task.
21.06.2025 14:05:18   RunJava shutdown.
```

## Frequently Asked Questions <a href="#id-6-frequently-asked-questions" id="id-6-frequently-asked-questions"></a>

**Q: How do I develop my JAddin project in Eclipse?**\
A: Ensure that you include the two JAddin framework class files and the notes.jar file (installed with HCL Notes or HCL Domino) as external libraries in your Eclipse project.

**Q: What is the heartbeat in JAddin?**\
A: The main thread in JAddin is triggered every 15 seconds to perform internal housekeeping tasks. One of these tasks monitors Java heap usage to help prevent out-of-memory errors. It also checks whether the user thread has terminated unexpectedly.

**Q: I have copied a new version of my add-in to the server, but it does not become active during application startup. Why?**\
A: The RunJava task caches Java classes in memory. To reload your updated class file, you must terminate all other RunJava tasks—effectively stopping RunJava itself—before restarting it.


# Architecture

Some background information on the framework architecture

## Framework Architecture <a href="#id-1-framework-architecture" id="id-1-framework-architecture"></a>

The JAddin architecture consists of two Java classes which are distributed with your application code.

<figure><img src="https://3024637945-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MRfU0Pp7UVc4GlFJVf7%2Fuploads%2Fk4zOKVsCpGEp26ErWgZz%2FJAddin-Architecture.png?alt=media&amp;token=f65d3350-6273-4360-b3d2-820d14c7c522" alt=""><figcaption></figcaption></figure>

### **JAddin.class**

The JAddin class is loaded by the HCL Domino RunJava task as the main Java thread. It executes under the control of RunJava and shares the HCL Domino Java Virtual Machine (JVM) with RunJava.

Main functions of JAddin thread:

* Initialize the JAddin framework
* Dynamically loads and starts the user add-in as a subclass of JAddinThread
* Monitors the Java heap space
* Acts on special framework commands (see command `Help!`)
* Supports internal debugging thru `Debug!` command
* Backcalls the user methods `addInXXX()` (see below)

### **JAddinThread.class**

This abstract class must be implemented by the user add-in class. It runs as a separate thread to minimize any delays on the normal processing of the HCL Domino server.

* Initialize the runtime environment
* Calls the user class thru addinStart()
* Includes several methods for accessing HCL Domino objects and the server environment

### **AddinName.class**

The user code runs within a subclass of JAddinThread and handles all application-specific processing. The framework invokes several callback methods that can or must be implemented by the user class. When the user class completes execution, the framework performs the necessary cleanup and terminates the main JAddin thread.

| **Method**         | **Required** | **Description**                                       |
| ------------------ | ------------ | ----------------------------------------------------- |
| addinStart()       | Yes          | Main entry point of the application code              |
| addinStop()        | Yes          | Called before termination                             |
| addinInterrupted() | No           | Returns true if main thread issued Thread.interrupt() |
| addinNextHour()    | No           | Called at each new hour                               |
| addinNextDay()     | No           | Called at each new day                                |
| addinCommand()     | No           | Called for any console command entered                |


# Download

How to download the JAddin framework

<details>

<summary>Planned for next version</summary>

* Minor code and document changes

</details>

### Version 2025.11.27

{% file src="/files/nWysAxps5F7iw5y8Lp74" %}

* Wait 10 seconds for subtask termination during shutdown before writing timeout message
* Change version number scheme from n.n.n to yyyy.mm.dd

### Version 2.2.1 2025-06-21

{% file src="/files/KseLiylXlkWtfMelnLim" %}

* Added *addinInterrupted()* to check if main task JAddin requests shutdown (see example code)
* Overall code refactoring and cleanup

### Version 2.2.0 2025-06-16

{% file src="/files/Awl2VC4gRHfQRNM7NevM" %}

* Optimize thread termination and Domino resource cleanup
* Removed command 'gc!'
* Added warning message if Java heap size is >90% used

### Version 2.1.4 2024-09-03

{% file src="/files/ZnKlpEEaFTCiJgiBKv2z" %}

{% hint style="warning" %}
Starting with version 2.1.4, the addinStop() method must be implemented to ensure proper termination of the add-in. During shutdown—either triggered by the server or manually—the main JAddin thread invokes addinStop() and, if necessary, issues a Thread.interrupt() to stop running threads. Note that the Domino server may not shut down cleanly if background threads remain active.
{% endhint %}

* Support for JVM Java 17 (used in HCL Domino 14.5 and higher)

### Version 2.1.3 2023-09-11

{% file src="/files/BXdch3tYcmz2JUBqDdMO" %}

* Remove JVM version check
* Project web page moved to <https://jaddin.k43.ch>
* Added architecture diagramm in documentation

### **Version 2.1.2 2021-01-25**

{% file src="/files/-MS25ezVix3XMyeGGARb" %}
Download
{% endfile %}

* Change: Show OS, JVM and Domino versions on console in debug mode
* Change: Add Domino statistic “AddinName.JVM.HeapUsedKB”
* Documentation: The documentation has been updated and moved to GitBook.

### **Version 2.1.1 2019-03-07**

{% file src="/files/-MS25gkDYGOG5-aeVVW0" %}
Download
{% endfile %}

* Change: dbSendMessage now uses mail1.box if mail.box is not present

### **Version 2.1.0 2019-02-03**

{% file src="/files/-MS25hnCpen5wkntQtMI" %}
Download
{% endfile %}

* Added static methods JAddin.fromISODateUTC() and JAddin.toISODateUTC()
* Added method generateHash(), encryptAES(), decryptAES(), fromBase64 and toBase64()
* Changed method dbSendMessage() to always create a MIME message
* Changed method dbRecycleObjects() to better support arrays and vectors
* Changed Domino statistic to show date in UTC ISO 8601 format
* JavaDoc changes

### **Version 2.0.0 2019-01-16**

{% file src="/files/-MS25idVBLxR0heKsG4R" %}
Download
{% endfile %}

* Major rewrite of JAddin.java and JAddinThread.java
* Now requires JVM 1.8+ (Domino 9.0.1 FP8+)
* Many new and changed methods to support applications
* Complete rewrite of the documentation and publish it on GitHub
* Create project homepage at <https://jaddin.k43.ch>

### **Version 1.3.0 2016-03-24**

* Beta Version for selected customers
* Change: Replace the Thread termination sequence by Thread.interrupt()
* Change: Mark addInTerminate() as deprecated
* Change: Small change in sendMessage() for processing sender name
* Add: New method waitSeconds() to delay execution
* Add: New method recycleObjects() to free Domino object resources
* Add: New documentation chapter to explain program flow

### **Version 1.2.0 2013-12-18**

* Add: New command “Version!” to display JAddin, Java and OS version numbers.
* Change: Send the low heap memory warning message only once for each threshold reached.

### **Version 1.1.0 2012-07-18**

* Add: New methods addinNextHour() and addinNextDay() to allow for notification of next hour and next day.
* Change: Several runtime optimizations.

### **Version 1.0.0 2012-04-28**

* Add: First formal version
* Add: New method sendMessage() to create and send a message.

### **Version 0.5.0 2010-08-22**

* New: First public beta version.


