Domino & Spring Boot: How does it work

The example Spring Boot Plugin I have published two days ago is a full working example to run Spring Boot applications directly in the Domino HTTP task. It is designed as an OSGi plugin and runs inside the servlet container, which means that the „normal“ features of the Domino HTTP task are available at runtime, for example the existing the user session is accessible via the ContextInfo object.

To complile and deploy the plugin, you first have to install the XPages SDK and create the missing feature project and update site project as described in one of my older posts.
After importing the plugin in the UpdateSite and restarting the HTTP task, the Spring Boot application is ready and will flood the console with a lot of debugging informations when the first request hits the application:

While the example is a really basic one I am using the same approach for years in production environment. The reason is that it was fundamental for the customer (which has abandoned Domino years ago) to have a modern and industry-wide standard framework: The application is now a Spring Boot application which has a NoSQL backend – the decision makers had some buzzwords, the term „Domino“ is no longer used and all participants are happy now.

How does it work?

First it is required that the main configuration is still in the web.xml file. This is required because of the old servlet container which is still only available in version 2.5; I was not successfull to implement the latest Spring Boot version 5, because it seems that a servlet container version 3.0 is required.

In the web.xml file, the servlet mapping is defined:

<servlet>
   <servlet-name>dominoSpringBootServlet</servlet-name>
   <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
   <load-on-startup>1</load-on-startup>
</servlet>

An additional configuration file dominoSpringBootServlet.xml contains the servlet specific configuration; both (the servlet name and the XML configuration) must have the same name, otherwise Spring Boot will not find the configuration file.

In this configuration file, the base package is defined, which tells the framework where to scan for Java classes and annotations:

<context:component-scan base-package="domino.springboot.plugin" />

The following line enables Spring Boot’s annotations:

<mvc:annotation-driven />

Now, the package domino.springboot is scanned for controllers and configuration classes, which I will describe in the next post.

 

Veröffentlicht unter Java, OSGi, Server, Spring, Web | Verschlagwortet mit , , | Hinterlasse einen Kommentar

Domino & Spring Boot: An example project

I have uploaded an example for running Spring Boot applications on top of Domino. You can find it here:
https://github.com/hasselbach/domino-springboot

This solution is running for years in productive environments.

Hopefully I will find some time to explain how it works.

Veröffentlicht unter Java, OSGi, REST, Spring, Web | Verschlagwortet mit , , , | 2 Kommentare

Domino & Spring Boot: ScheduledTasks

When developing Spring Boot applications running on Domino, there is a feature which runs out of the box and makes developers happy: ScheduledTasks.

These are the equivalent for agents, but they are running directly in the HTTP task (which allows to access the complete Spring Application at runtime) and can be scheduled exactly to the milisecond.

To enable a scheduled task, you first have to add the @EnableScheduling annotation in your Application class:

package domino_spring.plugin;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableScheduling;

@SpringBootApplication
@EnableScheduling
public class Application extends org.springframework.boot.web.support.SpringBootServletInitializer {

   public static void main(String[] args) {
      SpringApplication.run(Application.class, args);
   }

}

Next step is to declare the TaskScheduler used. Just add a bean to your Application class:

@Bean
 public TaskScheduler taskScheduler() {
      return new ConcurrentTaskScheduler();
 }

After completing the setup you can define your scheduled task:

package domino_spring.plugin;

import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

@Component
public class ScheduledTasks {

   private static final Logger log = LoggerFactory.getLogger(ScheduledTasks.class);

   private static final SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss");

   @Scheduled(fixedRate = 5000)
   public void reportCurrentTime() {
      log.info("The time is now {}", dateFormat.format(new Date()));
   }
 
}

When the Sprint Boot application is now started, the current time is  printed to the logs every 5 seconds.

Veröffentlicht unter Agenten, Java, Server, Spring, Web | Verschlagwortet mit , , , , , | 2 Kommentare

java.security.AccessControlException kills productivity

Dear IBM, can you please remove the totally useless java policy restrictions? Especially for agents running on the server?

I can’t imagine how much life time and customers money was spent during the last decades just to find a workaround for these limitations. The Q&A sites are full of questions about problems with this topic, and I never met someone who found the restriction usefull.

