diff --git a/.gitignore b/.gitignore
index 10d81e8c69b7a6700576643dcd104b107a5a66df..0776b3851ab3d97b7ba632216b63c1a4d8644b8b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 /.project
 /.settings/
 /target/
+/node_modules/
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f7d327e633093341a553d84bda8f65ca8038d08e..a9fc001f749acb7388bf2672f5eb01a718d4da88 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -11,11 +11,13 @@ variables:
   # Maven deployment settings for Nexus, please use env vars in Settings -> CI/CD -> Variables.
   MAVEN_SETTINGS_PATH: ".m2/settings.xml"
   MAVEN_DEPLOY_OPTS: "--settings=$MAVEN_SETTINGS_PATH"
+  MAVEN_IMAGE: "maven:3.8.7-eclipse-temurin-17"
   # Semantic versioning commit and push vars (the TOKEN name and user)
   GIT_AUTHOR_EMAIL: ${GL_USER}@noreply.gitlab.gwdg.de
   GIT_AUTHOR_NAME: ${GL_USER}
   GIT_COMMITTER_EMAIL: ${GL_USER}@noreply.gitlab.gwdg.de
   GIT_COMMITTER_NAME: ${GL_USER}
+  DOCKERFILE: $CI_PROJECT_DIR/src/main/docker/Dockerfile.jvm-multistage
 
 # Include Java settings from Gitlab templates repo.
 include:
@@ -60,7 +62,7 @@ prepare-release:
   rules:
   # Only run if branch "main" AND commit title IS NOT "1.2.3" (main commit with tag) AND DOES NOT START WITH "Prepare next development iteration" (main commit with new version)
     - if: $CI_COMMIT_REF_NAME == "main" && $CI_COMMIT_TITLE !~ /^[\d\.]+$/ && $CI_COMMIT_TITLE !~ /^Prepare next development iteration/
-  image: maven:3.8.3-jdk-8
+  image: $MAVEN_IMAGE
   extends:
     - .prepare-semantic-release
 
@@ -71,7 +73,7 @@ validate-java:
     - main
     - develop
     - tags
-  image: maven:3.8.3-jdk-8
+  image: $MAVEN_IMAGE
   script:
     - mvn $MAVEN_OPTS $MAVEN_CLI_OPTS $MAVEN_DEPLOY_OPTS -U clean validate package
   artifacts:
@@ -84,7 +86,7 @@ validate-java:
 # NOTE: "deploy" also triggers BOM creation!
 build-and-deploy-jars:
   stage: test-build-deploy-maven
-  image: maven:3.8.3-jdk-8
+  image: $MAVEN_IMAGE
   only:
     - develop
     - tags
