How to Handle JSF Exceptions in Jakarta EE 10

Exception handling is a tedious but necessary job during development of modern web applications. And it’s teh same for Jakarta EE 10. But if you migrate an existing application to the new Jakarta EE 10 things have change a little bit and so it can happen that you old errorHandler does no no longer work. At least this was the case when I migrated Imixs-Office-Workflow to Jakrata EE 10. So in this short tutorial I will briefly explain how to handle JSF Exceptions.

First of all you need an exeptionHandler extending the Jakarta EE10 ExceptionHandlerWrapper class. The implementation can look like this:

import java.util.Iterator;
import java.util.Objects;

import jakarta.faces.FacesException;
import jakarta.faces.application.NavigationHandler;
import jakarta.faces.context.ExceptionHandler;
import jakarta.faces.context.ExceptionHandlerWrapper;
import jakarta.faces.context.FacesContext;
import jakarta.faces.context.Flash;
import jakarta.faces.event.ExceptionQueuedEvent;
import jakarta.faces.event.ExceptionQueuedEventContext;

public class MyExceptionHandler extends ExceptionHandlerWrapper {

  public MyExceptionHandler(ExceptionHandler wrapped) {

  public void handle() throws FacesException {
    Iterator iterator = getUnhandledExceptionQueuedEvents().iterator();

    while (iterator.hasNext()) {
      ExceptionQueuedEvent event = (ExceptionQueuedEvent);
      ExceptionQueuedEventContext context = (ExceptionQueuedEventContext) event.getSource();

      Throwable throwable = context.getException();

      throwable = findCauseUsingPlainJava(throwable);

      FacesContext fc = FacesContext.getCurrentInstance();

      try {
        Flash flash = fc.getExternalContext().getFlash();
        flash.put("message", throwable.getMessage());
        flash.put("type", throwable.getClass().getSimpleName());
        flash.put("exception", throwable.getClass().getName());

        NavigationHandler navigationHandler = fc.getApplication().getNavigationHandler();

        navigationHandler.handleNavigation(fc, null, "/errorhandler.xhtml?faces-redirect=true");

      } finally {

    // Let the parent handle the rest

   * Helper method to find the exception root cause.
   * See:
  public static Throwable findCauseUsingPlainJava(Throwable throwable) {
    Throwable rootCause = throwable;
    while (rootCause.getCause() != null && rootCause.getCause() != rootCause) {
      System.out.println("cause: " + rootCause.getCause().getMessage());
      rootCause = rootCause.getCause();
    return rootCause;


This wrapper overwrites the default ExceptionHandlerWrapper. In the method handle() (which is the imprtant one) we search the root cause of the exception and put some meta information into the JSF flash scope. The flash is a memory that can be used by the JSF page we redirect to – ‘errorhandler.xhtml’

Next you need to create a custom ExceptionHanlderFactor. This class simple registers our new ExceptionHandler:

import jakarta.faces.context.ExceptionHandler;
import jakarta.faces.context.ExceptionHandlerFactory;

public class MyExceptionHandlerFactory extends ExceptionHandlerFactory {
    public MyExceptionHandlerFactory(ExceptionHandlerFactory wrapped) {

    public ExceptionHandler getExceptionHandler() {
        ExceptionHandler parentHandler = getWrapped().getExceptionHandler();
        return new MyExceptionHandler(parentHandler);


The new Factory method need to be registered in the faces-config.xml file:


And finally we can create a errorhandler.xhtml page that displays a user friendly error message. We can access the flash memory here to display the meta data collected in our ErrorHandler.

<ui:composition xmlns=""
		Display a error message depending on the cause of a exception
	<ui:define name="content">
	  <h:panelGroup styleClass="" layout="block">
				<p><h4>#{flash.keep.type}: #{flash.keep.message}</h4>
		<br />
		<br />
		<strong>Error Code:</strong>
		<br />
		<h:outputText value="#{session.lastAccessedTime}">
			<f:convertDateTime pattern="#{message.dateTimePatternLong}" timeZone="#{message.timeZone}"
							type="date" />
	  <h:commandButton action="home" value="Close"
		immediate="true" />			


That’s it. You can extend and customize this to you own needs.

Find And Replace in ODF Documents

With the ODF Toolkit you got a lightweight Java Library to create, search and manipulate Office Document in the Open Document Format. The following tutorial will show some examples to find and replace parts of text and spreadsheet documents.


You can add the ODF Toolkit to your Java project with the following Maven dependency:


Note: Since version 0.12.0 new methods where added which I will explain in the following examples.

Text Documents

To find and replace parts of ODF text document you can use the class TextNavigation. The class allows you to search with regular expression in a text document and navigate through the content.

The following example show how to find all text containing the names ‘John’ or ‘Marry’ and replace the text selection with ‘user’:

OdfTextDocument odt = (OdfTextDocument) OdfDocument.loadDocument(inputStream);
TextNavigation textNav;

textNav = new TextNavigation("John|Marry", odt);
while (textNav.hasNext()) {
	TextSelection selection =;"Found " + selection.getText() + 
                    " at Position=" + selection.getIndex());

It is also possible to change the style of a selection during iterating through a document. See the following example:

    OdfStyle styleBold = new OdfStyle(contentDOM);
    styleBold.setProperty(StyleTextPropertiesElement.FontWeight, "bold");
    // bold all occurrences of "Open Document Format"
    TextNavigation search = new TextNavigation("Open Document Format", doc);
    while (search.hasNext()) {
       TextSelection selection =;

SpreadSheet Documents

To find and manipulate cells in a SpreadSheet document is also very easy. In case of a .ods document you can find a cell by its coordinates:

InputStream inputStream = getClass().getResourceAsStream("/test-document.ods");
OdfSpreadsheetDocument ods = (OdfSpreadsheetDocument) OdfDocument.loadDocument(inputStream);

OdfTable tbl = ods.getTableByName("Table1");
OdfTableCell cell = tbl.getCellByPosition("B3");
// set a new value

There are much more methods in the ODS Toolkit. Try it out and join the community.

Why You Shouldn’t Trust IT Consulting Companies

Very large companies often tend to hire very large IT consulting firms to solve their IT problems. Often with moderate success. You can observe this all over the world when you read about failed big IT projects.

So why is this happening? Large IT consulting firms are perfect at telling you that they are the only ones able to solve your problem quickly and reliably. Typically, they also have a real expert who recognizes the problem very well and has an idea of a working solution. You should memorize this person’s face well, because you may never see this expert again. And he probably won’t be the one to solve your problem.

But what exactly is happening here? Why should an international big IT consulting company not be the right expert for your IT problem? To understand this, you simply think about the business model of such companies. It consists of selling you IT services at a fixed daily or hourly rate. This means that the more hours you buy, the better it is for the consulting firm. In order to further maximize profits, these companies are often looking for teams consisting of young enthusiastic university graduates. Typically in a completely different place in the world, where much lower wages are paid. It may be that you are lucky and you find an expert able to solve your problem. But it can also happen that he is confronted with this problem for the first time in his life.

So, now you have an international IT team managed by a large consulting firm and you may continue to have your original IT problem for a very long time. How can you solve this situation in a better way? It’s basically quite simple. Just take a look at the open source community. For every problem in IT, there is someone who deals with it. And if he or she makes the problem public and also publishes his proposed solution, then that’s your IT expert! If the problem is big enough, it may happen that the open source project grows a little. This means that there are now more than one experts able to solve your problem. You will save yourself a lot of money and time if you try to solve your IT problems in this way in the future.

So the biggest problem for you is actually only to find these IT experts in the open source community. However, you should not hire a large IT consulting company to search for such experts. If you’re wondering why – just read this article again from the beginning.

Start Your Debian Terminal with cowsay

Cowsay is a Linux tool drawing a cow with a bubble into your terminal.

To have more fun starting your bash you can add it into your bash configuration in Debian:

$ sudo apt-get install cowsay fortune

Next edit your ~/.bashrc file and add the following script at the end of this config file:

if [ -x /usr/games/cowsay -a -x /usr/games/fortune ]; then
    fortune | cowsay

That’s it.

Debian – Bluetooth disconnects Sound Device

I have had the problem that I can’t connect a new SoundCore speaker device to my notbook running Debian. The problem was that the Bluetooth device was detected, but when I tried to connect it immediatly disconnected.

After a long trail and error the solution was simple:

$ sudo apt-get install pulseaudio-module-bluetooth
$ killall pulseaudio

Connected again – and it worked! Find background here.

How to Configure Payara in Docker?

When I started with the Application Server Glassfish years ago I used to configure the Server always directly in the domain.xml file. This is the file containing the configuration and all your customizations when you configure your Glassfish form the Web Admin Interface. The same is true for Payara Server which is more widespread in projects today. (The main different from Glassfish to Payara is, that Payara offers support where Glassfish is the reference implementation for Jakarta EE).

I’ve never gotten rid of my habit of configuring the server directly in the domain .xml, although there is a command-line tool called ‘asadmin‘ for doing the configuration. When you run you projects in Docker you even can copy the domain.xml into a Payara Docker image as you will do with your application. But these days I learned that this is a clumsy and impractical way to do this. The problem with tweaking the domain.xml directly is that you can miss some important XML tags or new coniguration details. So using the asadmin tool is more stable also over differnt versions of Payara.

Docker and asadmin

To configure the Payara Sever directly in your Dockerfile can be done easily when you use so called Preboot and Postboot commands. This are asadmin commands which can be placed in separate files.

So simply create two files called post-boot-commands.asadmin and pre-boot-commands.asadmin and copy these files into your custom Payara Docker image using the COPY command in your Dockerfile:

FROM payara/server-full
# add configuration files
USER root

# Preconfigure Resources
COPY ./my-scripts/preboot-commands.asadmin $POSTBOOT_COMMANDS
COPY ./my-scripts/post-boot-commands.asadmin $POSTBOOT_COMMANDS

## Copy additional deployments here
## e.g. Postgres Driver
COPY ./my-scripts/postgresql-42.2.5.jar /opt/payara/paasDomain/lib/
USER payara

The Preeboot and Postboot scripts can contain any asadmin command to configure your server. For example to configure a JDBC Database Pool for Postgres the command will look like this:

# Create the JDBC connection pool for Postgres:
create-jdbc-connection-pool --datasourceclassname=org.postgresql.ds.PGSimpleDataSource --restype=javax.sql.DataSource --property user=${ENV=POSTGRES_USER}:password=${ENV=POSTGRES_PASSWORD}:Url=${ENV=POSTGRES_CONNECTION} my-database

# Create the JDBC resource:
create-jdbc-resource --connectionpoolid my-database jdbc/my-database

Now build your Docker image and start you server:

$ docker build -t my-payara .
$ docker run -p 8080:8080 my-payara

The Payara server will automatically execute the PreBoot and PostBoot scripts during startup and creates the configuration. In case your command is wrong or misspelled you will see the error message in the log file directly in the log file.

That’s it. Now you have a stable configuration setup for a Payara Docker Image that you can easily adapt to the latest version of Payara by simply upgrading the payara version in your Dockerfile.

My Visual-Studio Code – Cheat Sheet

This is just a short collection of VSCode commands and tricks which I personally did not know after switching from Eclipse ID.

Install or Update on Debian

To install or update VSCode on Linux Debian just got to the Download page and download the latest .deb package.

Next switch into the download folder and just run

$ sudo apt install ./code_*.deb

If you already have installation an update will be installed.

Open Command Palette

Most things in VSCode can be controlled via the Command Palette:

Press Ctrl + Shift + P


Switch Remote Branch

To switch the remote branch of the current git repo you usually can click on the branch-icon on the lower-left corner:

But this only works if you already have the branch in your local git repo. If this is not the case use the command:

Git: Checkout to...

and select the corresponding remote branch.

Tag and Push

To tag the new release and push the tag to Github open the command palette and use

Git: Create Tag
-> choose your projec
-> enter teh tag name

Next you can push your new local tag to github with the command

Git: Push (Follow Tags)

Clean and Rebuild Java Projects

In some situations it may be helpful to rebuild all Java projects in your workspace

Java: Clean Java Language Server Workspace

Debug Jakarta EE Server

To use the Java Debugger to debug your code running in a Jakarta EE (or any Web Server) you need to create a so called launch-configuration first. Create or edit the project file .vscode/launch.json and add a configuration pointing to your remote server and project. The following example shows a configuration for Wildfyl in a project called ‘my-jakarta-app’

  // Wildfly Debug Configuration
  "configurations": [
      "type": "java",
      "name": "Debug my-jakarta-app",
      "request": "attach",
      "hostName": "localhost",
      "port": "8787",
      "projectName": "my-jakarta-app"

After creating the debug configuration you can launch the debugger:

Note: It is important that you enter the correct ‘projectName‘. If not, the debugger will not detect your sources correctly. You can see that the debug configuration is correct when the debug console print out something.

SSH Key – Github Pull hangs…

In case you run into a scenario that your build-in git pull command within VSCode hangs forever, this may be an issue related to the ssh-agent (find background here).

You can test if yoru ssh-agent is running (which is necessary for VSCode) by checking the following command in a terminal:

$ ssh-add -l
The agent has no identities.

The result here shows, that not SSH IDs are available and this causes the hang in VSCode.

To solve such a situation, you can open a Terminal and enter

$ eval `ssh-agent`
$ ssh-add

This will promt you for the password of your ssh private key and register the ssh-agent with the SSH id. Now you can start VSCode:

$ code

This way VSCode will inherit the environment variables it needs to get key services from ssh-agent, and therefore will not prompt for your passphrase so long as the ssh-agent process continues running.

To automate this you can add the following script into your ~/.bashrc or ~/.bash_profile file:

if [ -z "$SSH_AUTH_SOCK" ]; then
   # Check for a currently running instance of the agent
   RUNNING_AGENT="`ps -ax | grep 'ssh-agent -s' | grep -v grep | wc -l | tr -d '[:space:]'`"
   if [ "$RUNNING_AGENT" = "0" ]; then
        # Launch a new instance of the agent
        ssh-agent -s &> .ssh/ssh-agent
   eval `cat .ssh/ssh-agent`

Find details also here.

Compare .bpmn files with Text-Diff Editor

To compare different versions of .bpmn files in the text-diff editor, you first need to set the text editor as the default editor for .bpmn files.

  1. Choose the context menu ‘open with…’ on a .bpmn file
  2. Select the option “configure default editor for .bpmn…” and choose the option ‘Text Editor’

Now BPMN files will always be opened with text editor per default – also in the compare dialogues from Git.

Later you can switch back the default editor the BPMN.

Java Language Support – Redhat

The RedHat Java Language Support may cause problems on startup – the build task hangs. To solve this you can try to edit the java settings:

-> go to Setting and type and click Edit in settings.json.

Now you can edit the settigns file. Try to add the following Lines:

    "": "-Xlog:jni+resolve=off",
    "java.debug.settings.vmArgs": "-Xlog:jni+resolve=off",
    "": false

Lerna does no longer build browser-app module!?

Within my Node.js / yarn project I run into a strange problem. Suddenly my lerna build tool did no longer build my app module.

I am using a monorepo with module/directory structure like this

├── .gitignore
├── lerna.json
├── open-bpmn-app
├── open-bpmn-glsp
├── open-bpmn-theia
├── package.json
└── yarn.lock

The module ‘open-bpmn-app’ was ignored. As it turns out newer nx versions of lerna parse the .gitignore file in the root folder. You have to make sure that the root folder of your workspace packages is not excluded via .gitignore. In my case I had the following instructions included:


By removing these two lines the problem was solved!

See also here and here.

Traefik and Basic Authentication

Today I once again came across a configuration issue in regarding an authentication problem. Traefik is a cloud native networking solution for container platforms. It can be used for example within Kubernetes and is a build in function of K3S – a lightweight Kubernetes solution.

In K3S Traefik is used for the ingress configuration. For example to route Web traffic from an Internet domain to a specific service within your cluster.

My problem was that I wanted to install a private Docker Registry within my K3S cluster. The Docker Registry comes without any security. This is fine within a cluster, but in case you connect from outside you don’t want that your private registry is open for everyone. With Traefik you can easily secure you service. I will explain how you can do this.

Continue reading “Traefik and Basic Authentication”

JsonFroms – Custom Component for SelectItems

JsonForms is a powerful and very flexible framework to build complex forms just from a JSON Schemata. A form can contain various different controls and controls can be separated into categories and layout sections. This makes JsonForrms a first-hand framework if you have to deal with dynamic forms in a JavaScript application.

JsonForms already provides different so called Renderer Sets to handle complex input widgets. But further more you can also create easily you own widget if you have special needs not supported by JsonForms out of the box.

Continue reading “JsonFroms – Custom Component for SelectItems”