It’s 2018, and writing something in Lotus Script just to „solve“ this issue makes absolutly no sense. The whole „Let’s restrict Java as much as we can“ is pita – everyone knows how to ship around these restrictions. The „bad guys“ are not stopped, only the „good developers“ will be limited.

By the way: Are these limitations planned for notes.js integration? If so, please drop it immediatly.

Veröffentlicht unter Java, Security | Verschlagwortet mit , , | Hinterlasse einen Kommentar

The anatomy of a LTPA token

LTPA Token

LTPA token are widely used in the IBM world for authentication between different physical machines, also known as WebSSO. There are two three types available, LTPA1, LTPA2 and a Domino format.

LTPA1 and LTPA2 are commonly used with WebSphere, and Domino can import the keys to work with this kind of token. The Domino version of LTPA is normally used in the Domino world, and that’s the token I will write about.

First, what is a Domino LTPA token in general? It is a BASE64 encoded String containing the information about the user, including some timestamps. To avoid a security problem, the token is hashed and then encrypted (see here: LTPA versions and token formats).

So let’s look into a real world example. Here is a LTPA Domino token from my server*:

77+9AQIDNUFCMTJBNjk1QUIxMzg3OUNOPVN2ZW4gSGFzc2VsYmFjaC9PPUhhc3NlbGJhL089Q0gwezcFKix7Fy00cg==

Now here comes the BASE64 decoded version:

As you can see, there is my username insinde of the token. And at this point I am a little bit confused, because the IBM writes in the linked article above:

Domino uses a shared key and SHA-1 to calculate a MAC over the content. After the MAC is attached, the user data and MAC are encrypted with a 3DES key obtained from the LTPA key file.

Maybe it is because I have super powers which allow me to decrypt the 3DES encrypted userdata in my brain. But I think it is just a wrong information, and the userdata are not encrypted with 3DES.

This does not make the LTPA token unsafe, there is still a SHA-1 hash which protects the userdata from beeing changed in a text editor. Let’s look how the token is build up:

Anatomy of LTPA Domino Token

Byte 0-3 4-11 12-19 20 – ? ? – ? + 20
Content Header Creation Expiration Username Hash

Header (4 Bytes)

Byte 01 02 03 04
Value 0 1 2 3

Creation & Expiration (each 8 Bytes)

These values are Java Dates stored as Long value.

Username (Length different)

A string containing the abbreviated form of the current username. The length varies.

Hash (20 Bytes)

A SHA-1 hash, 160 Bits long. The hash is generated by adding the LTPA secret at the end of the userdata; the result is added to the end of the LTPA token.

The Problem

The problem with LTPA Domino token is the use of an insecure hash algorithm. We had to change all SSL certificates because of it, the NIST has deprecated it in 2011. And the 3DES encryption is a myth.

But we are still protecting our infrastructure with this weak algorithm…

*: no, it’s not 😉

Veröffentlicht unter Security, Server | Verschlagwortet mit , , , | 1 Kommentar

Datenschutz in Hessen: Wen interessieren schon behinderte Kinder?

Ab Mai dieses Jahres wird es ernst: Das neue Datenschutzgesetzt tritt in Kraft, mit härteren Anforderungen an die Datensammler, und noch härteren Strafen bei Verstößen gegen die neuen Vorschriften. Zumindest gilt das für die Privatwirtschaft. Und für Privatpersonen.

Behörden und Ämter in Wiesbaden können nämlich machen was sie wollen, und auch zukünftig wird sich da wohl nicht viel ändern. Denn als ich am 22. Februar den hessischen Datenschutzbeauftragten informiert habe, daß das Schulamt Wiesbaden im Zuge einer Ausschreibung die Adressdaten von 97 beeinträchtigten Kindern einer Förderschule im Netz veröffentlicht hat, war mir nicht bewusst, was dann geschehen würde: Nichts.

OK, „Nichts“ ist nicht ganz richtig, denn immerhin habe ich heute, auf mehrfache Nachfrage eine Stellungnahme erhalten, deren Kernsatz folgender ist:

„Zweifellos stehen ihre berechtigten Interessen dem eines inhaltvollen Ausschreibeverfahrens entgegen. Eine wie auch immer geartete Veränderung des Ausschreibeverfahrens hätte mit einiger Wahrscheinlichkeit zur Folge, dass die Ausschreibung, da nicht mehr mit den allgemeinen Grundsätzen für ein derartiges Verfahren konform, von Dritten beanstandet werden könnte mit der Konsequenz, dass die Ausschreibung neu aufgesetzt werden müsste.“

  • Der Hessische Datenschutzbeauftragte

