Thursday, July 10, 2025

XPages Rendering Issue to Be Fixed in Domino 14.5 FP1

If you’ve recently upgraded your Domino server to version 14.5, and you’re working with XPages, you may have encountered a frustrating issue: broken rendering in certain views or components. This bug has been affecting a number of applications, particularly those that rely on partial refresh or dynamically rendered controls.

HCL has officially acknowledged this issue and published a knowledge base article detailing the problem. According to the article (KB0122228), the issue is caused by a regression introduced in recent versions of the XPages runtime, and it affects how JavaScript resources are handled during page rendering.

Good news: a fix is coming soon!

HCL plans to resolve this issue in Domino 14.5 Fix Pack 1 (FP1). If you're running into problems with XPages after upgrading, you’ll want to keep an eye out for this upcoming fix pack.

In the meantime, if your applications are mission-critical and you're stuck with broken UI elements, consider temporarily rolling back to a stable version or using workarounds such as disabling dynamic rendering or tweaking partial refresh logic where possible.

Wednesday, April 02, 2025

Generating PDF Documents in Domino Using PD4ML Java Library

Generating PDF documents from web content or structured data is a common requirement in many applications. When working with HCL Domino, we often need to create PDFs from HTML templates, Notes documents, or dynamically generated content. In this article, I'll walk you through using the PD4ML Java library to generate PDFs within a Domino Java Agent.

Why Use PD4ML?

PD4ML is a powerful Java library that allows you to convert HTML and CSS into high-quality PDF documents. It supports:

  • CSS styling
  • Page breaks and headers/footers
  • Embedded images
  • Table of contents and bookmarks
  • Various output formats (A4, Letter, etc.)

This makes it a great choice for generating invoices, reports, or any structured documents from Domino applications.

Setting Up PD4ML in Domino

To use PD4ML in your Domino environment, follow these steps:

1. Download PD4ML

Get the PD4ML JAR from pd4ml.com. You can use the free or commercial version, depending on your needs.

2. Add PD4ML to Your Domino Project

  1. Place the PD4ML JAR file in the jvm/lib/ext directory of your Domino server (if you want it available for all agents) or within your NSF under WEB-INF/lib (if used in an XPages app).
  2. If using a Java agent, attach the JAR to the agent's Build Path (I usually create a dedicated Java library for external JARs).

3. Write a Java Agent to Generate a PDF

Below is just a snippet to get an idea what you need to do in your Domino Java Agent. The example takes an HTML string and converts it into a PDF:

PD4ML pd4ml = new PD4ML();

String html = "TEST <b>Hello, World!</b>";
ByteArrayInputStream bais = new ByteArrayInputStream(html.getBytes());

// read and parse HTML
pd4ml.readHTML(bais);

File pdf = File.createTempFile("result", ".pdf");
FileOutputStream fos = new FileOutputStream(pdf);

// render and write the result as PDF
pd4ml.writePDF(fos);

PD4ML and HCL Notes/Domino

PD4ML claims they provide support for converting HCL Notes documents into PDFs (I have never checked it though), making it an ideal solution for Domino applications.

Using PD4ML in HCL Domino makes PDF generation straightforward. Whether you need to create reports, invoices, or structured documents, this Java library is a flexible and efficient solution. Try it out in your Domino projects and let me know if you run into any issues!

I have previously used iText and Apache PDFBox for generating PDFs in Domino, as well as various external tools that convert HTML files into PDFs. However, I found PD4ML to be the most user-friendly solution due to its seamless integration with HTML and CSS, built-in support for page formatting, and its ability to handle embedded images and styles with minimal effort.


What tools or libraries do you use in your Domino applications to build PDF files?

Tuesday, September 17, 2024

Implementing SSO Authentication with Saml Using LotusScript & Java

Introduction

SAML (Security Assertion Markup Language) is a widely used protocol for Single Sign-On (SSO), allowing users to authenticate once and access multiple applications. In this article, we'll walk through implementing SAML authentication in a Domino application, detailing the steps needed to provide metadata, make the SSO call, and handle the assertion response (ACS call).

Prerequisites

Before you begin, ensure you have:

  • Access to a SAML Identity Provider (IdP) such as Microsoft Azure AD or Okta.
  • Basic knowledge of Java and HTTP requests.
  • A configured Domino server with the capability to execute Java agents.

Step-by-Step Implementation

1. Providing Metadata

The first step in setting up SAML authentication is to provide metadata that the Identity Provider (IdP) and Service Provider (SP) can use for configuration. You’ll need to supply both IdP and SP metadata to the Domino application.

Basically it means you will need to make 2 public URL: https://yourdomain.com/meta/{id} that provide XML response (and that will be used by IdP) and additionally to that IdP sohuld provide their URL you are going work with.