diff --git a/.mvn/wrapper/.gitignore b/.mvn/wrapper/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e72f5e8b737c2abfc37d8ebf4ccb086a9fd61279
--- /dev/null
+++ b/.mvn/wrapper/.gitignore
@@ -0,0 +1 @@
+maven-wrapper.jar
diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100644
index 0000000000000000000000000000000000000000..84d1e60d8d2f339d7ddaab039a5e416c62e43243
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,98 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.Authenticator;
+import java.net.PasswordAuthentication;
+import java.net.URL;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+public final class MavenWrapperDownloader
+{
+    private static final String WRAPPER_VERSION = "3.2.0";
+
+    private static final boolean VERBOSE = Boolean.parseBoolean( System.getenv( "MVNW_VERBOSE" ) );
+
+    public static void main( String[] args )
+    {
+        log( "Apache Maven Wrapper Downloader " + WRAPPER_VERSION );
+
+        if ( args.length != 2 )
+        {
+            System.err.println( " - ERROR wrapperUrl or wrapperJarPath parameter missing" );
+            System.exit( 1 );
+        }
+
+        try
+        {
+            log( " - Downloader started" );
+            final URL wrapperUrl = new URL( args[0] );
+            final String jarPath = args[1].replace( "..", "" ); // Sanitize path
+            final Path wrapperJarPath = Paths.get( jarPath ).toAbsolutePath().normalize();
+            downloadFileFromURL( wrapperUrl, wrapperJarPath );
+            log( "Done" );
+        }
+        catch ( IOException e )
+        {
+            System.err.println( "- Error downloading: " + e.getMessage() );
+            if ( VERBOSE )
+            {
+                e.printStackTrace();
+            }
+            System.exit( 1 );
+        }
+    }
+
+    private static void downloadFileFromURL( URL wrapperUrl, Path wrapperJarPath )
+        throws IOException
+    {
+        log( " - Downloading to: " + wrapperJarPath );
+        if ( System.getenv( "MVNW_USERNAME" ) != null && System.getenv( "MVNW_PASSWORD" ) != null )
+        {
+            final String username = System.getenv( "MVNW_USERNAME" );
+            final char[] password = System.getenv( "MVNW_PASSWORD" ).toCharArray();
+            Authenticator.setDefault( new Authenticator()
+            {
+                @Override
+                protected PasswordAuthentication getPasswordAuthentication()
+                {
+                    return new PasswordAuthentication( username, password );
+                }
+            } );
+        }
+        try ( InputStream inStream = wrapperUrl.openStream() )
+        {
+            Files.copy( inStream, wrapperJarPath, StandardCopyOption.REPLACE_EXISTING );
+        }
+        log( " - Downloader complete" );
+    }
+
+    private static void log( String msg )
+    {
+        if ( VERBOSE )
+        {
+            System.out.println( msg );
+        }
+    }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100644
index 0000000000000000000000000000000000000000..346d645fd06fd06e116483d5a51d41321a60be02
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1,18 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.6/apache-maven-3.9.6-bin.zip
+wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar
diff --git a/Dockerfile b/Dockerfile
deleted file mode 100644
index be2a2ab819f9e4f22d3d494e1938ae254bf19831..0000000000000000000000000000000000000000
--- a/Dockerfile
+++ /dev/null
@@ -1,36 +0,0 @@
-###
-# build
-###
-FROM maven:3.8.3-jdk-8 as builder
-
-COPY . /build
-WORKDIR /build
-
-RUN --mount=type=cache,target=/root/.m2 mvn clean verify package
-
-
-###
-# assemble image
-###
-FROM jboss/wildfly:9.0.2.Final
-
-ARG JOLOKIA_VERSION="1.3.7" # jolokia as of 1.5.0 requires auth for proxy operation
-
-USER root
-# https://tufora.com/tutorials/linux/general/install-vips-vips-tools-and-vips-devel-libvips-on-centos-7
-RUN yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm && yum install -y yum-utils && yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm && yum-config-manager --enable remi && yum install -y vips vips-tools && yum clean all
-
-COPY ./src/docker/config-jms.cli /opt/config-jms.cli
-
-USER jboss
-RUN curl -XGET "https://repo1.maven.org/maven2/org/jolokia/jolokia-war/${JOLOKIA_VERSION}/jolokia-war-${JOLOKIA_VERSION}.war" --output /opt/jboss/wildfly/standalone/deployments/jolokia.war
-COPY --from=builder /build/target/*.war  /opt/jboss/wildfly/standalone/deployments/
-
-# yes, right, here is a password, but the service is not going to be exposed to the world
-# TODO: find out how to solve this in a nicer way
-RUN /opt/jboss/wildfly/bin/add-user.sh -a --user tgcrud --password secret --group guest --silent
-
-RUN /opt/jboss/wildfly/bin/jboss-cli.sh --file=/opt/config-jms.cli
-
-ENTRYPOINT /opt/jboss/wildfly/bin/standalone.sh -c standalone-full.xml -b 0.0.0.0 -bmanagement 0.0.0.0
-
diff --git a/mvnw b/mvnw
new file mode 100755
index 0000000000000000000000000000000000000000..8d937f4c14f11f8c3aded556054af0b0097eaede
--- /dev/null
+++ b/mvnw
@@ -0,0 +1,308 @@
+#!/bin/sh
+# ----------------------------------------------------------------------------
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#    http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Apache Maven Wrapper startup batch script, version 3.2.0
+#
+# Required ENV vars:
+# ------------------
+#   JAVA_HOME - location of a JDK home dir
+#
+# Optional ENV vars
+# -----------------
+#   MAVEN_OPTS - parameters passed to the Java VM when running Maven
+#     e.g. to debug Maven itself, use
+#       set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
+#   MAVEN_SKIP_RC - flag to disable loading of mavenrc files
+# ----------------------------------------------------------------------------
+
+if [ -z "$MAVEN_SKIP_RC" ] ; then
+
+  if [ -f /usr/local/etc/mavenrc ] ; then
+    . /usr/local/etc/mavenrc
+  fi
+
+  if [ -f /etc/mavenrc ] ; then
+    . /etc/mavenrc
+  fi
+
+  if [ -f "$HOME/.mavenrc" ] ; then
+    . "$HOME/.mavenrc"
+  fi
+
+fi
+
+# OS specific support.  $var _must_ be set to either true or false.
+cygwin=false;
+darwin=false;
+mingw=false
+case "$(uname)" in
+  CYGWIN*) cygwin=true ;;
+  MINGW*) mingw=true;;
+  Darwin*) darwin=true
+    # Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
+    # See https://developer.apple.com/library/mac/qa/qa1170/_index.html
+    if [ -z "$JAVA_HOME" ]; then
+      if [ -x "/usr/libexec/java_home" ]; then
+        JAVA_HOME="$(/usr/libexec/java_home)"; export JAVA_HOME
+      else
+        JAVA_HOME="/Library/Java/Home"; export JAVA_HOME
+      fi
+    fi
+    ;;
+esac
+
+if [ -z "$JAVA_HOME" ] ; then
+  if [ -r /etc/gentoo-release ] ; then
+    JAVA_HOME=$(java-config --jre-home)
+  fi
+fi
+
+# For Cygwin, ensure paths are in UNIX format before anything is touched
+if $cygwin ; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --unix "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --unix "$CLASSPATH")
+fi
+
+# For Mingw, ensure paths are in UNIX format before anything is touched
+if $mingw ; then
+  [ -n "$JAVA_HOME" ] && [ -d "$JAVA_HOME" ] &&
+    JAVA_HOME="$(cd "$JAVA_HOME" || (echo "cannot cd into $JAVA_HOME."; exit 1); pwd)"
+fi
+
+if [ -z "$JAVA_HOME" ]; then
+  javaExecutable="$(which javac)"
+  if [ -n "$javaExecutable" ] && ! [ "$(expr "\"$javaExecutable\"" : '\([^ ]*\)')" = "no" ]; then
+    # readlink(1) is not available as standard on Solaris 10.
+    readLink=$(which readlink)
+    if [ ! "$(expr "$readLink" : '\([^ ]*\)')" = "no" ]; then
+      if $darwin ; then
+        javaHome="$(dirname "\"$javaExecutable\"")"
+        javaExecutable="$(cd "\"$javaHome\"" && pwd -P)/javac"
+      else
+        javaExecutable="$(readlink -f "\"$javaExecutable\"")"
+      fi
+      javaHome="$(dirname "\"$javaExecutable\"")"
+      javaHome=$(expr "$javaHome" : '\(.*\)/bin')
+      JAVA_HOME="$javaHome"
+      export JAVA_HOME
+    fi
+  fi
+fi
+
+if [ -z "$JAVACMD" ] ; then
+  if [ -n "$JAVA_HOME"  ] ; then
+    if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+      # IBM's JDK on AIX uses strange locations for the executables
+      JAVACMD="$JAVA_HOME/jre/sh/java"
+    else
+      JAVACMD="$JAVA_HOME/bin/java"
+    fi
+  else
+    JAVACMD="$(\unset -f command 2>/dev/null; \command -v java)"
+  fi
+fi
+
+if [ ! -x "$JAVACMD" ] ; then
+  echo "Error: JAVA_HOME is not defined correctly." >&2
+  echo "  We cannot execute $JAVACMD" >&2
+  exit 1
+fi
+
+if [ -z "$JAVA_HOME" ] ; then
+  echo "Warning: JAVA_HOME environment variable is not set."
+fi
+
+# traverses directory structure from process work directory to filesystem root
+# first directory with .mvn subdirectory is considered project base directory
+find_maven_basedir() {
+  if [ -z "$1" ]
+  then
+    echo "Path not specified to find_maven_basedir"
+    return 1
+  fi
+
+  basedir="$1"
+  wdir="$1"
+  while [ "$wdir" != '/' ] ; do
+    if [ -d "$wdir"/.mvn ] ; then
+      basedir=$wdir
+      break
+    fi
+    # workaround for JBEAP-8937 (on Solaris 10/Sparc)
+    if [ -d "${wdir}" ]; then
+      wdir=$(cd "$wdir/.." || exit 1; pwd)
+    fi
+    # end of workaround
+  done
+  printf '%s' "$(cd "$basedir" || exit 1; pwd)"
+}
+
+# concatenates all lines of a file
+concat_lines() {
+  if [ -f "$1" ]; then
+    # Remove \r in case we run on Windows within Git Bash
+    # and check out the repository with auto CRLF management
+    # enabled. Otherwise, we may read lines that are delimited with
+    # \r\n and produce $'-Xarg\r' rather than -Xarg due to word
+    # splitting rules.
+    tr -s '\r\n' ' ' < "$1"
+  fi
+}
+
+log() {
+  if [ "$MVNW_VERBOSE" = true ]; then
+    printf '%s\n' "$1"
+  fi
+}
+
+BASE_DIR=$(find_maven_basedir "$(dirname "$0")")
+if [ -z "$BASE_DIR" ]; then
+  exit 1;
+fi
+
+MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}; export MAVEN_PROJECTBASEDIR
+log "$MAVEN_PROJECTBASEDIR"
+
+##########################################################################################
+# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
+# This allows using the maven wrapper in projects that prohibit checking in binary data.
+##########################################################################################
+wrapperJarPath="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar"
+if [ -r "$wrapperJarPath" ]; then
+    log "Found $wrapperJarPath"
+else
+    log "Couldn't find $wrapperJarPath, downloading it ..."
+
+    if [ -n "$MVNW_REPOURL" ]; then
+      wrapperUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    else
+      wrapperUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar"
+    fi
+    while IFS="=" read -r key value; do
+      # Remove '\r' from value to allow usage on windows as IFS does not consider '\r' as a separator ( considers space, tab, new line ('\n'), and custom '=' )
+      safeValue=$(echo "$value" | tr -d '\r')
+      case "$key" in (wrapperUrl) wrapperUrl="$safeValue"; break ;;
+      esac
+    done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+    log "Downloading from: $wrapperUrl"
+
+    if $cygwin; then
+      wrapperJarPath=$(cygpath --path --windows "$wrapperJarPath")
+    fi
+
+    if command -v wget > /dev/null; then
+        log "Found wget ... using wget"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--quiet"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            wget $QUIET "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        else
+            wget $QUIET --http-user="$MVNW_USERNAME" --http-password="$MVNW_PASSWORD" "$wrapperUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
+        fi
+    elif command -v curl > /dev/null; then
+        log "Found curl ... using curl"
+        [ "$MVNW_VERBOSE" = true ] && QUIET="" || QUIET="--silent"
+        if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
+            curl $QUIET -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        else
+            curl $QUIET --user "$MVNW_USERNAME:$MVNW_PASSWORD" -o "$wrapperJarPath" "$wrapperUrl" -f -L || rm -f "$wrapperJarPath"
+        fi
+    else
+        log "Falling back to using Java to download"
+        javaSource="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.java"
+        javaClass="$MAVEN_PROJECTBASEDIR/.mvn/wrapper/MavenWrapperDownloader.class"
+        # For Cygwin, switch paths to Windows format before running javac
+        if $cygwin; then
+          javaSource=$(cygpath --path --windows "$javaSource")
+          javaClass=$(cygpath --path --windows "$javaClass")
+        fi
+        if [ -e "$javaSource" ]; then
+            if [ ! -e "$javaClass" ]; then
+                log " - Compiling MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/javac" "$javaSource")
+            fi
+            if [ -e "$javaClass" ]; then
+                log " - Running MavenWrapperDownloader.java ..."
+                ("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$wrapperUrl" "$wrapperJarPath") || rm -f "$wrapperJarPath"
+            fi
+        fi
+    fi
+fi
+##########################################################################################
+# End of extension
+##########################################################################################
+
+# If specified, validate the SHA-256 sum of the Maven wrapper jar file
+wrapperSha256Sum=""
+while IFS="=" read -r key value; do
+  case "$key" in (wrapperSha256Sum) wrapperSha256Sum=$value; break ;;
+  esac
+done < "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.properties"
+if [ -n "$wrapperSha256Sum" ]; then
+  wrapperSha256Result=false
+  if command -v sha256sum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | sha256sum -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  elif command -v shasum > /dev/null; then
+    if echo "$wrapperSha256Sum  $wrapperJarPath" | shasum -a 256 -c > /dev/null 2>&1; then
+      wrapperSha256Result=true
+    fi
+  else
+    echo "Checksum validation was requested but neither 'sha256sum' or 'shasum' are available."
+    echo "Please install either command, or disable validation by removing 'wrapperSha256Sum' from your maven-wrapper.properties."
+    exit 1
+  fi
+  if [ $wrapperSha256Result = false ]; then
+    echo "Error: Failed to validate Maven wrapper SHA-256, your Maven wrapper might be compromised." >&2
+    echo "Investigate or delete $wrapperJarPath to attempt a clean download." >&2
+    echo "If you updated your Maven version, you need to update the specified wrapperSha256Sum property." >&2
+    exit 1
+  fi
+fi
+
+MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin; then
+  [ -n "$JAVA_HOME" ] &&
+    JAVA_HOME=$(cygpath --path --windows "$JAVA_HOME")
+  [ -n "$CLASSPATH" ] &&
+    CLASSPATH=$(cygpath --path --windows "$CLASSPATH")
+  [ -n "$MAVEN_PROJECTBASEDIR" ] &&
+    MAVEN_PROJECTBASEDIR=$(cygpath --path --windows "$MAVEN_PROJECTBASEDIR")
+fi
+
+# Provide a "standardized" way to retrieve the CLI args that will
+# work with both Windows and non-Windows executions.
+MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $*"
+export MAVEN_CMD_LINE_ARGS
+
+WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
+
+# shellcheck disable=SC2086 # safe args
+exec "$JAVACMD" \
+  $MAVEN_OPTS \
+  $MAVEN_DEBUG_OPTS \
+  -classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
+  "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
+  ${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
diff --git a/pom.xml b/pom.xml
index d8bf9324ad18b6c3c1236b0a497786de1cc74a1d..3ce0e3cbae3e5ecd0843ab088e458bb5e53dbf0f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,264 +1,205 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<groupId>info.textgrid.middleware</groupId>
-	<artifactId>message-beans</artifactId>
-	<version>3.3.1-SNAPSHOT</version>
-	<packaging>war</packaging>
-	<name>DARIAHDE :: Repository :: Message Driven Beans</name>
-	<description>Message driven beans for the TextGrid and DARIAH-DE Repository</description>
-	<url>https://de.dariah.eu</url>
-	<properties>
-		<common.version>4.0.1</common.version>
-		<commons-imaging.version>1.0-alpha1</commons-imaging.version>
-		<commons-io.version>2.4</commons-io.version>
-		<crud.version>11.0.0-DH-RELEASE</crud.version>
-		<cyclonedx-maven-plugin.version>2.7.0</cyclonedx-maven-plugin.version>
-		<jboss-bom.version>8.0.0.Final</jboss-bom.version>
-		<jboss-javaee-all-7.0.version>1.0.0.Final</jboss-javaee-all-7.0.version>
-		<jdeb.version>1.4</jdeb.version>
-		<jdk.version>1.7</jdk.version>
-		<junit.version>4.12</junit.version>
-		<maven-compiler-plugin.version>3.1</maven-compiler-plugin.version>
-		<maven-deploy-plugin.version>2.8.2</maven-deploy-plugin.version>
-		<maven-eclipse-plugin.version>2.9</maven-eclipse-plugin.version>
-		<maven-war-plugin.version>3.0.0</maven-war-plugin.version>
-		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
-		<saxon-he.version>9.5.0.2</saxon-he.version>
-		<wildfly-maven-plugin.version>1.0.2.Final</wildfly-maven-plugin.version>
-	</properties>
-	<dependencyManagement>
-		<dependencies>
-			<!-- Define the version of JBoss' Java EE 7 APIs we want to use -->
-			<!-- JBoss distributes a complete set of Java EE 7 APIs including a Bill 
-				of Materials (BOM). A BOM specifies the versions of a "stack" (or a collection) 
-				of artifacts. We use this here so that we always get the correct versions 
-				of artifacts. Here we use the jboss-javaee-7.0 stack (you can read this as 
-				the JBoss stack of the Java EE 7 APIs). You can actually use this stack with 
-				any version of WildFly that implements Java EE 7, not just JBoss WildFly 
-				8! -->
-			<dependency>
-				<groupId>org.jboss.spec</groupId>
-				<artifactId>jboss-javaee-all-7.0</artifactId>
-				<version>${jboss-javaee-all-7.0.version}</version>
-				<type>pom</type>
-				<scope>import</scope>
-			</dependency>
-			<dependency>
-				<groupId>org.wildfly.bom</groupId>
-				<artifactId>jboss-javaee-7.0-with-resteasy</artifactId>
-				<version>${jboss-bom.version}</version>
-				<scope>import</scope>
-				<type>pom</type>
-			</dependency>
-		</dependencies>
-	</dependencyManagement>
-	<dependencies>
-		<!-- First declare the APIs we depend on and need for compilation. All 
-			of them are provided by JBoss WildFly -->
-		<dependency>
-			<groupId>org.jboss.spec.javax.jms</groupId>
-			<artifactId>jboss-jms-api_2.0_spec</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<!-- Import the EJB API, we use provided scope as the API is included in 
-			JBoss WildFly -->
-		<dependency>
-			<groupId>org.jboss.spec.javax.ejb</groupId>
-			<artifactId>jboss-ejb-api_3.2_spec</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<!-- Import the CDI API, we use provided scope as the API is included in 
-			JBoss WildFly -->
-		<dependency>
-			<groupId>javax.enterprise</groupId>
-			<artifactId>cdi-api</artifactId>
-			<scope>provided</scope>
-		</dependency>
-		<!-- We want JAX-RS client! -->
-		<dependency>
-			<groupId>org.jboss.resteasy</groupId>
-			<artifactId>jaxrs-api</artifactId>
-		</dependency>
-		<!-- RESTEasy implementation of JAX-RS API -->
-		<dependency>
-			<groupId>org.jboss.resteasy</groupId>
-			<artifactId>resteasy-jaxrs</artifactId>
-		</dependency>
-		<!-- RESTEasy implementation of JAX-RS Client API -->
-		<dependency>
-			<groupId>org.jboss.resteasy</groupId>
-			<artifactId>resteasy-client</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>info.textgrid.middleware</groupId>
-			<artifactId>dhcrud-api</artifactId>
-			<version>${crud.version}</version>
-			<exclusions>
-				<!-- Exclude frontend-jaxrs due to Wildfly deployment dependency problems 
-					in JBoss. -->
-				<exclusion>
-					<groupId>org.apache.cxf</groupId>
-					<artifactId>cxf-rt-frontend-jaxrs</artifactId>
-				</exclusion>
-			</exclusions>
-		</dependency>
-		<dependency>
-			<groupId>info.textgrid.middleware</groupId>
-			<artifactId>jpairtree</artifactId>
-			<version>${common.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>info.textgrid.middleware</groupId>
-			<artifactId>cacheutils</artifactId>
-			<version>${common.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>info.textgrid.middleware</groupId>
-			<artifactId>const</artifactId>
-			<version>${common.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>info.textgrid.middleware</groupId>
-			<artifactId>tgcrud-client</artifactId>
-			<version>${crud.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>commons-io</groupId>
-			<artifactId>commons-io</artifactId>
-			<version>${commons-io.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>org.apache.commons</groupId>
-			<artifactId>commons-imaging</artifactId>
-			<version>${commons-imaging.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>net.sf.saxon</groupId>
-			<artifactId>Saxon-HE</artifactId>
-			<version>${saxon-he.version}</version>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<version>${junit.version}</version>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-	<repositories>
-		<repository>
-			<id>maven-dariah-public</id>
-			<name>GWDG Nexus DARIAH-DE Repository</name>
-			<url>https://nexus.gwdg.de/repository/maven-dariah-public/</url>
-		</repository>
-	</repositories>
-	<build>
-		<finalName>${project.artifactId}</finalName>
-		<defaultGoal>package</defaultGoal>
-		<plugins>
-			<plugin>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<version>${maven-compiler-plugin.version}</version>
-				<configuration>
-					<source>${jdk.version}</source>
-					<target>${jdk.version}</target>
-				</configuration>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-deploy-plugin</artifactId>
-				<version>${maven-deploy-plugin.version}</version>
-				<configuration>
-					<skip>true</skip>
-				</configuration>
-			</plugin>
-			<plugin>
-				<artifactId>maven-war-plugin</artifactId>
-				<version>${maven-war-plugin.version}</version>
-				<configuration>
-					<!-- Java EE 7 doesn't require web.xml, Maven needs to catch up! -->
-					<failOnMissingWebXml>false</failOnMissingWebXml>
-				</configuration>
-			</plugin>
-			<!-- The WildFly plugin deploys your war to a local WildFly container -->
-			<!-- To use, run: mvn package wildfly:deploy -->
-			<plugin>
-				<groupId>org.wildfly.plugins</groupId>
-				<artifactId>wildfly-maven-plugin</artifactId>
-				<version>${wildfly-maven-plugin.version}</version>
-			</plugin>
-			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-eclipse-plugin</artifactId>
-				<version>${maven-eclipse-plugin.version}</version>
-				<configuration>
-					<downloadSources>true</downloadSources>
-					<downloadJavadocs>true</downloadJavadocs>
-				</configuration>
-			</plugin>
-		</plugins>
-	</build>
-	<profiles>
-		<profile>
-			<id>sbom</id>
-			<build>
-				<plugins>
-					<plugin>
-						<groupId>org.cyclonedx</groupId>
-						<artifactId>cyclonedx-maven-plugin</artifactId>
-						<version>${cyclonedx-maven-plugin.version}</version>
-						<executions>
-							<execution>
-								<phase>package</phase>
-								<goals>
-									<goal>makeAggregateBom</goal>
-								</goals>
-							</execution>
-						</executions>
-						<configuration>
-							<outputFormat>JSON</outputFormat>
-						</configuration>
-					</plugin>
-				</plugins>
-			</build>
-		</profile>
-		<profile>
-			<id>dhrep.deb</id>
-			<build>
-				<plugins>
-					<plugin>
-						<groupId>org.vafer</groupId>
-						<artifactId>jdeb</artifactId>
-						<version>${jdeb.version}</version>
-						<executions>
-							<execution>
-								<phase>package</phase>
-								<goals>
-									<goal>jdeb</goal>
-								</goals>
-								<configuration>
-									<snapshotExpand>true</snapshotExpand>
-									<dataSet>
-										<data>
-											<type>file</type>
-											<src>${project.build.directory}/${project.build.finalName}.war</src>
-											<mapper>
-												<type>perm</type>
-												<prefix>/var/dhrep/webapps/${project.build.finalName}</prefix>
-												<user>root</user>
-												<group>wildfly</group>
-												<filemode>755</filemode>
-											</mapper>
-										</data>
-									</dataSet>
-								</configuration>
-							</execution>
-						</executions>
-					</plugin>
-				</plugins>
-			</build>
-		</profile>
-	</profiles>
+<?xml version="1.0"?>
+<project
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
+    xmlns="http://maven.apache.org/POM/4.0.0"
+    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+    <modelVersion>4.0.0</modelVersion>
+    <groupId>info.textgrid.middleware</groupId>
+    <artifactId>message-beans</artifactId>
+    <version>4.0.0-SNAPSHOT</version>
+    <name>DARIAHDE :: Repository :: Message Driven Beans</name>
+    <description>Message driven beans for the TextGrid and DARIAH-DE Repository</description>
+    <properties>
+        <compiler-plugin.version>3.11.0</compiler-plugin.version>
+        <common.version>6.1.0</common.version>
+        <commons-imaging.version>1.0-alpha3</commons-imaging.version>
+        <commons-io.version>2.15.1</commons-io.version>
+        <crud.version>12.0.1</crud.version>
+        <cyclonedx-maven-plugin.version>2.7.0</cyclonedx-maven-plugin.version>
+        <maven.compiler.release>17</maven.compiler.release>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
+        <quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
+        <quarkus.platform.version>3.6.3</quarkus.platform.version>
+        <skipITs>true</skipITs>
+        <surefire-plugin.version>3.1.2</surefire-plugin.version>
+    </properties>
+    <repositories>
+        <repository>
+            <id>maven-dariah-public</id>
+            <name>GWDG Nexus DARIAH-DE Repository</name>
+            <url>https://nexus.gwdg.de/repository/maven-dariah-public/</url>
+        </repository>
+    </repositories>
+    <distributionManagement>
+        <snapshotRepository>
+            <id>maven-dariah-public</id>
+            <name>GWDG Nexus DARIAH-DE Repository</name>
+            <url>https://nexus.gwdg.de/repository/maven-dariah-public/</url>
+        </snapshotRepository>
+        <repository>
+            <id>maven-dariah-public</id>
+            <name>GWDG Nexus DARIAH-DE Repository</name>
+            <url>https://nexus.gwdg.de/repository/maven-dariah-public/</url>
+        </repository>
+    </distributionManagement>
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>${quarkus.platform.artifact-id}</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+    <dependencies>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-smallrye-reactive-messaging-amqp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-arc</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-rest-client-reactive-jaxb</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-micrometer-registry-prometheus</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>info.textgrid.middleware</groupId>
+            <artifactId>cacheutils</artifactId>
+            <version>${common.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>info.textgrid.middleware</groupId>
+            <artifactId>const</artifactId>
+            <version>${common.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>info.textgrid.middleware</groupId>
+            <artifactId>dhcrud-api</artifactId>
+            <version>${crud.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>info.textgrid.middleware</groupId>
+            <artifactId>jpairtree</artifactId>
+            <version>${common.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-imaging</artifactId>
+            <version>${commons-imaging.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>io.quarkus</groupId>
+            <artifactId>quarkus-junit5</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons-io.version}</version>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <id>sbom</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.cyclonedx</groupId>
+                        <artifactId>cyclonedx-maven-plugin</artifactId>
+                        <version>${cyclonedx-maven-plugin.version}</version>
+                        <executions>
+                            <execution>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>makeAggregateBom</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <outputFormat>JSON</outputFormat>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>native</id>
+            <activation>
+                <property>
+                    <name>native</name>
+                </property>
+            </activation>
+            <properties>
+                <skipITs>false</skipITs>
+                <quarkus.package.type>native</quarkus.package.type>
+            </properties>
+        </profile>
+    </profiles>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>${quarkus.platform.group-id}</groupId>
+                <artifactId>quarkus-maven-plugin</artifactId>
+                <version>${quarkus.platform.version}</version>
+                <extensions>true</extensions>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>build</goal>
+                            <goal>generate-code</goal>
+                            <goal>generate-code-tests</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${compiler-plugin.version}</version>
+                <configuration>
+                    <compilerArgs>
+                        <arg>-parameters</arg>
+                    </compilerArgs>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <configuration>
+                    <systemPropertyVariables>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+            <plugin>
+                <artifactId>maven-failsafe-plugin</artifactId>
+                <version>${surefire-plugin.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>integration-test</goal>
+                            <goal>verify</goal>
+                        </goals>
+                    </execution>
+                </executions>
+                <configuration>
+                    <systemPropertyVariables>
+                        <native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
+                        <java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
+                        <maven.home>${maven.home}</maven.home>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
 </project>
diff --git a/src/deb/control/control b/src/deb/control/control
deleted file mode 100644
index faba3688597acc66140bd66191ad42eba50d5956..0000000000000000000000000000000000000000
--- a/src/deb/control/control
+++ /dev/null
@@ -1,7 +0,0 @@
-Package: [[artifactId]]
-Version: [[version]]
-Section: misc
-Priority: low
-Architecture: all
-Description: [[description]]
-Maintainer: funk@sub.uni-goettingen.de
diff --git a/src/deb/control/postinst b/src/deb/control/postinst
deleted file mode 100644
index 6f351a61de34315c6b860dee857156404e3640ff..0000000000000000000000000000000000000000
--- a/src/deb/control/postinst
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-service wildfly start
-# return success, even if service not installed
-#exit 0
diff --git a/src/deb/control/preinst b/src/deb/control/preinst
deleted file mode 100644
index 08cb8e51f71daa409ed611a6bc14480f1117c73c..0000000000000000000000000000000000000000
--- a/src/deb/control/preinst
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-service wildfly stop
-# return success, even if service not installed
-#exit 0
diff --git a/src/docker/config-jms.cli b/src/docker/config-jms.cli
deleted file mode 100644
index 691c36661a60bd3d456defa77fb63c045536f2da..0000000000000000000000000000000000000000
--- a/src/docker/config-jms.cli
+++ /dev/null
@@ -1,3 +0,0 @@
-embed-server --server-config=standalone-full.xml
-jms-topic add --topic-address=tgcrudTopic --entries=topic/tgcrud,java:jboss/exported/jms/topic/tgcrud
-
diff --git a/src/main/docker/Dockerfile.jvm b/src/main/docker/Dockerfile.jvm
new file mode 100644
index 0000000000000000000000000000000000000000..d90e3ec7952054d56b21c99daf0c470b8d63c708
--- /dev/null
+++ b/src/main/docker/Dockerfile.jvm
@@ -0,0 +1,97 @@
+####
+# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
+#
+# Before building the container image run:
+#
+# ./mvnw package
+#
+# Then, build the image with:
+#
+# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/message-beans-jvm .
+#
+# Then run the container using:
+#
+# docker run -i --rm -p 8080:8080 quarkus/message-beans-jvm
+#
+# If you want to include the debug port into your docker image
+# you will have to expose the debug port (default 5005 being the default) like this :  EXPOSE 8080 5005.
+# Additionally you will have to set -e JAVA_DEBUG=true and -e JAVA_DEBUG_PORT=*:5005
+# when running the container
+#
+# Then run the container using :
+#
+# docker run -i --rm -p 8080:8080 quarkus/message-beans-jvm
+#
+# This image uses the `run-java.sh` script to run the application.
+# This scripts computes the command line to execute your Java application, and
+# includes memory/GC tuning.
+# You can configure the behavior using the following environment properties:
+# - JAVA_OPTS: JVM options passed to the `java` command (example: "-verbose:class")
+# - JAVA_OPTS_APPEND: User specified Java options to be appended to generated options
+#   in JAVA_OPTS (example: "-Dsome.property=foo")
+# - JAVA_MAX_MEM_RATIO: Is used when no `-Xmx` option is given in JAVA_OPTS. This is
+#   used to calculate a default maximal heap memory based on a containers restriction.
+#   If used in a container without any memory constraints for the container then this
+#   option has no effect. If there is a memory constraint then `-Xmx` is set to a ratio
+#   of the container available memory as set here. The default is `50` which means 50%
+#   of the available memory is used as an upper boundary. You can skip this mechanism by
+#   setting this value to `0` in which case no `-Xmx` option is added.
+# - JAVA_INITIAL_MEM_RATIO: Is used when no `-Xms` option is given in JAVA_OPTS. This
+#   is used to calculate a default initial heap memory based on the maximum heap memory.
+#   If used in a container without any memory constraints for the container then this
+#   option has no effect. If there is a memory constraint then `-Xms` is set to a ratio
+#   of the `-Xmx` memory as set here. The default is `25` which means 25% of the `-Xmx`
+#   is used as the initial heap size. You can skip this mechanism by setting this value
+#   to `0` in which case no `-Xms` option is added (example: "25")
+# - JAVA_MAX_INITIAL_MEM: Is used when no `-Xms` option is given in JAVA_OPTS.
+#   This is used to calculate the maximum value of the initial heap memory. If used in
+#   a container without any memory constraints for the container then this option has
+#   no effect. If there is a memory constraint then `-Xms` is limited to the value set
+#   here. The default is 4096MB which means the calculated value of `-Xms` never will
+#   be greater than 4096MB. The value of this variable is expressed in MB (example: "4096")
+# - JAVA_DIAGNOSTICS: Set this to get some diagnostics information to standard output
+#   when things are happening. This option, if set to true, will set
+#  `-XX:+UnlockDiagnosticVMOptions`. Disabled by default (example: "true").
+# - JAVA_DEBUG: If set remote debugging will be switched on. Disabled by default (example:
+#    true").
+# - JAVA_DEBUG_PORT: Port used for remote debugging. Defaults to 5005 (example: "8787").
+# - CONTAINER_CORE_LIMIT: A calculated core limit as described in
+#   https://www.kernel.org/doc/Documentation/scheduler/sched-bwc.txt. (example: "2")
+# - CONTAINER_MAX_MEMORY: Memory limit given to the container (example: "1024").
+# - GC_MIN_HEAP_FREE_RATIO: Minimum percentage of heap free after GC to avoid expansion.
+#   (example: "20")
+# - GC_MAX_HEAP_FREE_RATIO: Maximum percentage of heap free after GC to avoid shrinking.
+#   (example: "40")
+# - GC_TIME_RATIO: Specifies the ratio of the time spent outside the garbage collection.
+#   (example: "4")
+# - GC_ADAPTIVE_SIZE_POLICY_WEIGHT: The weighting given to the current GC time versus
+#   previous GC times. (example: "90")
+# - GC_METASPACE_SIZE: The initial metaspace size. (example: "20")
+# - GC_MAX_METASPACE_SIZE: The maximum metaspace size. (example: "100")
+# - GC_CONTAINER_OPTIONS: Specify Java GC to use. The value of this variable should
+#   contain the necessary JRE command-line options to specify the required GC, which
+#   will override the default of `-XX:+UseParallelGC` (example: -XX:+UseG1GC).
+# - HTTPS_PROXY: The location of the https proxy. (example: "myuser@127.0.0.1:8080")
+# - HTTP_PROXY: The location of the http proxy. (example: "myuser@127.0.0.1:8080")
+# - NO_PROXY: A comma separated lists of hosts, IP addresses or domains that can be
+#   accessed directly. (example: "foo.example.com,bar.example.com")
+#
+###
+FROM registry.access.redhat.com/ubi8/openjdk-17:1.18
+
+ENV LANGUAGE='en_US:en'
+
+
+# We make four distinct layers so if there are application changes the library layers can be re-used
+COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
+COPY --chown=185 target/quarkus-app/*.jar /deployments/
+COPY --chown=185 target/quarkus-app/app/ /deployments/app/
+COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
+
+EXPOSE 8080
+USER 185
+ENV JAVA_OPTS_APPEND="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
+
+ENTRYPOINT [ "/opt/jboss/container/java/run/run-java.sh" ]
+
diff --git a/src/main/docker/Dockerfile.jvm-multistage b/src/main/docker/Dockerfile.jvm-multistage
new file mode 100644
index 0000000000000000000000000000000000000000..9e8db188dc8671f84c843847d5315ee4e6c4ddbf
--- /dev/null
+++ b/src/main/docker/Dockerfile.jvm-multistage
@@ -0,0 +1,28 @@
+## Stage 1 : build with maven builder image
+FROM maven:3.8.7-eclipse-temurin-17 as build
+COPY . /code/
+WORKDIR /code
+RUN --mount=type=cache,target=/root/.m2 mvn clean package
+
+## Stage 2 : create the docker final image
+#FROM registry.access.redhat.com/ubi8/openjdk-17:1.18
+FROM debian:bookworm-slim
+ENV LANGUAGE='en_US:en'
+WORKDIR /work/
+RUN chmod 775 /work
+RUN apt-get update -y && \
+    apt-get upgrade -y && \
+    apt-get install --no-install-recommends -y \
+    openjdk-17-jdk \
+    libvips-tools \
+    # save some space
+    && rm -rf /var/lib/apt/lists/*
+# We make four distinct layers so if there are application changes the library layers can be re-used
+COPY --from=build /code/target/quarkus-app/lib/ /deployments/lib/
+COPY --from=build /code/target/quarkus-app/*.jar /deployments/
+COPY --from=build /code/target/quarkus-app/app/ /deployments/app/
+COPY --from=build /code/target/quarkus-app/quarkus/ /deployments/quarkus/
+EXPOSE 8080
+ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
+ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
+ENTRYPOINT ["/usr/lib/jvm/java-17-openjdk-amd64/bin/java", "-jar", "/deployments/quarkus-run.jar", "-Dquarkus.http.host=0.0.0.0", "-Djava.util.logging.manager=org.jboss.logmanager.LogManager"]
diff --git a/src/main/docker/Dockerfile.native-multistage b/src/main/docker/Dockerfile.native-multistage
new file mode 100644
index 0000000000000000000000000000000000000000..4f193d4b72be124eecb3d3306f5ee52173570949
--- /dev/null
+++ b/src/main/docker/Dockerfile.native-multistage
@@ -0,0 +1,18 @@
+## Stage 1 : build with maven builder image with native capabilities
+FROM quay.io/quarkus/ubi-quarkus-mandrel-builder-image:jdk-17 AS build
+USER root
+COPY . /code/
+WORKDIR /code
+RUN --mount=type=cache,target=/root/.m2 ./mvnw clean package -Dnative
+
+## Stage 2 : create the docker final image
+FROM debian:bookworm-slim
+WORKDIR /work/
+COPY --from=build /code/target/*-runner /work/application
+RUN chmod 775 /work
+RUN apt-get update -y && apt-get upgrade -y && apt-get install --no-install-recommends -y \
+    libvips-tools \
+    # save some space
+    && rm -rf /var/lib/apt/lists/*
+EXPOSE 8080
+CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/src/main/java/info/textgrid/middleware/ejb/Connect.java b/src/main/java/info/textgrid/middleware/ejb/Connect.java
deleted file mode 100644
index 8ad16ce9a4575c588590078a2332d19ae723af2b..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/ejb/Connect.java
+++ /dev/null
@@ -1,49 +0,0 @@
-package info.textgrid.middleware.ejb;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URISyntaxException;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.MetadataParseFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault;
-
-/**
- *
- */
-public interface Connect {
-
-  /**
-   * 
-   */
-  public void init();
-
-  /**
-   * @param theUri
-   * @return
-   * @throws MetadataParseFault
-   * @throws ObjectNotFoundFault
-   * @throws IoFault
-   * @throws AuthFault
-   * @throws ProtocolNotImplementedFault
-   * @throws IOException
-   * @throws URISyntaxException
-   * @throws NullPointerException
-   */
-  public InputStream getObjectData(String theUri) throws MetadataParseFault, ObjectNotFoundFault,
-      IoFault, AuthFault, ProtocolNotImplementedFault, IOException, NullPointerException,
-      URISyntaxException;
-
-  /**
-   * @param key
-   * @return
-   */
-  public String getProperty(String key);
-
-  /**
-   * @return
-   */
-  public String getAuth();
-
-}
diff --git a/src/main/java/info/textgrid/middleware/ejb/ConnectAbs.java b/src/main/java/info/textgrid/middleware/ejb/ConnectAbs.java
deleted file mode 100644
index 470949e8a0cd23241005ec20c864af8c911e4208..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/ejb/ConnectAbs.java
+++ /dev/null
@@ -1,45 +0,0 @@
-package info.textgrid.middleware.ejb;
-
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Properties;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- *
- */
-public abstract class ConnectAbs implements Connect {
-
-  protected final static Logger LOGGER = Logger.getLogger(Connect.class.getName());
-
-  protected String propertiesLocation;
-  protected Properties properties;
-  protected URL crudUrl;
-
-  /**
-   * 
-   */
-  public void init() {
-
-    this.properties = new Properties();
-    BufferedInputStream stream;
-
-    try {
-      stream = new BufferedInputStream(new FileInputStream(this.propertiesLocation));
-      this.properties.load(stream);
-      stream.close();
-
-      this.crudUrl = new URL(this.properties.getProperty("crudUrl"));
-
-    } catch (FileNotFoundException e) {
-      LOGGER.log(Level.SEVERE, "Properties file not found!", e);
-    } catch (IOException e) {
-      LOGGER.log(Level.SEVERE, "Unable to get CRUD URL from properties file!", e);
-    }
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/ejb/DHConnectEJB.java b/src/main/java/info/textgrid/middleware/ejb/DHConnectEJB.java
deleted file mode 100644
index e5c3a6ef98c1ad29315abd0ab99f17cfecee3847..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/ejb/DHConnectEJB.java
+++ /dev/null
@@ -1,93 +0,0 @@
-package info.textgrid.middleware.ejb;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URI;
-import java.net.URISyntaxException;
-import javax.ejb.Stateful;
-import javax.ws.rs.core.Response;
-import org.apache.cxf.helpers.IOUtils;
-import org.jboss.resteasy.client.jaxrs.ResteasyClient;
-import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.DHCrudService;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.MetadataParseFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault;
-
-/**
- *
- */
-@Stateful
-public class DHConnectEJB extends ConnectAbs {
-
-  private static final String CLASS_NAME = "{DHConnectEJB} ";
-
-  private ResteasyClient rclient = new ResteasyClientBuilder().connectionPoolSize(100).build();
-
-  /**
-   * @param thePropertiesLocation
-   */
-  public DHConnectEJB() {
-
-    this.propertiesLocation = "/etc/dhrep/messagebeans/dhmb.properties";
-
-    init();
-
-    LOGGER.info(CLASS_NAME + "Called init()");
-  }
-
-  /**
-   * @param theUri
-   * @param theTempFile
-   * @throws IOException
-   * @throws URISyntaxException
-   * @throws NullPointerException
-   */
-  public void getObjectData(String theUri, File theTempFile)
-      throws IOException, NullPointerException, URISyntaxException {
-
-    DHCrudService dhclient = this.rclient.target(this.crudUrl.toURI()).proxy(DHCrudService.class);
-
-    Response response = dhclient.read(URI.create(theUri), 0l, "MB" + System.currentTimeMillis());
-
-    LOGGER.info(CLASS_NAME + "Retrieving data from " + theUri + ", storing to " + theTempFile);
-
-    IOUtils.transferTo(response.readEntity(InputStream.class), theTempFile);
-
-    response.close();
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see info.textgrid.middleware.ejb.Connect#getProperty(java.lang.String)
-   */
-  public String getProperty(String key) {
-    return this.properties.getProperty(key);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see info.textgrid.middleware.ejb.Connect#getAuth()
-   */
-  public String getAuth() {
-    return "";
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see info.textgrid.middleware.ejb.Connect#getObjectData(java.lang.String)
-   */
-  public InputStream getObjectData(String theUri)
-      throws MetadataParseFault, ObjectNotFoundFault, IoFault, AuthFault,
-      ProtocolNotImplementedFault, IOException, NullPointerException, URISyntaxException {
-    // TODO Auto-generated method stub
-    return null;
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/ejb/TGConnect.java b/src/main/java/info/textgrid/middleware/ejb/TGConnect.java
deleted file mode 100644
index c762531063f22661556095927064333c307fe4b4..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/ejb/TGConnect.java
+++ /dev/null
@@ -1,178 +0,0 @@
-package info.textgrid.middleware.ejb;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.logging.Level;
-import javax.activation.DataHandler;
-import javax.ws.rs.client.Client;
-import javax.ws.rs.client.ClientBuilder;
-import javax.ws.rs.client.Entity;
-import javax.ws.rs.client.WebTarget;
-import javax.ws.rs.core.Form;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.xml.ws.Holder;
-import info.textgrid.namespaces.metadata.core._2010.MetadataContainerType;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.AuthFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.IoFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.MetadataParseFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ObjectNotFoundFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.ProtocolNotImplementedFault;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.TGCrudService;
-import info.textgrid.namespaces.middleware.tgcrud.services.tgcrudservice.tgcrudclient.TGCrudClientUtilities;
-
-/**
- *
- */
-public class TGConnect extends ConnectAbs {
-
-  private TGCrudService tgcrudclient;
-  private String sid;
-  private String textgridUser;
-  private String textgridPw;
-  private int count;
-  private URL webauthUrl;
-  private String authzInstance;
-
-  /**
-   * @param thePropertiesLocation
-   */
-  public TGConnect(String thePropertiesLocation) {
-
-    this.propertiesLocation = thePropertiesLocation;
-
-    init();
-
-    try {
-      this.tgcrudclient = TGCrudClientUtilities.getTgcrud(this.crudUrl.toString());
-
-      LOGGER.fine("New TG-crud HTTP client created: " + this.tgcrudclient.getVersion());
-
-    } catch (MalformedURLException e) {
-      // TODO Auto-generated catch block
-      e.printStackTrace();
-    }
-  }
-
-  /**
-   * 
-   */
-  public void init() {
-
-    super.init();
-
-    try {
-      this.textgridUser = this.properties.getProperty("textgrid.login");
-      this.textgridPw = this.properties.getProperty("textgrid.password");
-      this.webauthUrl = new URL(this.properties.getProperty("webauthUrl"));
-      this.authzInstance = this.properties.getProperty("authzinstance");
-    } catch (IOException e) {
-      // TODO Auto-generated catch block
-      e.printStackTrace();
-    }
-  }
-
-  /**
-   * @param textgridUri
-   * @return
-   * @throws MetadataParseFault
-   * @throws ObjectNotFoundFault
-   * @throws IoFault
-   * @throws AuthFault
-   * @throws ProtocolNotImplementedFault
-   * @throws IOException
-   */
-  public InputStream getObjectData(String textgridUri) throws MetadataParseFault,
-      ObjectNotFoundFault, IoFault, AuthFault, ProtocolNotImplementedFault, IOException {
-
-    Holder<MetadataContainerType> metaHolder = new Holder<MetadataContainerType>();
-    Holder<DataHandler> dataHolder = new Holder<DataHandler>();
-
-    this.tgcrudclient.read(getAuth(), "", textgridUri, metaHolder, dataHolder);
-
-    return dataHolder.value.getInputStream();
-  }
-
-  /**
-   * @param key
-   * @return
-   */
-  public String getProperty(String key) {
-    return this.properties.getProperty(key);
-  }
-
-  /**
-   * @return
-   */
-  public String getAuth() {
-
-    LOGGER.fine("ejb-count:" + this.count);
-    this.count++;
-
-    if (this.sid == null) {
-      this.sid = getSidFromAuth();
-    }
-
-    return this.sid;
-  }
-
-  // **
-  // PRIVATE METHODS
-  // **
-
-  /**
-   * @return
-   */
-  private String getSidFromAuth() {
-
-    if (this.textgridUser == null || this.textgridPw == null) {
-      LOGGER.info("no user or pw, assuming sidless operations");
-      return "";
-    }
-
-    String sid = "";
-
-    try {
-      Form form = new Form();
-      form.param("loginname", this.textgridUser);
-      form.param("password", this.textgridPw);
-      form.param("authZinstance", this.authzInstance);
-
-      LOGGER.info(
-          "get sid for " + this.textgridUser + " / webauthurl: " + this.webauthUrl.toString());
-
-      Client client = ClientBuilder.newClient();
-
-      WebTarget target =
-          client.target(this.webauthUrl.getProtocol() + "://" + this.webauthUrl.getHost())
-              .path(this.webauthUrl.getPath());
-
-      Response res =
-          target.request().post(Entity.entity(form, MediaType.APPLICATION_FORM_URLENCODED_TYPE));
-
-      BufferedReader reader =
-          new BufferedReader(new InputStreamReader(res.readEntity(InputStream.class)));
-
-      String line;
-      while ((line = reader.readLine()) != null) {
-        if (line.startsWith("<meta name=\"rbac_sessionid")) {
-          int cpos = line.indexOf("content=");
-          int bpos = line.indexOf("\"", cpos) + 1;
-          int epos = line.indexOf("\"", bpos);
-          sid = line.substring(bpos, epos);
-          break;
-        }
-      }
-
-    } catch (IOException e) {
-      LOGGER.log(Level.SEVERE, "error getting sid ", e);
-    }
-
-    return sid;
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/DHAllMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/DHAllMDB.java
deleted file mode 100644
index f555d3df9f4e4260fe85e009f442223e3f302074..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/DHAllMDB.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// package info.textgrid.middleware.messagebeans;
-//
-// import javax.ejb.ActivationConfigProperty;
-// import javax.ejb.MessageDriven;
-// import javax.jms.JMSException;
-// import javax.jms.Message;
-//
-/// **
-// *
-// */
-// @MessageDriven(name = "DHAllMDB", activationConfig = {
-// @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/dhcrud"),
-// @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-// @ActivationConfigProperty(propertyName = "acknowledgeMode",
-// propertyValue = "Auto-acknowledge")})
-// public class DHAllMDB extends DHMessageBeanAbs {
-//
-// /*
-// * (non-Javadoc)
-// *
-// * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
-// */
-// public void onMessage(Message msg) {
-// try {
-// logMoreInfo(this.getClass().getSimpleName(), msg);
-// } catch (JMSException e) {
-// throw new RuntimeException(e);
-// }
-// }
-//
-// }
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/DHImageMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/DHImageMDB.java
deleted file mode 100644
index b7f66897ef8f6a774b117ee05f52e830f30e5606..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/DHImageMDB.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// package info.textgrid.middleware.messagebeans;
-//
-// import javax.ejb.ActivationConfigProperty;
-// import javax.ejb.MessageDriven;
-// import javax.jms.JMSException;
-// import javax.jms.Message;
-// import info.textgrid.namespaces.middleware.tgcrud.common.CrudOperations;
-//
-/// **
-// *
-// */
-// @MessageDriven(name = "DHImageMDB", activationConfig = {
-// @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/dhcrud"),
-// @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-// @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
-// @ActivationConfigProperty(propertyName = "messageSelector",
-// propertyValue = "format LIKE 'image/%' AND operation=" + CrudOperations.CREATE)})
-// public class DHImageMDB extends DHMessageBeanAbs {
-//
-// /*
-// * (non-Javadoc)
-// *
-// * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
-// */
-// public void onMessage(Message msg) {
-// try {
-// logMoreInfo(this.getClass().getSimpleName(), msg);
-// } catch (JMSException e) {
-// throw new RuntimeException(e);
-// }
-// }
-//
-// }
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/DHLoggingMessageConsumer.java b/src/main/java/info/textgrid/middleware/messagebeans/DHLoggingMessageConsumer.java
new file mode 100644
index 0000000000000000000000000000000000000000..7e3b9bce46485131b94148190dbbb00e3b645e0d
--- /dev/null
+++ b/src/main/java/info/textgrid/middleware/messagebeans/DHLoggingMessageConsumer.java
@@ -0,0 +1,28 @@
+package info.textgrid.middleware.messagebeans;
+
+import java.util.concurrent.CompletionStage;
+import org.eclipse.microprofile.reactive.messaging.Incoming;
+import org.eclipse.microprofile.reactive.messaging.Message;
+import info.textgrid.middleware.model.CrudMessage;
+import io.smallrye.reactive.messaging.annotations.Blocking;
+
+/**
+ *
+ */
+public class DHLoggingMessageConsumer extends MessageConsumerAbs {
+
+  /**
+   * @param message
+   * @return
+   */
+  @Incoming("dhcrud")
+  @Blocking
+  CompletionStage<Void> onMessage(Message<CrudMessage> message) {
+
+    CrudMessage msg = fromMessage(message);
+    logInfo(this.getClass().getSimpleName(), msg);
+
+    return message.ack();
+  }
+
+}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/DHMessageBeanAbs.java b/src/main/java/info/textgrid/middleware/messagebeans/DHMessageBeanAbs.java
deleted file mode 100644
index 7649e15352c1bacd11cfd4e79727771bb42ed983..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/DHMessageBeanAbs.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package info.textgrid.middleware.messagebeans;
-
-/**
- *
- */
-public abstract class DHMessageBeanAbs extends MessageBeanAbs {
-
-  /**
-   * 
-   */
-  public DHMessageBeanAbs() {
-    MessageBeanAbs.setUriKey("pid");
-    MessageBeanAbs.setRootIdKey("collection");
-    MessageBeanAbs.setJmsTypeKey("dhcrud-notification");
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/DHDigilibPrescalerMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/DHPrescaleMessageConsumer.java
similarity index 67%
rename from src/main/java/info/textgrid/middleware/messagebeans/DHDigilibPrescalerMDB.java
rename to src/main/java/info/textgrid/middleware/messagebeans/DHPrescaleMessageConsumer.java
index 4aca04a7ec609abdc10065160e28721f2b68838a..304d8b7a4cf169076a5639be60af8926cef8b40d 100644
--- a/src/main/java/info/textgrid/middleware/messagebeans/DHDigilibPrescalerMDB.java
+++ b/src/main/java/info/textgrid/middleware/messagebeans/DHPrescaleMessageConsumer.java
@@ -2,50 +2,49 @@ package info.textgrid.middleware.messagebeans;
 
 import java.io.File;
 import java.io.IOException;
-import java.net.URISyntaxException;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
 import java.util.List;
-import java.util.logging.Level;
-import javax.ejb.ActivationConfigProperty;
-import javax.ejb.EJB;
-import javax.ejb.MessageDriven;
-import javax.jms.JMSException;
-import javax.jms.Message;
+import java.util.concurrent.CompletionStage;
 import org.apache.commons.imaging.ImageReadException;
+import org.eclipse.microprofile.reactive.messaging.Incoming;
+import org.eclipse.microprofile.reactive.messaging.Message;
 import info.textgrid.middleware.common.CrudOperations;
-import info.textgrid.middleware.ejb.DHConnectEJB;
+import info.textgrid.middleware.common.TextGridMimetypes;
+import info.textgrid.middleware.model.CrudMessage;
+import info.textgrid.middleware.services.DHConnect;
+import io.smallrye.reactive.messaging.annotations.Blocking;
+import jakarta.inject.Inject;
 
 /**
- *
+ * 
  */
-@MessageDriven(name = "DHDigilibPrescalerMDB", activationConfig = {
-    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/dhcrud"),
-    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
-    @ActivationConfigProperty(propertyName = "messageSelector",
-        propertyValue = "format LIKE 'image/%'")})
-public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
+public class DHPrescaleMessageConsumer extends MessageConsumerAbs {
 
-  @EJB
-  private DHConnectEJB dhconnect;
+  private static final String CLASS_NAME =
+      "{" + DHPrescaleMessageConsumer.class.getSimpleName() + "} ";
 
-  private static final String CLASS_NAME = "{DHDigilibPrescalerMDB} ";
+  @Inject
+  DHConnect dhconnect;
 
-  /*
-   * (non-Javadoc)
-   *
-   * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
+  /**
+   * @param message
+   * @return
    */
-  @Override
-  public void onMessage(Message msg) {
+  @Incoming("dhcrud")
+  @Blocking
+  CompletionStage<Void> onMessage(Message<CrudMessage> message) {
 
-    try {
-      int operation = msg.getIntProperty(OPERATION_KEY);
-      String uri = msg.getStringProperty(uriKey);
-      boolean isPublic = msg.getBooleanProperty(PUBLIC_KEY);
+    CrudMessage msg = fromMessage(message);
+
+    // Select image mimetypes via TextGrid mimetypes from dariah-de-common.
+    if (TextGridMimetypes.IMAGE_SET.contains(msg.getFormat())) {
+
+      int operation = msg.getOperation();
+      String uri = msg.getObjectId().toASCIIString();
+      boolean isPublic = msg.isPublic();
 
       switch (operation) {
         case CrudOperations.CREATE:
@@ -53,7 +52,7 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
           prescale(uri, isPublic);
           break;
         case CrudOperations.UPDATE:
-          LOGGER.info(CLASS_NAME + "UPDATE: Re-prescaling " + uri);
+          LOGGER.info(CLASS_NAME + "UPDATE: Rescaling " + uri);
           prescale(uri, isPublic);
           break;
         case CrudOperations.DELETE:
@@ -61,13 +60,13 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
           removePrescales(uri);
           break;
         default:
-          LOGGER.info(CLASS_NAME + "UNKNOWN OPERATION: " + CrudOperations.getName(operation)
+          LOGGER.warning(CLASS_NAME + "UNKNOWN OPERATION: " + CrudOperations.getName(operation)
               + " on " + uri);
           break;
       }
-    } catch (JMSException e) {
-      LOGGER.log(Level.SEVERE, CLASS_NAME + "Error recieving message from dhcrud", e);
     }
+
+    return message.ack();
   }
 
   // **
@@ -111,11 +110,12 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
 
     // Create temp folder, if not yet existing.
     File tempFolder = new File(TEMP_PATH);
+
     if (!tempFolder.exists()) {
       boolean tempFolderCreated = tempFolder.mkdirs();
       if (tempFolderCreated) {
-        LOGGER.info(CLASS_NAME + "Temp folder not yet existing! Created new folder: "
-            + tempFolder.getAbsolutePath());
+        LOGGER.info(CLASS_NAME +
+            "Temp folder not yet existing! Created new folder: " + tempFolder.getAbsolutePath());
       } else {
         LOGGER.fine(CLASS_NAME + "Temp folder already existing: " + tempFolder.getAbsolutePath());
       }
@@ -126,9 +126,11 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
     // Get prescale pathes.
     FileSystem fs = FileSystems.getDefault();
     List<Path> pathList = getPrescaleProcessingList(fs, prescaleFilename);
+
     // Create cache folders here, if not yet existing.
     for (Path p : pathList) {
       File pFolder = p.toFile().getParentFile();
+
       if (!pFolder.exists()) {
         boolean cacheFolderCreated = pFolder.mkdirs();
         if (cacheFolderCreated) {
@@ -142,6 +144,7 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
 
     // Get image path and create file.
     File tempFile = new File(tempFolder, prescaleFilename);
+
     try {
       // Retrieve image from DH-crud and store image to original path.
       this.dhconnect.getObjectData(theURI, tempFile);
@@ -160,17 +163,17 @@ public class DHDigilibPrescalerMDB extends DHMessageBeanAbs {
 
       LOGGER.info(CLASS_NAME + "Scaling COMPLETE for " + prescaleFilename);
 
-    } catch (NullPointerException | IOException | URISyntaxException e) {
-      LOGGER.log(Level.SEVERE, CLASS_NAME + "Could not store data file from DH-crud to "
-          + tempFile.getAbsolutePath() + "!", e);
+    } catch (IOException e) {
+      LOGGER.severe(CLASS_NAME + "Could not store data file from DH-crud to "
+          + tempFile.getAbsolutePath() + "!");
     } catch (ImageReadException e) {
-      LOGGER.log(Level.WARNING,
-          CLASS_NAME + "Error identifying image properties: " + tempFile.getAbsolutePath(), e);
+      LOGGER.warning(
+          CLASS_NAME + "Error identifying image properties: " + tempFile.getAbsolutePath());
     } finally {
       // Remove original data file from temp.
       boolean deleted = tempFile.delete();
       if (!deleted) {
-        LOGGER.log(Level.WARNING, CLASS_NAME + "Could not delete orig data file from temp: "
+        LOGGER.warning(CLASS_NAME + "Could not delete orig data file from temp: "
             + tempFile.getAbsolutePath() + "!");
       } else {
         LOGGER.info(CLASS_NAME + "Temp file deletion complete: " + tempFile.getAbsolutePath());
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/MessageBeanAbs.java b/src/main/java/info/textgrid/middleware/messagebeans/MessageConsumerAbs.java
similarity index 76%
rename from src/main/java/info/textgrid/middleware/messagebeans/MessageBeanAbs.java
rename to src/main/java/info/textgrid/middleware/messagebeans/MessageConsumerAbs.java
index 8e0d365f20993f428c3e62a2305531f35b9c5925..d8ebe76722ff04fc9206c454702e3430ae6787d4 100644
--- a/src/main/java/info/textgrid/middleware/messagebeans/MessageBeanAbs.java
+++ b/src/main/java/info/textgrid/middleware/messagebeans/MessageConsumerAbs.java
@@ -10,28 +10,29 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import javax.jms.JMSException;
-import javax.jms.Message;
-import javax.jms.MessageListener;
 import org.apache.commons.imaging.ImageInfo;
 import org.apache.commons.imaging.ImageReadException;
 import org.apache.commons.imaging.Imaging;
+import org.eclipse.microprofile.reactive.messaging.Message;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
 import info.textgrid.middleware.common.CachingUtils;
-import info.textgrid.middleware.common.CrudOperations;
+import info.textgrid.middleware.model.CrudMessage;
 
 /**
  *
  */
-public abstract class MessageBeanAbs implements MessageListener {
+public abstract class MessageConsumerAbs {
+
+  private static final String CLASS_NAME = "{" + MessageConsumerAbs.class.getName() + "} ";
 
-  private static final String CLASS_NAME = "{MessageBeanAbs} ";
   protected static final String PRESCALE_PATH = "/var/dhrep/digilib/prescale/";
 
   protected static final int JPEG_QUALITY = 90;
   protected static final int TILESIZE = 512;
   protected static final int MAX_FRACTION = 16;
 
-  protected final static Logger LOGGER = Logger.getLogger(MessageBeanAbs.class.toString());
+  protected final static Logger LOGGER = Logger.getLogger(MessageConsumerAbs.class.toString());
   protected final static String OPERATION_KEY = "operation";
   protected final static String FORMAT_KEY = "format";
   protected final static String PUBLIC_KEY = "public";
@@ -43,34 +44,35 @@ public abstract class MessageBeanAbs implements MessageListener {
   protected final static String JPEG_SUFFIX = ".jpeg";
   protected final static String TIFF_SUFFIX = ".tiff";
 
-  protected static String uriKey;
-  protected static String rootIdKey;
-  protected static String jmsTypeKey;
+  /**
+   * @param msg
+   * @return
+   */
+  CrudMessage fromMessage(Message msg) {
+    return fromString((String) msg.getPayload());
+  }
 
   /**
-   * @param theClassName
-   * @param theMessage
-   * @throws JMSException
+   * @param jsonString
+   * @return
    */
-  protected void logGeneralInfo(String theClassName, Message theMessage) throws JMSException {
-    String message = "[" + jmsTypeKey + " > " + uriKey + "=" + theMessage.getStringProperty(uriKey)
-        + " | " + OPERATION_KEY + "="
-        + CrudOperations.getName(theMessage.getIntProperty(OPERATION_KEY)) + "]";
-    LOGGER.info("{" + theClassName + "} " + RECEIVED + message);
+  CrudMessage fromString(String jsonString) {
+    ObjectMapper mapper = new ObjectMapper();
+    try {
+      return mapper.readValue(jsonString, CrudMessage.class);
+    } catch (JsonProcessingException e) {
+      // TODO Auto-generated catch block
+      e.printStackTrace();
+    }
+    return new CrudMessage();
   }
 
   /**
    * @param theClassName
    * @param theMessage
-   * @throws JMSException
    */
-  protected void logMoreInfo(String theClassName, Message theMessage) throws JMSException {
-    String message = "[" + jmsTypeKey + " > " + uriKey + "=" + theMessage.getStringProperty(uriKey)
-        + " | " + rootIdKey + "=" + theMessage.getStringProperty(rootIdKey) + " | " + OPERATION_KEY
-        + "=" + CrudOperations.getName(theMessage.getIntProperty(OPERATION_KEY)) + " | "
-        + FORMAT_KEY + "=" + theMessage.getStringProperty(FORMAT_KEY) + " | " + PUBLIC_KEY + "="
-        + theMessage.getBooleanProperty(PUBLIC_KEY) + "]";
-    LOGGER.info("{" + theClassName + "} " + RECEIVED + message);
+  protected void logInfo(String theClassName, CrudMessage theMessage) {
+    LOGGER.info("{" + theClassName + "} " + RECEIVED + theMessage);
   }
 
   /**
@@ -276,58 +278,6 @@ public abstract class MessageBeanAbs implements MessageListener {
   // GETTERS AND SETTERS
   // **
 
-  /**
-   * @return
-   */
-  public static String getUriKey() {
-    return uriKey;
-  }
-
-  /**
-   * @param uriKey
-   */
-  public static void setUriKey(String uriKey) {
-    MessageBeanAbs.uriKey = uriKey;
-  }
-
-  /**
-   * @return
-   */
-  public static String getRootIdKey() {
-    return rootIdKey;
-  }
-
-  /**
-   * @param rootIdKey
-   */
-  public static void setRootIdKey(String rootIdKey) {
-    MessageBeanAbs.rootIdKey = rootIdKey;
-  }
-
-  /**
-   * @return
-   */
-  public static String getJmsTypeKey() {
-    return jmsTypeKey;
-  }
-
-  /**
-   * @param jmsTypeKey
-   */
-  public static void setJmsTypeKey(String jmsTypeKey) {
-    MessageBeanAbs.jmsTypeKey = jmsTypeKey;
-  }
-
-  /**
-   * @param theURI
-   * @return
-   */
-  @Deprecated
-  public static String getPrescalePathOnly(String theURI) {
-    String completePath = CachingUtils.getCachingPathFromURI(theURI).trim();
-    return completePath.substring(4, completePath.lastIndexOf("/"));
-  }
-
   /**
    * @param theURI
    * @return
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGAllMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/TGAllMDB.java
deleted file mode 100644
index 95b04257d0cbca345bbdc2e2f5d43cbda9581be8..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/TGAllMDB.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package info.textgrid.middleware.messagebeans;
-
-import javax.ejb.ActivationConfigProperty;
-import javax.ejb.MessageDriven;
-import javax.jms.JMSException;
-import javax.jms.Message;
-
-/**
- *
- */
-@MessageDriven(name = "TGAllMDB", activationConfig = {
-    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/tgcrud"),
-    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-    @ActivationConfigProperty(propertyName = "acknowledgeMode",
-        propertyValue = "Auto-acknowledge")})
-public class TGAllMDB extends TGMessageBeanAbs {
-
-  /*
-   * (non-Javadoc)
-   *
-   * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
-   */
-  public void onMessage(Message msg) {
-    try {
-      logMoreInfo(this.getClass().getSimpleName(), msg);
-    } catch (JMSException e) {
-      throw new RuntimeException(e);
-    }
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGImageMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/TGImageMDB.java
deleted file mode 100644
index df96173b80fafb7ea8b961f0898ccfdc1ec0d5f8..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/TGImageMDB.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// package info.textgrid.middleware.messagebeans;
-//
-// import javax.ejb.ActivationConfigProperty;
-// import javax.ejb.MessageDriven;
-// import javax.jms.JMSException;
-// import javax.jms.Message;
-// import info.textgrid.namespaces.middleware.tgcrud.common.CrudOperations;
-//
-/// **
-// *
-// */
-// @MessageDriven(name = "TGImageMDB", activationConfig = {
-// @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/tgcrud"),
-// @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-// @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
-// @ActivationConfigProperty(propertyName = "messageSelector",
-// propertyValue = "format LIKE 'image/%' AND operation=" + CrudOperations.CREATE)})
-// public class TGImageMDB extends TGMessageBeanAbs {
-//
-// /*
-// * (non-Javadoc)
-// *
-// * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
-// */
-// public void onMessage(Message msg) {
-// try {
-// logGeneralInfo(this.getClass().getSimpleName(), msg);;
-// } catch (JMSException e) {
-// throw new RuntimeException(e);
-// }
-// }
-//
-// }
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGLoggingMessageConsumer.java b/src/main/java/info/textgrid/middleware/messagebeans/TGLoggingMessageConsumer.java
new file mode 100644
index 0000000000000000000000000000000000000000..1cbe6a3acc9e9ef1410e76330f34a9ced184da34
--- /dev/null
+++ b/src/main/java/info/textgrid/middleware/messagebeans/TGLoggingMessageConsumer.java
@@ -0,0 +1,28 @@
+package info.textgrid.middleware.messagebeans;
+
+import java.util.concurrent.CompletionStage;
+import org.eclipse.microprofile.reactive.messaging.Incoming;
+import org.eclipse.microprofile.reactive.messaging.Message;
+import info.textgrid.middleware.model.CrudMessage;
+import io.smallrye.reactive.messaging.annotations.Blocking;
+
+/**
+ *
+ */
+public class TGLoggingMessageConsumer extends TGMessageConsumerAbs {
+
+  /**
+   * @param message
+   * @return
+   */
+  @Incoming("tgcrud")
+  @Blocking
+  CompletionStage<Void> onMessage(Message<CrudMessage> message) {
+
+    CrudMessage msg = fromMessage(message);
+    logInfo(this.getClass().getSimpleName(), msg);
+
+    return message.ack();
+  }
+
+}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGMessageBeanAbs.java b/src/main/java/info/textgrid/middleware/messagebeans/TGMessageBeanAbs.java
deleted file mode 100644
index a0bff57dd6011e522870203d63633cdd3823a474..0000000000000000000000000000000000000000
--- a/src/main/java/info/textgrid/middleware/messagebeans/TGMessageBeanAbs.java
+++ /dev/null
@@ -1,37 +0,0 @@
-package info.textgrid.middleware.messagebeans;
-
-/**
- *
- */
-public abstract class TGMessageBeanAbs extends MessageBeanAbs {
-
-  /**
-   * 
-   */
-  public TGMessageBeanAbs() {
-    MessageBeanAbs.setUriKey("textgridUri");
-    MessageBeanAbs.setRootIdKey("projectID");
-    MessageBeanAbs.setJmsTypeKey("tgcrud-notification");
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see info.textgrid.middleware.messagebeans.MessageBeanAbs#getPrescaleHash(java.lang.String)
-   */
-  protected String getPrescaleHash(String theURI) {
-    // Take the first three chars.
-    return getPrescaleID(theURI).substring(0, 2);
-  }
-
-  /*
-   * (non-Javadoc)
-   * 
-   * @see info.textgrid.middleware.messagebeans.MessageBeanAbs#getPrescaleID(java.lang.String)
-   */
-  protected String getPrescaleID(String theURI) {
-    // Cut "textgrid:".
-    return theURI.substring(9);
-  }
-
-}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGMessageConsumerAbs.java b/src/main/java/info/textgrid/middleware/messagebeans/TGMessageConsumerAbs.java
new file mode 100644
index 0000000000000000000000000000000000000000..5b1791a708dd9b2af21b38fe23b1d5ef74d36026
--- /dev/null
+++ b/src/main/java/info/textgrid/middleware/messagebeans/TGMessageConsumerAbs.java
@@ -0,0 +1,26 @@
+package info.textgrid.middleware.messagebeans;
+
+/**
+ *
+ */
+public abstract class TGMessageConsumerAbs extends MessageConsumerAbs {
+
+  /**
+   * @param theURI
+   * @return
+   */
+  protected String getPrescaleHash(String theURI) {
+    // Take the first three chars.
+    return getPrescaleID(theURI).substring(0, 2);
+  }
+
+  /**
+   * @param theURI
+   * @return
+   */
+  protected String getPrescaleID(String theURI) {
+    // Cut "textgrid:".
+    return theURI.substring(9);
+  }
+
+}
diff --git a/src/main/java/info/textgrid/middleware/messagebeans/TGDigilibPrescalerMDB.java b/src/main/java/info/textgrid/middleware/messagebeans/TGPrescaleMessageConsumer.java
similarity index 63%
rename from src/main/java/info/textgrid/middleware/messagebeans/TGDigilibPrescalerMDB.java
rename to src/main/java/info/textgrid/middleware/messagebeans/TGPrescaleMessageConsumer.java
index 8f96d1b4d848d6f8e868dbcde772b01811b89457..bf7097d864b10bb5169c2d0b18b4b09af3489b0c 100644
--- a/src/main/java/info/textgrid/middleware/messagebeans/TGDigilibPrescalerMDB.java
+++ b/src/main/java/info/textgrid/middleware/messagebeans/TGPrescaleMessageConsumer.java
@@ -7,44 +7,42 @@ import java.nio.file.FileSystems;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.attribute.FileTime;
-import java.util.logging.Level;
-import javax.ejb.ActivationConfigProperty;
-import javax.ejb.MessageDriven;
-import javax.jms.JMSException;
-import javax.jms.Message;
+import java.util.concurrent.CompletionStage;
 import org.apache.commons.imaging.ImageReadException;
+import org.eclipse.microprofile.reactive.messaging.Incoming;
+import org.eclipse.microprofile.reactive.messaging.Message;
 import info.textgrid.middleware.common.CrudOperations;
 import info.textgrid.middleware.common.JPairtree;
+import info.textgrid.middleware.common.TextGridMimetypes;
+import info.textgrid.middleware.model.CrudMessage;
+import io.smallrye.reactive.messaging.annotations.Blocking;
 
 /**
- *
+ * 
  */
-@MessageDriven(name = "TGDigilibPrescalerMDB", activationConfig = {
-    @ActivationConfigProperty(propertyName = "destinationLookup", propertyValue = "topic/tgcrud"),
-    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Topic"),
-    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
-    @ActivationConfigProperty(propertyName = "messageSelector",
-        propertyValue = "format LIKE 'image/%'")})
-public class TGDigilibPrescalerMDB extends TGMessageBeanAbs {
+public class TGPrescaleMessageConsumer extends TGMessageConsumerAbs {
 
+  private static final String CLASS_NAME =
+      "{" + TGPrescaleMessageConsumer.class.getSimpleName() + "} ";
   private static final String PUBLIC_STORAGE_PATH = "/data/public/productive/";
   private static final String NONPUBLIC_STORAGE_PATH = "/data/nonpublic/productive/";
-  private static final String PRESCALE_PATH = "/var/dhrep/digilib/prescale/";
 
-  private static final String CLASS_NAME = "{TGDigilibPrescalerMDB} ";
-
-  /*
-   * (non-Javadoc)
-   *
-   * @see javax.jms.MessageListener#onMessage(javax.jms.Message)
+  /**
+   * @param message
+   * @return
    */
-  @Override
-  public void onMessage(Message msg) {
+  @Incoming("tgcrud")
+  @Blocking
+  CompletionStage<Void> onMessage(Message<CrudMessage> message) {
 
-    try {
-      int operation = msg.getIntProperty(OPERATION_KEY);
-      String uri = msg.getStringProperty(uriKey);
-      boolean isPublic = msg.getBooleanProperty(PUBLIC_KEY);
+    CrudMessage msg = fromMessage(message);
+
+    // Select image mimetypes via TextGrid mimetypes from dariah-de-common.
+    if (TextGridMimetypes.IMAGE_SET.contains(msg.getFormat())) {
+
+      int operation = msg.getOperation();
+      String uri = msg.getObjectId().toASCIIString();
+      boolean isPublic = msg.isPublic();
 
       switch (operation) {
         case CrudOperations.CREATE:
@@ -60,18 +58,17 @@ public class TGDigilibPrescalerMDB extends TGMessageBeanAbs {
           removePrescales(uri);
           break;
         case CrudOperations.UPDATEMETADATA:
+          LOGGER.fine(CLASS_NAME + "UPDATEMETADATA " + uri);
           touchPrescales(uri);
           break;
         default:
-          LOGGER.info(CLASS_NAME + "UNKNOWN OPERATION: " + CrudOperations.getName(operation)
+          LOGGER.warning(CLASS_NAME + "UNKNOWN OPERATION: " + CrudOperations.getName(operation)
               + " on " + uri);
           break;
       }
-
-    } catch (JMSException e) {
-      LOGGER.log(Level.SEVERE, CLASS_NAME + "Error recieving message from tgcrud", e);
     }
 
+    return message.ack();
   }
 
   /**
@@ -79,25 +76,22 @@ public class TGDigilibPrescalerMDB extends TGMessageBeanAbs {
    *
    * @param textgridUri
    */
-  private void touchPrescales(String textgridUri) {
+  private static void touchPrescales(String textgridUri) {
 
     String id = textgridUri.substring(9);
     FileTime modificationTime = FileTime.fromMillis(System.currentTimeMillis());
     FileSystem fs = FileSystems.getDefault();
 
     for (int i = 1; i <= MAX_FRACTION; i = i * 2) {
-      Path scaleJpegFile =
-          fs.getPath(PRESCALE_PATH + "jpeg-sf" + i + "/" + id + ".jpeg");
-      Path tileTiffFile =
-          fs.getPath(PRESCALE_PATH + "tile-sf" + i + "/" + id + ".tiff");
+      Path scaleJpegFile = fs.getPath(PRESCALE_PATH + "jpeg-sf" + i + "/" + id + ".jpeg");
+      Path tileTiffFile = fs.getPath(PRESCALE_PATH + "tile-sf" + i + "/" + id + ".tiff");
       try {
         Files.setLastModifiedTime(scaleJpegFile, modificationTime);
         Files.setLastModifiedTime(tileTiffFile, modificationTime);
       } catch (IOException e) {
-        LOGGER.log(Level.SEVERE, CLASS_NAME + "Error touching " + textgridUri, e);
+        LOGGER.severe(CLASS_NAME + "Error touching " + textgridUri);
       }
     }
-
   }
 
   /**
@@ -110,15 +104,13 @@ public class TGDigilibPrescalerMDB extends TGMessageBeanAbs {
     FileSystem fs = FileSystems.getDefault();
 
     for (int i = 1; i <= MAX_FRACTION; i = i * 2) {
-      Path scaleJpegFile =
-          fs.getPath(PRESCALE_PATH + "jpeg-sf" + i + "/" + id + ".jpeg");
-      Path tileTiffFile =
-          fs.getPath(PRESCALE_PATH + "tile-sf" + i + "/" + id + ".tiff");
+      Path scaleJpegFile = fs.getPath(PRESCALE_PATH + "jpeg-sf" + i + "/" + id + ".jpeg");
+      Path tileTiffFile = fs.getPath(PRESCALE_PATH + "tile-sf" + i + "/" + id + ".tiff");
       try {
         Files.delete(scaleJpegFile);
         Files.delete(tileTiffFile);
       } catch (IOException e) {
-        LOGGER.log(Level.SEVERE, CLASS_NAME + "Error deleting " + textgridUri, e);
+        LOGGER.severe(CLASS_NAME + "Error deleting " + textgridUri);
       }
     }
   }
@@ -168,15 +160,14 @@ public class TGDigilibPrescalerMDB extends TGMessageBeanAbs {
       fractionalScale(id, origFile);
 
     } catch (IOException e) {
-      LOGGER.log(Level.SEVERE, CLASS_NAME + "Error prescaling image: " + textgridUri, e);
+      LOGGER.severe(CLASS_NAME + "Error prescaling image: " + textgridUri);
     } catch (ImageReadException e) {
-      LOGGER.log(Level.WARNING, CLASS_NAME + "Error identifying image properties: " + textgridUri,
-          e);
+      LOGGER.warning(CLASS_NAME + "Error identifying image properties: " + textgridUri);
     } finally {
       // Remove link to original data file from temp.
       boolean deleted = tempLinkFile.delete();
       if (!deleted) {
-        LOGGER.log(Level.WARNING, CLASS_NAME + "Could not delete link to orig data file from temp: "
+        LOGGER.warning(CLASS_NAME + "Could not delete link to orig data file from temp: "
             + tempLinkFile.getAbsolutePath() + "!");
       } else {
         LOGGER.info(
diff --git a/src/main/java/info/textgrid/middleware/model/CrudMessage.java b/src/main/java/info/textgrid/middleware/model/CrudMessage.java
new file mode 100644
index 0000000000000000000000000000000000000000..3b3f1ae46aa108a36dd074f55d830d3167cf41fb
--- /dev/null
+++ b/src/main/java/info/textgrid/middleware/model/CrudMessage.java
@@ -0,0 +1,114 @@
+package info.textgrid.middleware.model;
+
+import java.net.URI;
+import io.quarkus.runtime.annotations.RegisterForReflection;
+
+/**
+ *
+ */
+@RegisterForReflection
+public class CrudMessage {
+
+  // TODO Put into common for common crud and message-beans usage?
+
+  public URI objectId; // tguri for tg, pid for dh
+  public int operation; // create, update, delete
+  public String format; // mimetype
+  public String rootId; // collectionId for dh, projectId for tg
+  public boolean isPublic; // public or not public
+
+  /**
+   * Default constructor required for Jackson serializer
+   */
+  public CrudMessage() {}
+
+  /**
+   *
+   */
+  @Override
+  public String toString() {
+    return "CrudMessage{objectId='%s', operation='%d', format='%s', rootId='%s', public='%b'}"
+        .formatted(this.objectId, this.operation, this.format, this.rootId, this.isPublic);
+  }
+
+  /**
+   * @return
+   */
+  public URI getObjectId() {
+    return this.objectId;
+  }
+
+  /**
+   * @param objectId
+   * @return
+   */
+  public CrudMessage setObjectId(URI objectId) {
+    this.objectId = objectId;
+    return this;
+  }
+
+  /**
+   * @return
+   */
+  public int getOperation() {
+    return this.operation;
+  }
+
+  /**
+   * @param operation
+   * @return
+   */
+  public CrudMessage setOperation(int operation) {
+    this.operation = operation;
+    return this;
+  }
+
+  /**
+   * @return
+   */
+  public String getFormat() {
+    return this.format;
+  }
+
+  /**
+   * @param format
+   * @return
+   */
+  public CrudMessage setFormat(String format) {
+    this.format = format;
+    return this;
+  }
+
+  /**
+   * @return
+   */
+  public String getRootId() {
+    return this.rootId;
+  }
+
+  /**
+   * @param rootId
+   * @return
+   */
+  public CrudMessage setRootId(String rootId) {
+    this.rootId = rootId;
+    return this;
+  }
+
+  /**
+   * @return
+   */
+  public boolean isPublic() {
+    return this.isPublic;
+  }
+
+  /**
+   * @param isPublic
+   * @return
+   */
+  public CrudMessage setPublic(boolean isPublic) {
+    this.isPublic = isPublic;
+    return this;
+  }
+
+}
diff --git a/src/main/java/info/textgrid/middleware/services/DHConnect.java b/src/main/java/info/textgrid/middleware/services/DHConnect.java
new file mode 100644
index 0000000000000000000000000000000000000000..59a083fdfbc075a189c667422817f731ea43a1c0
--- /dev/null
+++ b/src/main/java/info/textgrid/middleware/services/DHConnect.java
@@ -0,0 +1,87 @@
+package info.textgrid.middleware.services;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Properties;
+import java.util.logging.Logger;
+import org.apache.commons.io.FileUtils;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
+
+/**
+ *
+ */
+@ApplicationScoped
+public class DHConnect {
+
+  private static final Logger LOGGER = Logger.getLogger(DHConnect.class.getName());
+  private static final String CLASS_NAME = "{" + DHConnect.class.getSimpleName() + "} ";
+
+  private String propertiesLocation;
+  private Properties properties;
+  private URL crudUrl;
+  private Client dhclient;
+
+  /**
+   * 
+   */
+  public DHConnect() {
+
+    this.propertiesLocation = "/etc/dhrep/messagebeans/dhmb.properties";
+
+    this.properties = new Properties();
+    BufferedInputStream stream;
+
+    try {
+      stream = new BufferedInputStream(new FileInputStream(this.propertiesLocation));
+      this.properties.load(stream);
+      stream.close();
+
+      this.crudUrl = new URL(this.properties.getProperty("crudUrl"));
+
+    } catch (FileNotFoundException e) {
+      LOGGER.severe(CLASS_NAME + "Properties file not found!");
+    } catch (IOException e) {
+      LOGGER.severe(CLASS_NAME + "Unable to get CRUD URL from properties file!");
+    }
+
+    if (this.dhclient == null) {
+      this.dhclient = ClientBuilder.newClient().property("thread.safe.client", "true");
+    }
+
+    LOGGER.info(CLASS_NAME + "dhclient: " + this.dhclient.getConfiguration().getProperties());
+  }
+
+  /**
+   * @param theUri
+   * @param theTempFile
+   * @throws IOException
+   */
+  public void getObjectData(String theUri, File theTempFile) {
+
+    WebTarget target = this.dhclient.target(this.crudUrl.toString()).path(theUri + "/data");
+
+    LOGGER.info(CLASS_NAME + "Reading DH-crud data file from: " + target.getUri());
+
+    try (Response response = target.request().get()) {
+      FileUtils.copyInputStreamToFile(response.readEntity(InputStream.class), theTempFile);
+
+      LOGGER.info(CLASS_NAME + "Copied data to temp file: " + theTempFile.getAbsolutePath());
+
+      response.close();
+
+    } catch (IOException e) {
+
+      LOGGER.severe(CLASS_NAME + "ERROR: " + e.getMessage());
+    }
+  }
+
+}
diff --git a/src/main/resources/application.properties b/src/main/resources/application.properties
new file mode 100644
index 0000000000000000000000000000000000000000..b5d0e57a7cb423ba7ad2adf96a4a4311cfb674a7
--- /dev/null
+++ b/src/main/resources/application.properties
@@ -0,0 +1,27 @@
+###
+# amqp related
+###
+
+# Set the AMQP address for the `tgcrud` and 'tgcrud' channels, as it's not the
+# channel name
+# Set to "dhcrud-events" for dhcrud messages, and to "tgcrud-events" for tgcrud messages!
+# See in docker-compose file env param: MP_MESSAGING_INCOMING_CRUD_ADDRESS
+mp.messaging.incoming.tgcrud.address=tgcrud-events
+mp.messaging.incoming.dhcrud.address=dhcrud-events
+
+# TooManyDownstreamCandidatesException:
+#   'IncomingConnector{channel:'crud', attribute:'mp.messaging.incoming.crud'}'
+# supports a single downstream consumer, but found 4:
+#  [SubscriberMethod{method:'onMessage', incoming:'crud'},
+#   SubscriberMethod{method:'onMessage', incoming:'crud'},
+#   SubscriberMethod{method:'onMessage', incoming:'crud'},
+#   SubscriberMethod{method:'onMessage', incoming:'crud'}].
+# You may want to enable broadcast using 'mp.messaging.incoming.crud.broadcast=true'
+#   to allow multiple downstreams.
+mp.messaging.incoming.tgcrud.broadcast=true
+mp.messaging.incoming.dhcrud.broadcast=true
+
+# Enable json metrics
+quarkus.micrometer.export.json.enabled=true
+quarkus.micrometer.export.json.path=metrics/json
+quarkus.micrometer.export.prometheus.path=metrics/prometheus
diff --git a/src/main/resources/enzyklops-adapter.xsl b/src/main/resources/enzyklops-adapter.xsl
deleted file mode 100644
index b3a028cf73fbbc5ee1554a30ca3c1e2e82fc628b..0000000000000000000000000000000000000000
--- a/src/main/resources/enzyklops-adapter.xsl
+++ /dev/null
@@ -1,43 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
-	xmlns:xs="http://www.w3.org/2001/XMLSchema"
-	xmlns:fn="http://textgrid.info/namespace/xslt/functions"
-	xpath-default-namespace="http://www.tei-c.org/ns/1.0"
-	exclude-result-prefixes="xs"	
-	version="2.0">
-	
-<xsl:output media-type="text/json" method="text" encoding="UTF-8"/>
-
-<xsl:template match="/">
-{"fulltext_structured" : 
-        [ <xsl:apply-templates/> ]
-}
-</xsl:template>
-	
-<xsl:template match="text()">
-	<xsl:if test="normalize-space(.) != ''">
-		<xsl:message>Da ist text wo er nicht sein soll: »<xsl:copy-of select="."/>«</xsl:message>
-	</xsl:if>
-</xsl:template> 
-
-<xsl:template match="*[not(descendant-or-self::div[@type='entry'][head])]">
-	{ "fulltext": "<xsl:value-of select="fn:escape-json-string(.)"/>" }
-        <xsl:if test="following::div[@type='entry'][head] | following::*[not(descendant-or-self::div[@type='entry'][head])]">,</xsl:if>
-</xsl:template>
-	
-<xsl:template match="div[@type='entry'][head]">
-      {
-        "title": "<xsl:value-of select="fn:escape-json-string(head[1])"/>",
-		"id": "<xsl:value-of select="@xml:id"/>",
-		"fulltext": "<xsl:value-of select="fn:escape-json-string(.)"/>" 
-      }
-      
-      <xsl:if test="following::div[@type='entry'][head] | following::*[not(descendant-or-self::div[@type='entry'][head])]">,</xsl:if>
-</xsl:template>
-		
-<xsl:function name="fn:escape-json-string" as="xs:string">
-	<xsl:param name="input" as="xs:string"/>
-	<xsl:variable name="stage1" select='replace($input, "\\", "\\\\")'/>  <!-- \ → \\ -->
-	<xsl:value-of select="normalize-space(replace($stage1, '&quot;', '\\&quot;'))"/>       <!-- " → \" -->
-</xsl:function>
-</xsl:stylesheet>
diff --git a/src/main/webapp/WEB-INF/beans.xml b/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index 3925cb3f0158cc52cedc0be588b0f4e4c3ac6254..0000000000000000000000000000000000000000
--- a/src/main/webapp/WEB-INF/beans.xml
+++ /dev/null
@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!-- JBoss, Home of Professional Open Source Copyright 2013, Red Hat, Inc. 
-	and/or its affiliates, and individual contributors by the @authors tag. See 
-	the copyright.txt in the distribution for a full listing of individual contributors. 
-	Licensed under the Apache License, Version 2.0 (the "License"); you may not 
-	use this file except in compliance with the License. You may obtain a copy 
-	of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required 
-	by applicable law or agreed to in writing, software distributed under the 
-	License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 
-	OF ANY KIND, either express or implied. See the License for the specific 
-	language governing permissions and limitations under the License. -->
-<!-- This file can be an empty text file (0 bytes) -->
-<!-- We're declaring the schema to save you time if you do have to configure 
-	this in the future -->
-<beans xmlns="http://xmlns.jcp.org/xml/ns/javaee"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/beans_1_1.xsd"
-	bean-discovery-mode="annotated">
-</beans>
diff --git a/src/test/java/info/textgrid/middleware/messagebeans/TestMessageBeanAbs.java b/src/test/java/info/textgrid/middleware/messagebeans/TestMessageBeanAbs.java
index 0ebe9d44b735298dbc56411974f3b4fcb2dcbabb..86c1b29092297cb54c77d3448f97cccaf40f7213 100644
--- a/src/test/java/info/textgrid/middleware/messagebeans/TestMessageBeanAbs.java
+++ b/src/test/java/info/textgrid/middleware/messagebeans/TestMessageBeanAbs.java
@@ -1,17 +1,24 @@
 package info.textgrid.middleware.messagebeans;
 
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
 import java.nio.file.FileSystem;
 import java.nio.file.FileSystems;
 import java.nio.file.Path;
 import java.util.ArrayList;
 import java.util.List;
-import org.junit.Test;
-import junit.framework.TestCase;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+import jakarta.ws.rs.client.Client;
+import jakarta.ws.rs.client.ClientBuilder;
+import jakarta.ws.rs.client.WebTarget;
+import jakarta.ws.rs.core.Response;
 
 /**
  *
  */
-public class TestMessageBeanAbs extends TestCase {
+public class TestMessageBeanAbs {
 
   /**
    * 
@@ -20,21 +27,12 @@ public class TestMessageBeanAbs extends TestCase {
   public void testGetCachingPathFromDariahURI() {
 
     String uri = "hdl:21.T11991/0000-0013-281B-1";
-    String expectedPath = "21.T11991-0000-0013";
     String expectedFilename = "21.T11991-0000-0013-281B-1";
 
-    // Test path.
-    String prescalePath = DHDigilibPrescalerMDB.getPrescalePathOnly(uri);
-    if (!prescalePath.equals(expectedPath)) {
-      System.out.println(prescalePath + " != " + expectedPath);
-      assertFalse(true);
-    }
-
     // Test filename.
-    String filename = DHDigilibPrescalerMDB.getPrescaleFilenameOnly(uri);
+    String filename = MessageConsumerAbs.getPrescaleFilenameOnly(uri);
     if (!filename.equals(expectedFilename)) {
       System.out.println(filename + " != " + expectedFilename);
-      assertFalse(true);
     }
   }
 
@@ -52,29 +50,29 @@ public class TestMessageBeanAbs extends TestCase {
     System.out.println(id);
 
     List<Path> expectedPathList = new ArrayList<Path>();
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "jpeg-sf1/21.T11991-0000-0013-281B-1.jpeg"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "jpeg-sf2/21.T11991-0000-0013-281B-1.jpeg"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "jpeg-sf4/21.T11991-0000-0013-281B-1.jpeg"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "jpeg-sf8/21.T11991-0000-0013-281B-1.jpeg"));
     expectedPathList.add(
-        fs.getPath(MessageBeanAbs.PRESCALE_PATH + "jpeg-sf16/21.T11991-0000-0013-281B-1.jpeg"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "tile-sf1/21.T11991-0000-0013-281B-1.tiff"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "tile-sf2/21.T11991-0000-0013-281B-1.tiff"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "tile-sf4/21.T11991-0000-0013-281B-1.tiff"));
-    expectedPathList
-        .add(fs.getPath(MessageBeanAbs.PRESCALE_PATH + "tile-sf8/21.T11991-0000-0013-281B-1.tiff"));
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "jpeg-sf1/21.T11991-0000-0013-281B-1.jpeg"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "jpeg-sf2/21.T11991-0000-0013-281B-1.jpeg"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "jpeg-sf4/21.T11991-0000-0013-281B-1.jpeg"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "jpeg-sf8/21.T11991-0000-0013-281B-1.jpeg"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "jpeg-sf16/21.T11991-0000-0013-281B-1.jpeg"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "tile-sf1/21.T11991-0000-0013-281B-1.tiff"));
     expectedPathList.add(
-        fs.getPath(MessageBeanAbs.PRESCALE_PATH + "tile-sf16/21.T11991-0000-0013-281B-1.tiff"));
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "tile-sf2/21.T11991-0000-0013-281B-1.tiff"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "tile-sf4/21.T11991-0000-0013-281B-1.tiff"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "tile-sf8/21.T11991-0000-0013-281B-1.tiff"));
+    expectedPathList.add(
+        fs.getPath(MessageConsumerAbs.PRESCALE_PATH + "tile-sf16/21.T11991-0000-0013-281B-1.tiff"));
 
-    String prescaleFilename = MessageBeanAbs.getPrescaleFilenameOnly(uri);
-    List<Path> pathList = MessageBeanAbs.getPrescaleProcessingList(fs, prescaleFilename);
+    String prescaleFilename = MessageConsumerAbs.getPrescaleFilenameOnly(uri);
+    List<Path> pathList = MessageConsumerAbs.getPrescaleProcessingList(fs, prescaleFilename);
 
     // We need to test, if all list elements are existing in each list, the order of elements is not
     // important.
@@ -85,4 +83,35 @@ public class TestMessageBeanAbs extends TestCase {
     }
   }
 
+  /**
+   * Testing online: dhcrud read access.
+   * 
+   * @throws IOException
+   */
+  // @Test
+  public void testGetFromDHCrudOnline() throws IOException {
+
+    String host = "https://trep.de.dariah.eu/1.0/dhcrud/";
+    String path = "hdl:21.T11991/0000-001D-8BF4-1/data";
+    File tempFile = File.createTempFile("kakki-", "-fakki");
+
+    Client client = ClientBuilder.newClient().property("thread.safe.client", "true");
+    WebTarget target = client.target(host).path(path);
+
+    try (Response response = target.request().get()) {
+
+      int status = response.getStatus();
+      String reasonPhrase = response.getStatusInfo().getReasonPhrase();
+
+      System.out.println(status + " " + reasonPhrase);
+
+      FileUtils.copyInputStreamToFile(response.readEntity(InputStream.class), tempFile);
+
+      response.close();
+
+    }
+
+    System.out.println(tempFile.getCanonicalPath() + "  -->  " + tempFile.length());
+  }
+
 }