Die Daten wieder löschen geht nicht, weil da müsste ja die Auschreibung vielleicht neu gemacht werden. Und das ist voll blöd, weil das ist ja voll die Arbeit für die Kollegen im Schulamt. Sagt der hessische Datenschutzbeauftragte!

Mir fehlen echt die Worte…

Veröffentlicht unter Allgemein | 4 Kommentare

Gemeinsame Erklärung der Eltern: Inklusion umsetzen!

Inklusion ist machbar. Wir kennen viele gute Beispiele. Deshalb danken wir all jenen, die Inklusion an hessischen Schulen schon jeden Tag leben.

Wir sind entsetzt, dass Inklusion in Presse und Öffentlichkeit immer wieder aufs Neue infrage gestellt wird, anstatt konstruktive Vorschläge zu machen und Konzepte zu entwickeln, um das gemeinsame Lernen von Kindern mit und ohne Behinderung endlich konsequent und zügig umzusetzen.

Denn Inklusion ist keine Sache der Freiwilligkeit:

Der UN-Fachausschuss erinnert in seinem Kommentar zu Artikel 24 UN-BRK daran, „dass Artikel 4 Absatz 5 von Bundesstaaten verlangt, dass Artikel 24 ohne Einschränkung oder Ausnahmen für alle Teile des Vertragsstaats umgesetzt wird.“

Die gemeinsame Erklärung der Eltern findet sich auf der Homepage von IGEL-WI:
Gemeinsame Erklärung der Eltern: Inklusion umsetzen!

Veröffentlicht unter Allgemein | Hinterlasse einen Kommentar

Quick-n-Dirty: Hotfix for DateTimeHelper

This weekend I stumbled over a bug of the DateTimeHelper: If the value of the field is empty, no actions and/or action listeners connected with a managed bean will be executed anymore.

Here is an example of a small XPage to illustrate the problem:

<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?>
<xp:view xmlns:xp="http://www.ibm.com/xsp/core">
 
    <xp:label 
        value="#{javascript:java.lang.System.currentTimeMillis()}" id="labelNow" />

     <xp:inputText id="inputTextDT" value="#{myBean.valueDT}">
         <xp:this.converter>
             <xp:convertDateTime type="date" />
         </xp:this.converter>
         <xp:dateTimeHelper />
     </xp:inputText>

    <xp:button id="button" value="OK">
        <xp:eventHandler
            event="onclick"
            submit="true"
            refreshMode="partial"
            refreshId="labelNow"
            actionListener="#{myBean.action}" />
     </xp:button>

</xp:view>

It does not matter if you set the disableValidators property for the text field to true, even an immediate=true won’t help here. The reason for the problem is that the renderer of the dateTimeHelper always uses the attached converter and fails with a null pointer exception if the value is empty (this infringes the JSF specification, but IBM has implemented it this way).

The workaround for this problem is to overwrite the existing renderer class and handle the NPE by yourself:

package ch.hasselba.xpages.renderer;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
public class DateTimeHelperRenderer
    extends com.ibm.xsp.renderkit.dojo.DateTimeHelperRenderer{

    public Object getConvertedValue(FacesContext fc, UIComponent uiComponent, Object obj)
        throws ConverterException  {

          Object result = super.getConvertedValue(fc, uiComponent, obj);

          if( result == null )
            return new Object();

          return result;
    }
}

The renderer must now be registered in faces-config.xml:

<?xml version="1.0" encoding="UTF-8"?><?xml version="1.0" encoding="UTF-8"?>
<faces-config>
  <render-kit>
    <renderer>
      <component-family>javax.faces.Input</component-family>
      <renderer-type>com.ibm.xsp.DateTimeHelper</renderer-type>
      <renderer-class>ch.hasselba.xpages.renderer.DateTimeHelperRenderer</renderer-class>
    </renderer>
  </render-kit>
</faces-config>

Now the problem is solved, the managed bean’s action get executed even if the value is empty.

Veröffentlicht unter Java, JSF, XPages | Verschlagwortet mit , , , , , | 1 Kommentar