You also need to find a suitable Java library that can provide your a SamlClient (I use https://github.com/lastpass/saml-sdk-java)

2. Making the SSO Call

Once the metadata is set, you can make the SSO request to the IdP. Here’s the code that generates the SAML authentication request and sends it to the IdP.

String idpURL = config.getItemValueString("IdPURL");
idpMeta = new URL(idpURL).openStream();

String spData = config.getItemValueString("MetaXML");
spMeta = new ByteArrayInputStream(spData.getBytes(StandardCharsets.UTF_8));

// 2. initialize saml client
SAMLInit.initialize();
IdPConfig idpConfig = new IdPConfig(idpMeta);
SPConfig spConfig = new SPConfig(spMeta);
SAMLClient client = new SAMLClient(spConfig, idpConfig);

// 3. send login request
String requestId = SAMLUtils.generateRequestId();
String authrequest = client.generateAuthnRequest(requestId);
String url = client.getIdPConfig().getLoginUrl() + "?SAMLRequest=" + URLEncoder.encode(authrequest, "UTF-8");

The SAMLClient is used to generate the authentication request, and the resulting URL is the login endpoint where the user must be redirected.

3. Handling the Assertion Consumer Service (ACS) Call

After the user is authenticated by the IdP, the SAML response is sent back to the Domino server via the Assertion Consumer Service (ACS) endpoint. The following code handles this response and extracts user attributes from it.

String authresponse = web.getParam("AuthResponse");
String idpURL = config.getItemValueString("IdPURL");
String spData = config.getItemValueString("MetaXML");

SAMLInit.initialize();
IdPConfig idpConfig = new IdPConfig(idpMeta);
SPConfig spConfig = new SPConfig(spMeta);
SAMLClient client = new SAMLClient(spConfig, idpConfig);

AttributeSet aset = client.validateResponse(authresponse);
Map> attr = aset.getAttributes();
for (Map.Entry> entry : attr.entrySet()) {
    String key = entry.getKey();
    List values = entry.getValue();
    doc.replaceItemValue(key, new Vector<>(values));
}

This code validates the SAML response using the SAMLClient, extracts the attributes (such as username, email, etc.), and stores them in the Domino document.

Conclusion

Implementing SAML authentication in Domino involves configuring metadata for the IdP and SP, making an authentication request, and handling the ACS call to process the response. While this example uses the LastPass SAML library, similar methods apply when using other libraries. The overall process is straightforward and can greatly improve the security and convenience of user authentication in your Domino applications.

Monday, September 16, 2024

Implementing SSO Authentication with OpenID Using LotusScript

Introduction

Single Sign-On (SSO) simplifies the user authentication process by allowing users to log in once and gain access to multiple applications. OpenID Connect is an authentication layer on top of OAuth 2.0 that facilitates SSO. In this article, we'll walk through implementing SSO authentication using OpenID Connect with LotusScript.

Prerequisites

Before diving into the code, ensure you have:

  • Basic knowledge of LotusScript and HTTP requests.
  • Familiarity with OpenID Connect and OAuth 2.0.
  • Access to a Microsoft Azure AD tenant or another OpenID Connect provider.

Step-by-Step Implementation

1. Setting Up Your Environment

Make sure your Lotus Domino server is properly configured to handle HTTP requests and that you have access to your OpenID Connect provider's endpoints.

2. Retrieving the Access Token

The access token is obtained after the user successfully authenticates. I am pretty sure outdays most of developer know how to parse values from DocumentContext (fieldsÆ QUERY_STRING or REQUEST_CONTENT). In example below I just use my own class but really you can do it in a few lines if needed

access_token = web.GetRequestParam("access_token")
token_type = web.GetRequestParam("token_type")

3. Making API Requests

Use NotesHTTPRequest to communicate with the OpenID Connect provider’s API. Set the Authorization header with the access token:

Dim session as NotesSession
Dim http As NotesHTTPRequest
Dim jsonNav as NotesJSONNavigator

Set session = new NotesSession
Set http = session.Createhttprequest()
http.Preferjsonnavigator = True
Call http.Setheaderfield("Authorization", token_type & " " & access_token)
Set jsonNav = http.Get("https://graph.microsoft.com/v1.0/me")

4. Parsing the Response

Handle and parse the JSON response to extract user information:

On Error 4843 Resume Next
Dim jsonEl As NotesJSONElement
Dim jsonObj As NotesJSONObject
Set jsonEl = jsonNav.getelementbyname("error")
If Not jsonEl Is Nothing Then
    Set jsonObj = jsonEl.Value
    Print |Status: 401|
    Print "<h2>Error</h2>"
    Print "<p>" & jsonObj.Getelementbyname("code").Value & "</p>"
    Print "<p>" & jsonObj.Getelementbyname("message").Value & "</p>"
    Call scriptLog.LogInfo(jsonNav.Stringify())
    Exit Function
End If

mail = jsonNav.Getelementbyname("mail").Value
displayName = jsonNav.Getelementbyname("displayName").Value

Knowing user's email or other unique data will help you to find a user in your application and make necessary steps for auth.

Conclusion

In my case, I have a web application written in Domino where users can register and sign in without using names.nsf. This approach allows for seamless authentication using OpenID, bypassing the traditional Domino authentication model.

While this solution does not allow users to authenticate directly with Domino, it is still a significant step in that direction. By integrating OpenID Connect, we are moving closer to a more flexible authentication model that can eventually be expanded to support Domino authentication.

Thursday, November 02, 2023

Configuring Entitlement Tracking in Domino 12

In the realm of HCL Domino Server 12.0, the feature of "Entitlement Tracking" has become a vital component for organizations.

While comprehensive information regarding Entitlement Tracking is available through HCL, I needed to know some practical management aspects, such as disabling the feature and adjusting intervals etc.

Disabling Entitlement Tracking:

To disable entitlement tracking, add the following entry and restart the server:

DISABLE_ENTITLEMENT_TRACKING=1

Debugging for Entitlement Tracking Issues:

Debug settings can be incredibly useful for troubleshooting any issues related to Entitlement Tracking. Here's how to configure debugging options:

DEBUG_ENTITLEMENT_AGGREGATOR_INTERVAL=60
DEBUG_UPDATE_ENTITLEMENT_TRACKING=2
ES_OPT_TIMING=1
DEBUG_DIRCAT=3

Hope that will help somebody.