High Performance REST Applications (4) – Looking into OSGi

Before going any deeper into the the servlet project, let’s have a look at the imported projects and talk about some OSGi basics.

First you will notice that for every cloned repository three Eclipse projects have been imported:

  1. A plugin project
  2. A feature project
  3. An updatesite project

The plugin project contains the code and all the relevant resources of the servlet. It defines extension points provided or describes which extension points are used by the plugin.
A feature project is basically a list of plugins and other features which can be understood as a logical separate unit. And an updatesite contains all features you need.

Using an UpdateSite is the preferred way to deploy plugins to Domino. It has a „Build All„-Button which builds all plugins from all features in your updatesite project, and creates the JARs to import into an UpdateSite in Domino.

Update Site „Build All“-Button

A plugin is mainly described by two files: the MANIFEST.MF (stored in the /META-INF folder) and a plugin.xml in the root.

plugin.xml & MANIFEST.MF

The MANIFEST.MF contains meta informations about the Plugin, like the name, imports and exports, other required bundles, the Activator class, the Execution environment and many more.

For example the Domino REST servlet plugin requires the concurrent plugin:

Required Bundles: „ch.hasselba.concurrent.plugin“

If the bundle is loaded, but the requirements are not fullyfied, the bundle won’t start.

The plugin.xml is optional for OSGI bundles, but we need this file, because it describes the extension point used by our plugin:

plugin.xml – Extension Point

Our servlet plugin uses the com.ibm.pvc.webcontainer.application extension point to run a JEE application. The parameter contextRoot is the path our servlet listens (which means it will be reachable at http://example.com/ec2017), and the contentLocation parameter is the path to the static files of the plugin and our web.xml.

WebContent folder

An Activator class is the class executed when a bundle is started or stopped (or the other possibilities a lifecyle of a bundle can have). It is also a good idea to store the BundleContext in the Activator to communicate with the OSGi environment.

Last but not least, there is a build.properties file: This file is for Eclipse and contains all relevant information to build the bundle. This means that if you add a JAR file the plugin requires, you have to add the JAR to both – the MANIFEST.MF and the build.properties (if the classes of the JAR file are used in the project).

In the Domino REST Servlet project, the spymemcached.jar is used, that’s why it is added to the build path and the manifest:

build.properties – spymemcached JAR

MANTIFEST.MF – spymemcached JAR

You have to keep this in your mind, because if you write some code, it is not enough just to add the required JAR to the build path, it also has to be exported in your bundle / plugin.

In the next post, let’s have a look into web.xml, and then go into the real „High Performance“ solution.

Veröffentlicht unter Apache Wink, Java, JEE, OSGi, REST, Server, Web | Verschlagwortet mit , , , , , , | 2 Kommentare

High Performance REST Applications (3) – Importing the Starter Project

Now you can import the projects required from Git.

First, go to „File > Import…

Import Project

Then select „Projects from Git“

Projects from Git

and „Clone URI“ to clone an existing repository:

Clone existing respository

To get the URI, you have to open https://github.com/hasselbach/ and select the repository „ch.hasselba.concurrent„. Click the „Clone or download„-Button and copy the URI from the opening box:

Get the repository URI

Paste the URI into the location in Eclipse

Add the URI to Eclipse

In the next dialog, you can choose the branch to import. In this case, only „master“ exists

Select the branch to import

Now you have to choose a local destination where the cloned repository will be stored

Select the local destination

Select „Import existing Eclipse projects„…

Import existing projects

… and select all projects of the repository:

Select all projects

With „Finish„, the sources are downloaded. In the „Project Explorer„, you can see the three imported projects. And you can see the original repository name and the current branch you are working on:

Repository & Branch

The JRE used for the project can be seen if you expand one of the projects. „Sometimes“ this changes magically, and the build will fail – that is one of the first things you have to check if you have errors in a OSGi project.

JRE / Target used for this project

Now, do the same for the „domino-rest-servlet“ repository. But instead importing the „master“ branch, select the „highperformance“ branch only.

Import HighPerformance Branch

That’s it. In the next post, we have take a look in what you have downloaded.

Veröffentlicht unter Java, JEE, OSGi, Performance, REST, Server, Web | Verschlagwortet mit , , , , | 4 Kommentare