diff --git a/auditlog/.gitignore b/auditlog/.gitignore
new file mode 100644
index 0000000000..7701859592
--- /dev/null
+++ b/auditlog/.gitignore
@@ -0,0 +1,3 @@
+target
+.quarkus
+connector-config
\ No newline at end of file
diff --git a/auditlog/README.md b/auditlog/README.md
index e83f4b7560..3ddecfe55a 100755
--- a/auditlog/README.md
+++ b/auditlog/README.md
@@ -5,37 +5,37 @@ It accompanies the blog post [Building Audit Logs with Change Data Capture and S
There are two applications (based on [Quarkus](https://quarkus.io/)):
-* _vegetables-service_: a simple REST service for inserting and updating vegetable data into a Postgres database;
-as part of its processing, it will not only update its actual "business table" `vegetable`,
-but also insert some auditing metadata into a dedicated metadata table `transaction_context_data`:
-the user (as obtained from the passed JWT token), the client's date (as passed via the HTTP 1.1 `Date` header)
-and a use case identifier (as specified in an annotation on the REST API methods).
-* _log-enricher_: a Kafka Streams application,
-which joins the CDC topic holding the `vegetable` change events (`dbserver1.inventory.vegetable`) with the corresponding metadata in the `dbserver1.inventory.transaction_context_data` topic sourced from the `transaction_context_data` table;
-this table is keyed by transaction id, allowing for joining the vegetable `KStream` with the metadata `KTable`.
-The enriched vegetable change events are written to the `dbserver1.inventory.vegetable.enriched` topic.
+- _vegetables-service_: a simple REST service for inserting and updating vegetable data into a Postgres database;
+ as part of its processing, it will not only update its actual "business table" `vegetable`,
+ but also insert some auditing metadata into a dedicated metadata table `transaction_context_data`:
+ the user (as obtained from the passed JWT token), the client's date (as passed via the HTTP 1.1 `Date` header)
+ and a use case identifier (as specified in an annotation on the REST API methods).
+- _log-enricher_: a Kafka Streams application,
+ which joins the CDC topic holding the `vegetable` change events (`dbserver1.inventory.vegetable`) with the corresponding metadata in the `dbserver1.inventory.transaction_context_data` topic sourced from the `transaction_context_data` table;
+ this table is keyed by transaction id, allowing for joining the vegetable `KStream` with the metadata `KTable`.
+ The enriched vegetable change events are written to the `dbserver1.inventory.vegetable.enriched` topic.
## Building the Demo
```console
-$ mvn clean package
+mvn clean package
```
```console
-$ export DEBEZIUM_VERSION=1.8
-$ docker-compose up --build
+export DEBEZIUM_VERSION=3.4
+docker-compose up --build
```
## Deploy the Debezium Postgres Connector
```console
-$ http PUT http://localhost:8083/connectors/inventory-connector/config < register-postgres.json
+http PUT http://localhost:8083/connectors/inventory-connector/config < register-postgres.json
```
## Modifying Some Data and Observing the Audit Log
```console
-$ http POST http://localhost:8080/vegetables 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJib2IiLCJ1cG4iOiJmYXJtZXJib2IiLCJhdXRoX3RpbWUiOjE1NjY0NTgxMTMsImlzcyI6ImZhcm1zaG9wIiwiZ3JvdXBzIjpbImZhcm1lcnMiLCJjdXN0b21lcnMiXSwiZXhwIjo0MTAyNDQ0Nzk5LCJpYXQiOjE1NjY0NTgxMTMsImp0aSI6IjQyIn0.CscbJN8amqKryYvnVO1184J8F67HN2iTEjVN2VOPodcnoeOd7_iQVKUjC3h-ye5apkJjvAsQKrjzlrGCHRfl-n6jC9F7IkOtjoWnJ4wQ9BBo1SAtPw_Czt1I_Ujm-Kb1p5-BWACCBCVVFgYZTWP_laz5JZS7dIvs6VqoNnw7A4VpA6iPfTVfYlNY3u86-k1FvEg_hW-N9Y9RuihMsPuTdpHK5xdjCrJiD0VJ7-0eRQ8RXpycHuHN4xfmV8MqXBYjYSYDOhbnYbdQVbf0YJoFFqfb75my5olN-97ITsi2MS62W_y-RNT0qZrbytqINA3fF3VQsSY6VcaqRAeygrKm_Q' 'Date:Thu, 22 Aug 2019 08:12:31 GMT' name=Tomatoe description=Yummy!
+http POST http://localhost:8080/vegetables 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJib2IiLCJ1cG4iOiJmYXJtZXJib2IiLCJhdXRoX3RpbWUiOjE1NjY0NTgxMTMsImlzcyI6ImZhcm1zaG9wIiwiZ3JvdXBzIjpbImZhcm1lcnMiLCJjdXN0b21lcnMiXSwiZXhwIjo0MTAyNDQ0Nzk5LCJpYXQiOjE1NjY0NTgxMTMsImp0aSI6IjQyIn0.CscbJN8amqKryYvnVO1184J8F67HN2iTEjVN2VOPodcnoeOd7_iQVKUjC3h-ye5apkJjvAsQKrjzlrGCHRfl-n6jC9F7IkOtjoWnJ4wQ9BBo1SAtPw_Czt1I_Ujm-Kb1p5-BWACCBCVVFgYZTWP_laz5JZS7dIvs6VqoNnw7A4VpA6iPfTVfYlNY3u86-k1FvEg_hW-N9Y9RuihMsPuTdpHK5xdjCrJiD0VJ7-0eRQ8RXpycHuHN4xfmV8MqXBYjYSYDOhbnYbdQVbf0YJoFFqfb75my5olN-97ITsi2MS62W_y-RNT0qZrbytqINA3fF3VQsSY6VcaqRAeygrKm_Q' 'Date:Thu, 22 Aug 2019 08:12:31 GMT' name=Tomatoe description=Yummy!
```
This uses a pre-generated JWT token (with expiration date set to 2099-12-31 and user set to "farmerbob").
@@ -44,13 +44,13 @@ To regenerate the token with different data, use the [Jwtenizr](https://github.c
You can also update an existing vegetable record (this token is for "farmermargaret"):
```console
-$ http PUT http://localhost:8080/vegetables/10 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJtYXJnYXJldCIsInVwbiI6ImZhcm1lcm1hcmdhcmV0IiwiYXV0aF90aW1lIjoxNTY5ODM1Mzk5LCJpc3MiOiJmYXJtc2hvcCIsImdyb3VwcyI6WyJmYXJtZXJzIiwiY3VzdG9tZXJzIl0sImV4cCI6NDEwMjQ0NDc5OSwiaWF0IjoxNTY5ODM1Mzk5LCJqdGkiOiI0MiJ9.DTEUA3p-xyK5nveoJIVhjfKNFdVszYIb55Qj4Xrm70DDbAXuOU2FMkffuUAUm2s7ACkp2KEmg6brRwSjvA-zhW61kDR9ZgEb9NWeDjr6Eue08xcSODKt7SGV-M7h3yhuDIhU7uaZrxRUAQTWqm1vxd2rmN_QH0frhKMUNFFsLIOGLG0zHcLosRcwZ4tAKXSSB9VE0fth6srIQCUebDkF7ucA_WSYjPRvahCBd8JvnV4VUGQxZW8zcRhTEwcaLq20ODO-dr85xgWI2Yr_1A7PDuDL4oUjCb90YyhtzaIzs2vQMjcxJ6TWmTcqJpgCfkjE-TeVwjaafcNJu0fBmcP8jA' 'Date:Thu, 22 Aug 2019 08:12:31 GMT' name=Tomatoe description=Tasty!
+http PUT http://localhost:8080/vegetables/10 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJtYXJnYXJldCIsInVwbiI6ImZhcm1lcm1hcmdhcmV0IiwiYXV0aF90aW1lIjoxNTY5ODM1Mzk5LCJpc3MiOiJmYXJtc2hvcCIsImdyb3VwcyI6WyJmYXJtZXJzIiwiY3VzdG9tZXJzIl0sImV4cCI6NDEwMjQ0NDc5OSwiaWF0IjoxNTY5ODM1Mzk5LCJqdGkiOiI0MiJ9.DTEUA3p-xyK5nveoJIVhjfKNFdVszYIb55Qj4Xrm70DDbAXuOU2FMkffuUAUm2s7ACkp2KEmg6brRwSjvA-zhW61kDR9ZgEb9NWeDjr6Eue08xcSODKt7SGV-M7h3yhuDIhU7uaZrxRUAQTWqm1vxd2rmN_QH0frhKMUNFFsLIOGLG0zHcLosRcwZ4tAKXSSB9VE0fth6srIQCUebDkF7ucA_WSYjPRvahCBd8JvnV4VUGQxZW8zcRhTEwcaLq20ODO-dr85xgWI2Yr_1A7PDuDL4oUjCb90YyhtzaIzs2vQMjcxJ6TWmTcqJpgCfkjE-TeVwjaafcNJu0fBmcP8jA' 'Date:Thu, 22 Aug 2019 08:12:31 GMT' name=Tomatoe description=Tasty!
```
Or delete a record (again using the "farmerbob" token):
```console
-$ http DELETE http://localhost:8080/vegetables/10 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJib2IiLCJ1cG4iOiJmYXJtZXJib2IiLCJhdXRoX3RpbWUiOjE1NjY0NTgxMTMsImlzcyI6ImZhcm1zaG9wIiwiZ3JvdXBzIjpbImZhcm1lcnMiLCJjdXN0b21lcnMiXSwiZXhwIjo0MTAyNDQ0Nzk5LCJpYXQiOjE1NjY0NTgxMTMsImp0aSI6IjQyIn0.CscbJN8amqKryYvnVO1184J8F67HN2iTEjVN2VOPodcnoeOd7_iQVKUjC3h-ye5apkJjvAsQKrjzlrGCHRfl-n6jC9F7IkOtjoWnJ4wQ9BBo1SAtPw_Czt1I_Ujm-Kb1p5-BWACCBCVVFgYZTWP_laz5JZS7dIvs6VqoNnw7A4VpA6iPfTVfYlNY3u86-k1FvEg_hW-N9Y9RuihMsPuTdpHK5xdjCrJiD0VJ7-0eRQ8RXpycHuHN4xfmV8MqXBYjYSYDOhbnYbdQVbf0YJoFFqfb75my5olN-97ITsi2MS62W_y-RNT0qZrbytqINA3fF3VQsSY6VcaqRAeygrKm_Q' 'Date:Thu, 22 Aug 2019 08:12:31 GMT'
+http DELETE http://localhost:8080/vegetables/10 'Authorization:Bearer eyJraWQiOiJqd3Qua2V5IiwidHlwIjoiSldUIiwiYWxnIjoiUlMyNTYifQ.eyJzdWIiOiJmYXJtZXJib2IiLCJ1cG4iOiJmYXJtZXJib2IiLCJhdXRoX3RpbWUiOjE1NjY0NTgxMTMsImlzcyI6ImZhcm1zaG9wIiwiZ3JvdXBzIjpbImZhcm1lcnMiLCJjdXN0b21lcnMiXSwiZXhwIjo0MTAyNDQ0Nzk5LCJpYXQiOjE1NjY0NTgxMTMsImp0aSI6IjQyIn0.CscbJN8amqKryYvnVO1184J8F67HN2iTEjVN2VOPodcnoeOd7_iQVKUjC3h-ye5apkJjvAsQKrjzlrGCHRfl-n6jC9F7IkOtjoWnJ4wQ9BBo1SAtPw_Czt1I_Ujm-Kb1p5-BWACCBCVVFgYZTWP_laz5JZS7dIvs6VqoNnw7A4VpA6iPfTVfYlNY3u86-k1FvEg_hW-N9Y9RuihMsPuTdpHK5xdjCrJiD0VJ7-0eRQ8RXpycHuHN4xfmV8MqXBYjYSYDOhbnYbdQVbf0YJoFFqfb75my5olN-97ITsi2MS62W_y-RNT0qZrbytqINA3fF3VQsSY6VcaqRAeygrKm_Q' 'Date:Thu, 22 Aug 2019 08:12:31 GMT'
```
Doing so, observe the contents of the `dbserver1.inventory.vegetable`, `dbserver1.inventory.transaction_context_data` and `dbserver1.inventory.vegetable.enriched` topics:
@@ -58,19 +58,19 @@ Doing so, observe the contents of the `dbserver1.inventory.vegetable`, `dbserver
```console
$ docker run -it --rm \
--network auditlog_default \
- quay.io/debezium/tooling:1.2 \
+ quay.io/debezium/tooling:2.0 \
/bin/bash -c "kafkacat -b kafka:9092 \
-C -o beginning -q -u -t dbserver1.inventory.vegetable | jq ."
$ docker run -it --rm \
--network auditlog_default \
- quay.io/debezium/tooling:1.2 \
+ quay.io/debezium/tooling:2.0 \
/bin/bash -c "kafkacat -b kafka:9092 \
-C -o beginning -q -u -t dbserver1.inventory.transaction_context_data | jq ."
$ docker run -it --rm \
--network auditlog_default \
- quay.io/debezium/tooling:1.2 \
+ quay.io/debezium/tooling:2.0 \
/bin/bash -c "kafkacat -b kafka:9092 \
-C -o beginning -q -u -t dbserver1.inventory.vegetable.enriched | jq ."
```
@@ -105,7 +105,7 @@ create a task for administrator to provide the missing data.
```console
$ docker run --tty --rm -i \
--network auditlog_default \
- quay.io/debezium/tooling:1.2 \
+ quay.io/debezium/tooling:2.0 \
bash -c 'pgcli postgresql://postgresuser:postgrespw@vegetables-db:5432/vegetablesdb'
```
@@ -147,7 +147,7 @@ This would then fix the missing event in the transaction context data topic and
## Stopping All Services
```console
-$ docker-compose down
+docker-compose down
```
## Running the Quarkus Applications Locally
@@ -156,7 +156,7 @@ Set `ADVERTISED_HOST_NAME` of the `kafka` service in _docker-compose.yaml_ to th
Start all services except the `vegetables-service` and the `log-enricher`:
```console
-$ docker-compose up --scale vegetables-service=0 --scale log-enricher=0
+docker-compose up --scale vegetables-service=0 --scale log-enricher=0
```
Then start the three services via the Quarkus dev mode:
diff --git a/auditlog/admin-service/.dockerignore b/auditlog/admin-service/.dockerignore
index b86c7ac340..94810d006e 100644
--- a/auditlog/admin-service/.dockerignore
+++ b/auditlog/admin-service/.dockerignore
@@ -1,4 +1,5 @@
*
!target/*-runner
!target/*-runner.jar
-!target/lib/*
\ No newline at end of file
+!target/lib/*
+!target/quarkus-app/*
\ No newline at end of file
diff --git a/auditlog/admin-service/pom.xml b/auditlog/admin-service/pom.xml
index 6e98e4227c..cca47f0c73 100644
--- a/auditlog/admin-service/pom.xml
+++ b/auditlog/admin-service/pom.xml
@@ -1,39 +1,65 @@
-
-
+
+
4.0.0
io.debezium.demos.auditing
auditing-admin-service
1.0-SNAPSHOT
- 1.8
- 1.8
- UTF-8
UTF-8
- 1.4.2.Final
- 2.22.0
+ UTF-8
+ 21
+ 21
+ 3.15.1
+ 3.2.5
+ org.kie.kogito
+ kogito-quarkus-bom
+ 10.1.0
+
- io.quarkus
- quarkus-universe-bom
+ io.quarkus.platform
+ quarkus-bom
${quarkus.version}
pom
import
+
+ ${kogito.bom.group-id}
+ ${kogito.bom.artifact-id}
+ ${kogito.bom.version}
+ pom
+ import
+
+
+
+ org.kie.kogito
+ kogito-api
+
+
+ io.quarkus
+ quarkus-messaging-kafka
+
- org.kie.kogito
- kogito-quarkus
+ io.quarkus
+ quarkus-rest
io.quarkus
- quarkus-smallrye-reactive-messaging-kafka
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
@@ -52,13 +78,15 @@
maven-surefire-plugin
${surefire-plugin.version}
-
+
org.jboss.logmanager.LogManager
-
+ ${maven.home}
+
+
native
@@ -69,21 +97,6 @@
-
- io.quarkus
- quarkus-maven-plugin
- ${quarkus.version}
-
-
-
- native-image
-
-
- true
-
-
-
-
maven-failsafe-plugin
${surefire-plugin.version}
@@ -94,9 +107,11 @@
verify
-
+
${project.build.directory}/${project.build.finalName}-runner
-
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
diff --git a/auditlog/admin-service/src/main/docker/Dockerfile.jvm b/auditlog/admin-service/src/main/docker/Dockerfile.jvm
index 39cbd25f9c..04e029bf9e 100644
--- a/auditlog/admin-service/src/main/docker/Dockerfile.jvm
+++ b/auditlog/admin-service/src/main/docker/Dockerfile.jvm
@@ -14,10 +14,20 @@
# docker run -i --rm -p 8080:8080 quarkus/admin-service-jvm
#
###
-# FROM fabric8/java-alpine-openjdk8-jre
-FROM fabric8/java-centos-openjdk8-jdk
-ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-ENV AB_ENABLED=jmx_exporter
-COPY target/lib/* /deployments/lib/
-COPY target/*-runner.jar /deployments/app.jar
-ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
+FROM registry.access.redhat.com/ubi8/openjdk-21:1.23
+
+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" ]
\ No newline at end of file
diff --git a/auditlog/admin-service/src/main/docker/Dockerfile.native b/auditlog/admin-service/src/main/docker/Dockerfile.native
index 567f42f7a4..e3223b6ab1 100644
--- a/auditlog/admin-service/src/main/docker/Dockerfile.native
+++ b/auditlog/admin-service/src/main/docker/Dockerfile.native
@@ -14,9 +14,14 @@
# docker run -i --rm -p 8080:8080 quarkus/admin-service
#
###
-FROM registry.access.redhat.com/ubi8/ubi-minimal
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10
WORKDIR /work/
-COPY target/*-runner /work/application
-RUN chmod 775 /work
+RUN chown 1001 /work \
+ && chmod "g+rwX" /work \
+ && chown 1001:root /work
+COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
+
EXPOSE 8080
-CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
+USER 1001
+
+ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/service/AdminService.java b/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/service/AdminService.java
index a305604d43..dbda325694 100644
--- a/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/service/AdminService.java
+++ b/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/service/AdminService.java
@@ -1,54 +1,44 @@
package io.debezium.demos.auditing.admin.service;
-import javax.annotation.PostConstruct;
-import javax.annotation.PreDestroy;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-
+import org.kie.api.KieServices;
+import org.kie.api.runtime.KieContainer;
import org.kie.api.runtime.KieSession;
-import org.kie.kogito.rules.KieRuntimeBuilder;
import io.debezium.demos.auditing.admin.TransactionEvent;
import io.debezium.demos.auditing.admin.VegetableEvent;
+import jakarta.annotation.PostConstruct;
+import jakarta.enterprise.context.ApplicationScoped;
@ApplicationScoped
public class AdminService {
- @Inject
- KieRuntimeBuilder kruntimeBuilder;
-
- private KieSession workinMemory;
-
+ private KieContainer kContainer;
+
@PostConstruct
public void setup() {
-
- this.workinMemory = kruntimeBuilder.newKieSession();
- }
-
- @PreDestroy
- public void cleanup() {
- this.workinMemory.dispose();
+ KieServices kieServices = KieServices.Factory.get();
+ this.kContainer = kieServices.getKieClasspathContainer();
}
-
- public TransactionEvent processTransaction(TransactionEvent event) {
- if (event == null) {
- throw new RuntimeException("Missing transaction event");
+
+ public void processEvents(TransactionEvent tx, VegetableEvent veg) {
+ if (tx == null || veg == null) {
+ throw new IllegalArgumentException("Both TransactionEvent and VegetableEvent are required");
}
-
- workinMemory.insert(event);
-
- workinMemory.fireAllRules();
- return event;
- }
- public VegetableEvent processVegetable(VegetableEvent event) {
- if (event == null) {
- throw new RuntimeException("Missing transaction event");
+ KieSession session = null;
+
+ try {
+ session = kContainer.newKieSession();
+
+ session.insert(tx);
+ session.insert(veg);
+
+ session.fireAllRules();
+
+ } finally {
+ if (session != null) {
+ session.dispose();
+ }
}
-
- workinMemory.insert(event);
-
- workinMemory.fireAllRules();
- return event;
}
-}
+}
\ No newline at end of file
diff --git a/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/wih/SendTransactionEventWIHandler.java b/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/wih/SendTransactionEventWIHandler.java
index 21340a6d45..c358852fe2 100644
--- a/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/wih/SendTransactionEventWIHandler.java
+++ b/auditlog/admin-service/src/main/java/io/debezium/demos/auditing/admin/wih/SendTransactionEventWIHandler.java
@@ -2,8 +2,6 @@
import java.util.Collections;
-import javax.enterprise.context.ApplicationScoped;
-
import org.eclipse.microprofile.reactive.messaging.Channel;
import org.eclipse.microprofile.reactive.messaging.Emitter;
import org.kie.api.runtime.process.WorkItem;
@@ -17,14 +15,17 @@
import io.debezium.demos.auditing.admin.TransactionEvent;
import io.debezium.demos.auditing.admin.VegetableEvent;
import io.smallrye.reactive.messaging.kafka.KafkaRecord;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
@ApplicationScoped
public class SendTransactionEventWIHandler implements WorkItemHandler {
- private ObjectMapper json = new ObjectMapper();
+ @Inject
+ ObjectMapper json;
@Channel("missingtransactions")
- Emitter emitter;
+ Emitter> emitter;
@Override
public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
@@ -32,38 +33,52 @@ public void executeWorkItem(WorkItem workItem, WorkItemManager manager) {
VegetableEvent vegetable = (VegetableEvent) workItem.getParameter("vegetable");
AuditData audit = (AuditData) workItem.getParameter("audit");
- TransactionEvent event = new TransactionEvent();
-
- event.setSource(vegetable.getSource());
- event.setOperation(vegetable.getOperation());
- event.setTimestamp(new java.util.Date());
+ if (vegetable == null || audit == null) {
+ throw new IllegalArgumentException("Missing required parameters: vegetable or audit");
+ }
- TransactionData data = new TransactionData();
- data.setTransactionId(vegetable.getSource().getTransactionId());
- data.setUseCase(audit.getUseCase());
- data.setClientDate(new java.util.Date());
- data.setUsername(audit.getUsername());
+ TransactionEvent event = buildEvent(vegetable, audit);
- event.setAfter(data);
+ String key = json.writeValueAsString(
+ Collections.singletonMap("transaction_id", vegetable.getSource().getTransactionId()));
- String key = json.writeValueAsString(Collections.singletonMap("transaction_id", vegetable.getSource().getTransactionId()));
String value = json.writeValueAsString(event);
- emitter.send(KafkaRecord.of(key, value));
+ emitter.send(KafkaRecord.of(key, value))
+ .toCompletableFuture()
+ .exceptionally(ex -> {
+ throw new RuntimeException("Failed to send Kafka message", ex);
+ });
manager.completeWorkItem(workItem.getId(), null);
+
} catch (Exception e) {
+ manager.abortWorkItem(workItem.getId());
throw new RuntimeException(e);
}
}
- @Override
- public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+ private TransactionEvent buildEvent(VegetableEvent vegetable, AuditData audit) {
+ TransactionEvent event = new TransactionEvent();
+
+ event.setSource(vegetable.getSource());
+ event.setOperation(vegetable.getOperation());
+ event.setTimestamp(new java.util.Date());
+
+ TransactionData data = new TransactionData();
+ data.setTransactionId(vegetable.getSource().getTransactionId());
+ data.setUseCase(audit.getUseCase());
+ data.setClientDate(new java.util.Date());
+ data.setUsername(audit.getUsername());
+
+ event.setAfter(data);
+
+ return event;
}
@Override
- public String getName() {
- return "Send Task";
+ public void abortWorkItem(WorkItem workItem, WorkItemManager manager) {
+ manager.abortWorkItem(workItem.getId());
}
-}
+}
\ No newline at end of file
diff --git a/auditlog/admin-service/src/main/resources/application.properties b/auditlog/admin-service/src/main/resources/application.properties
index 56494d5f60..1269377626 100644
--- a/auditlog/admin-service/src/main/resources/application.properties
+++ b/auditlog/admin-service/src/main/resources/application.properties
@@ -1,22 +1,24 @@
# Configuration file
# key = value
-
+# kafka.bootstrap.servers=localhost:9092
mp.messaging.incoming.transactions.connector=smallrye-kafka
-mp.messaging.incoming.transactions.bootstrap.servers=localhost:9092
+# mp.messaging.incoming.transactions.bootstrap.servers=localhost:9092
mp.messaging.incoming.transactions.topic=dbserver1.inventory.transaction_context_data
mp.messaging.incoming.transactions.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
#mp.messaging.incoming.transactions.auto.offset.reset=earliest
mp.messaging.incoming.vegetables.connector=smallrye-kafka
-mp.messaging.incoming.vegetables.bootstrap.servers=localhost:9092
+# mp.messaging.incoming.vegetables.bootstrap.servers=localhost:9092
mp.messaging.incoming.vegetables.topic=dbserver1.inventory.vegetable
mp.messaging.incoming.vegetables.value.deserializer=org.apache.kafka.common.serialization.StringDeserializer
#mp.messaging.incoming.vegetables.auto.offset.reset=earliest
mp.messaging.outgoing.missingtransactions.connector=smallrye-kafka
-mp.messaging.outgoing.missingtransactions.bootstrap.servers=localhost:9092
+# mp.messaging.outgoing.missingtransactions.bootstrap.servers=localhost:9092
mp.messaging.outgoing.missingtransactions.topic=dbserver1.inventory.transaction_context_data
mp.messaging.outgoing.missingtransactions.key.serializer=org.apache.kafka.common.serialization.StringSerializer
mp.messaging.outgoing.missingtransactions.value.serializer=org.apache.kafka.common.serialization.StringSerializer
-kogito.messaging.as-cloudevents=false
\ No newline at end of file
+kogito.messaging.as-cloudevents=false
+# Force Dev Services to use the modern Redpanda image
+quarkus.kafka.devservices.image-name=docker.io/redpandadata/redpanda:v24.1.2
\ No newline at end of file
diff --git a/auditlog/docker-compose.yaml b/auditlog/docker-compose.yaml
index 3677d96aee..569fcbdeed 100644
--- a/auditlog/docker-compose.yaml
+++ b/auditlog/docker-compose.yaml
@@ -3,42 +3,65 @@ services:
image: quay.io/debezium/kafka:${DEBEZIUM_VERSION}
ports:
- 9092:9092
+ # environment:
+ # KAFKA_NODE_ID: 1
+ # KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: "CONTROLLER:PLAINTEXT,PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT"
+ # KAFKA_ADVERTISED_LISTENERS: "PLAINTEXT_HOST://localhost:9092,PLAINTEXT://broker:19092"
+ # KAFKA_PROCESS_ROLES: "broker,controller"
+ # # KAFKA_CONTROLLER_QUORUM_VOTERS: "1@broker:29093"
+ #
+ # KAFKA_LISTENERS: "CONTROLLER://:29093,PLAINTEXT_HOST://:9092,PLAINTEXT://:19092"
+ # KAFKA_INTER_BROKER_LISTENER_NAME: "PLAINTEXT"
+ # KAFKA_CONTROLLER_LISTENER_NAMES: "CONTROLLER"
+ # CLUSTER_ID: "4L6g3nShT-eMCtK--X86sw"
+ # KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
+ # KAFKA_GROUP_INITIAL_REBALANCE_DELAY_MS: 0
+ # KAFKA_TRANSACTION_STATE_LOG_MIN_ISR: 1
+ # KAFKA_TRANSACTION_STATE_LOG_REPLICATION_FACTOR: 1
+ # KAFKA_SHARE_COORDINATOR_STATE_TOPIC_REPLICATION_FACTOR: 1
+ # KAFKA_SHARE_COORDINATOR_STATE_TOPIC_MIN_ISR: 1
+ # KAFKA_LOG_DIRS: "/tmp/kraft-combined-logs"
- 9093:9093
+ - 29092:29092
environment:
- CLUSTER_ID=oh-sxaDRTcyAr6pFRbXyzA
- - NODE_ID=1
- - NODE_ROLE=combined
- - KAFKA_CONTROLLER_QUORUM_VOTERS=1@kafka:9093
- - KAFKA_LISTENERS=PLAINTEXT://kafka:9092,CONTROLLER://kafka:9093
- - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092
+ - KAFKA_NODE_ID=1
+ - KAFKA_PROCESS_ROLES=broker,controller
+ - KAFKA_CONTROLLER_QUORUM_BOOTSTRAP_SERVERS=kafka:9093
+ - KAFKA_LISTENERS=PLAINTEXT://kafka:9092,CONTROLLER://kafka:9093,DEVLISTENER://localhost:29092
+ - KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092,DEVLISTENER://localhost:29092
+ - KAFKA_LISTENER_SECURITY_PROTOCOL_MAP=PLAINTEXT:PLAINTEXT,DEVLISTENER:PLAINTEXT,CONTROLLER:PLAINTEXT
# For local development of auditlog-enricher
# - ADVERTISED_HOST_NAME=192.168.1.6
- KAFKA_GROUP_MIN_SESSION_TIMEOUT_MS=250
+ - KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR=1
+ - KAFKA_DEFAULT_REPLICATION_FACTOR=1
+ - KAFKA_MIN_INSYNC_REPLICAS=1
vegetables-db:
image: quay.io/debezium/example-postgres:${DEBEZIUM_VERSION}
ports:
- - 5432:5432
+ - 5432:5432
environment:
- - POSTGRES_USER=postgresuser
- - POSTGRES_PASSWORD=postgrespw
- - POSTGRES_DB=vegetablesdb
+ - POSTGRES_USER=postgresuser
+ - POSTGRES_PASSWORD=postgrespw
+ - POSTGRES_DB=vegetablesdb
connect:
image: quay.io/debezium/connect:${DEBEZIUM_VERSION}
ports:
- - 8083:8083
+ - 8083:8083
depends_on:
- - kafka
- - vegetables-db
+ - kafka
+ - vegetables-db
environment:
- - BOOTSTRAP_SERVERS=kafka:9092
- - GROUP_ID=1
- - CONFIG_STORAGE_TOPIC=my_source_connect_configs
- - OFFSET_STORAGE_TOPIC=my_source_connect_offsets
- - STATUS_STORAGE_TOPIC=my_source_connect_statuses
- - CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE=false
- - CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE=false
+ - BOOTSTRAP_SERVERS=kafka:9092
+ - GROUP_ID=1
+ - CONFIG_STORAGE_TOPIC=my_source_connect_configs
+ - OFFSET_STORAGE_TOPIC=my_source_connect_offsets
+ - STATUS_STORAGE_TOPIC=my_source_connect_statuses
+ - CONNECT_KEY_CONVERTER_SCHEMAS_ENABLE=false
+ - CONNECT_VALUE_CONVERTER_SCHEMAS_ENABLE=false
vegetables-service:
image: debezium-examples/auditing-vegetables-service:${DEBEZIUM_VERSION}
@@ -46,14 +69,11 @@ services:
context: vegetables-service
dockerfile: src/main/docker/Dockerfile.jvm
ports:
- - 8080:8080
+ - 8080:8080
depends_on:
- - vegetables-db
+ - vegetables-db
environment:
- - QUARKUS_DATASOURCE_URL=jdbc:postgresql://vegetables-db:5432/vegetablesdb?currentSchema=inventory
- #depends_on:
- # vegetable-db:
- # condition: service_healthy
+ - QUARKUS_DATASOURCE_JDBC_URL=jdbc:postgresql://vegetables-db:5432/vegetablesdb?currentSchema=inventory
log-enricher:
image: debezium-examples/auditing-log-enricher:${DEBEZIUM_VERSION}
@@ -61,11 +81,11 @@ services:
context: log-enricher
dockerfile: src/main/docker/Dockerfile.jvm
ports:
- - 8081:8080
+ - 8081:8080
depends_on:
- - kafka
+ - kafka
environment:
- - QUARKUS_KAFKA_STREAMS_BOOTSTRAP_SERVERS=kafka:9092
+ - QUARKUS_KAFKA_STREAMS_BOOTSTRAP_SERVERS=kafka:9092
admin-service:
image: debezium-examples/auditing-admin-service:${DEBEZIUM_VERSION}
@@ -73,10 +93,11 @@ services:
context: admin-service
dockerfile: src/main/docker/Dockerfile.jvm
ports:
- - 8085:8080
+ - 8085:8080
depends_on:
- - kafka
+ - kafka
environment:
- - MP_MESSAGING_INCOMING_VEGETABLES_BOOTSTRAP_SERVERS=kafka:9092
- - MP_MESSAGING_INCOMING_TRANSACTIONS_BOOTSTRAP_SERVERS=kafka:9092
- - MP_MESSAGING_OUTGOING_MISSINGTRANSACTIONS_BOOTSTRAP_SERVERS=kafka:9092
+ - KAFKA_BOOTSTRAP_SERVERS=kafka:9092
+ - MP_MESSAGING_INCOMING_VEGETABLES_BOOTSTRAP_SERVERS=kafka:9092
+ - MP_MESSAGING_INCOMING_TRANSACTIONS_BOOTSTRAP_SERVERS=kafka:9092
+ - MP_MESSAGING_OUTGOING_MISSINGTRANSACTIONS_BOOTSTRAP_SERVERS=kafka:9092
diff --git a/auditlog/log-enricher/.dockerignore b/auditlog/log-enricher/.dockerignore
index b86c7ac340..94810d006e 100644
--- a/auditlog/log-enricher/.dockerignore
+++ b/auditlog/log-enricher/.dockerignore
@@ -1,4 +1,5 @@
*
!target/*-runner
!target/*-runner.jar
-!target/lib/*
\ No newline at end of file
+!target/lib/*
+!target/quarkus-app/*
\ No newline at end of file
diff --git a/auditlog/log-enricher/pom.xml b/auditlog/log-enricher/pom.xml
index 92eb40418a..6214abed3b 100644
--- a/auditlog/log-enricher/pom.xml
+++ b/auditlog/log-enricher/pom.xml
@@ -7,16 +7,16 @@
1.0-SNAPSHOT
UTF-8
- 2.22.0
- 1.4.2.Final
UTF-8
- 1.8
- 1.8
+ 21
+ 21
+ 3.15.1
+ 3.2.5
- io.quarkus
+ io.quarkus.platform
quarkus-bom
${quarkus.version}
pom
@@ -27,17 +27,11 @@
io.quarkus
- quarkus-resteasy
+ quarkus-rest
io.quarkus
- quarkus-junit5
- test
-
-
- io.rest-assured
- rest-assured
- test
+ quarkus-jsonp
io.quarkus
@@ -45,7 +39,13 @@
io.quarkus
- quarkus-jsonp
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
@@ -66,57 +66,12 @@
maven-surefire-plugin
${surefire-plugin.version}
-
+
org.jboss.logmanager.LogManager
-
+ ${maven.home}
+
-
-
- native
-
-
- native
-
-
-
-
-
- io.quarkus
- quarkus-maven-plugin
- ${quarkus.version}
-
-
-
- native-image
-
-
- true
-
-
-
-
-
- maven-failsafe-plugin
- ${surefire-plugin.version}
-
-
-
- integration-test
- verify
-
-
-
- ${project.build.directory}/${project.build.finalName}-runner
-
-
-
-
-
-
-
-
-
-
+
\ No newline at end of file
diff --git a/auditlog/log-enricher/src/main/docker/Dockerfile.jvm b/auditlog/log-enricher/src/main/docker/Dockerfile.jvm
index 4bb95f5ec9..17f3ef0187 100644
--- a/auditlog/log-enricher/src/main/docker/Dockerfile.jvm
+++ b/auditlog/log-enricher/src/main/docker/Dockerfile.jvm
@@ -14,9 +14,20 @@
# docker run -i --rm -p 8080:8080 quarkus/auditing-log-enricher-jvm
#
###
-FROM fabric8/java-centos-openjdk8-jdk
-ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-ENV AB_ENABLED=jmx_exporter
-COPY target/lib/* /deployments/lib/
-COPY target/*-runner.jar /deployments/app.jar
-ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
+FROM registry.access.redhat.com/ubi8/openjdk-21:1.23
+
+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" ]
\ No newline at end of file
diff --git a/auditlog/log-enricher/src/main/docker/Dockerfile.native b/auditlog/log-enricher/src/main/docker/Dockerfile.native
index 68474bdffc..630f9db631 100644
--- a/auditlog/log-enricher/src/main/docker/Dockerfile.native
+++ b/auditlog/log-enricher/src/main/docker/Dockerfile.native
@@ -14,9 +14,14 @@
# docker run -i --rm -p 8080:8080 quarkus/auditing-log-enricher
#
###
-FROM registry.access.redhat.com/ubi8/ubi-minimal
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10
WORKDIR /work/
-COPY target/*-runner /work/application
-RUN chmod 775 /work
+RUN chown 1001 /work \
+ && chmod "g+rwX" /work \
+ && chown 1001:root /work
+COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
+
EXPOSE 8080
-CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
+USER 1001
+
+ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/BufferOffsets.java b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/BufferOffsets.java
index e9f14d66ab..beea245b84 100644
--- a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/BufferOffsets.java
+++ b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/BufferOffsets.java
@@ -1,7 +1,7 @@
package io.debezium.demos.auditing.enricher;
-import javax.json.Json;
-import javax.json.JsonObject;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
/**
* Keeps track of the position within the key/value state store that is used as
@@ -31,8 +31,7 @@ public static BufferOffsets initial() {
static BufferOffsets fromJson(JsonObject json) {
return new BufferOffsets(
json.getJsonNumber("firstValue").longValue(),
- json.getJsonNumber("nextValue").longValue()
- );
+ json.getJsonNumber("nextValue").longValue());
}
public JsonObject toJson() {
diff --git a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/ChangeEventEnricher.java b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/ChangeEventEnricher.java
index 962f185f0a..b465ca5446 100644
--- a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/ChangeEventEnricher.java
+++ b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/ChangeEventEnricher.java
@@ -4,9 +4,6 @@
import java.util.Arrays;
import java.util.Optional;
-import javax.json.Json;
-import javax.json.JsonObject;
-
import org.apache.kafka.streams.KeyValue;
import org.apache.kafka.streams.kstream.Transformer;
import org.apache.kafka.streams.processor.ProcessorContext;
@@ -17,6 +14,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+
/**
* Enriches change events with transaction-scoped metadata. If no metadata for
* the associated transaction can be retrieved yet (as the change event gets
@@ -39,7 +39,8 @@ class ChangeEventEnricher implements Transformer) context.getStateStore(TopologyProducer.STREAM_BUFFER_NAME);
- txMetaDataStore = (TimestampedKeyValueStore) context.getStateStore(TopologyProducer.STORE_NAME);
+ txMetaDataStore = (TimestampedKeyValueStore) context
+ .getStateStore(TopologyProducer.STORE_NAME);
context.schedule(Duration.ofSeconds(1), PunctuationType.WALL_CLOCK_TIME, ts -> enrichAndEmitBufferedEvents());
}
@@ -79,12 +80,13 @@ private boolean enrichAndEmitBufferedEvents() {
boolean enrichedAllBuffered = true;
- for(long i = sequence.getFirstValue(); i < sequence.getNextValue(); i++) {
+ for (long i = sequence.getFirstValue(); i < sequence.getNextValue(); i++) {
JsonObject buffered = streamBuffer.get(i);
LOG.info("Processing buffered change event for key {}", buffered.getJsonObject("key"));
- KeyValue enriched = enrichWithTxMetaData(buffered.getJsonObject("key"), buffered.getJsonObject("changeEvent"));
+ KeyValue enriched = enrichWithTxMetaData(buffered.getJsonObject("key"),
+ buffered.getJsonObject("changeEvent"));
if (enriched == null) {
enrichedAllBuffered = false;
break;
@@ -117,8 +119,7 @@ private void bufferChangeEvent(JsonObject key, JsonObject changeEvent) {
streamBuffer.putAll(Arrays.asList(
KeyValue.pair(sequence.getNextValueAndIncrement(), wrapper),
- KeyValue.pair(BUFFER_OFFSETS_KEY, sequence.toJson())
- ));
+ KeyValue.pair(BUFFER_OFFSETS_KEY, sequence.toJson())));
}
/**
@@ -145,9 +146,8 @@ private KeyValue enrichWithTxMetaData(JsonObject key, Js
return KeyValue.pair(
key,
Json.createObjectBuilder(changeEvent)
- .add("audit", txMetaData)
- .build()
- );
+ .add("audit", txMetaData)
+ .build());
}
LOG.warn("No metadata found for transaction {}", txId);
@@ -158,8 +158,7 @@ private Optional bufferOffsets() {
JsonObject bufferOffsets = streamBuffer.get(BUFFER_OFFSETS_KEY);
if (bufferOffsets == null) {
return Optional.empty();
- }
- else {
+ } else {
return Optional.of(BufferOffsets.fromJson(bufferOffsets));
}
}
diff --git a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/JsonObjectSerde.java b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/JsonObjectSerde.java
index 92c03ba66a..e706207b9d 100644
--- a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/JsonObjectSerde.java
+++ b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/JsonObjectSerde.java
@@ -5,15 +5,14 @@
import java.io.IOException;
import java.util.Map;
-import javax.json.Json;
-import javax.json.JsonObject;
-import javax.json.JsonReader;
-
import org.apache.kafka.common.serialization.Deserializer;
import org.apache.kafka.common.serialization.Serde;
import org.apache.kafka.common.serialization.Serializer;
import io.quarkus.runtime.annotations.RegisterForReflection;
+import jakarta.json.Json;
+import jakarta.json.JsonObject;
+import jakarta.json.JsonReader;
/**
* A {@link Serde} that (de-)serializes JSON.
diff --git a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/TopologyProducer.java b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/TopologyProducer.java
index 9154948d1f..1eb62d8f2e 100644
--- a/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/TopologyProducer.java
+++ b/auditlog/log-enricher/src/main/java/io/debezium/demos/auditing/enricher/TopologyProducer.java
@@ -1,9 +1,5 @@
package io.debezium.demos.auditing.enricher;
-import javax.enterprise.context.ApplicationScoped;
-import javax.enterprise.inject.Produces;
-import javax.json.JsonObject;
-
import org.apache.kafka.common.serialization.Serdes;
import org.apache.kafka.streams.StreamsBuilder;
import org.apache.kafka.streams.Topology;
@@ -13,6 +9,10 @@
import org.apache.kafka.streams.state.Stores;
import org.eclipse.microprofile.config.inject.ConfigProperty;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.enterprise.inject.Produces;
+import jakarta.json.JsonObject;
+
@ApplicationScoped
public class TopologyProducer {
@@ -32,15 +32,13 @@ public class TopologyProducer {
public Topology buildTopology() {
StreamsBuilder builder = new StreamsBuilder();
- StoreBuilder> streamBufferStateStore =
- Stores
- .keyValueStoreBuilder(
+ StoreBuilder> streamBufferStateStore = Stores
+ .keyValueStoreBuilder(
Stores.persistentKeyValueStore(STREAM_BUFFER_NAME),
new Serdes.LongSerde(),
- new JsonObjectSerde()
- )
- .withCachingDisabled();
- builder.addStateStore(streamBufferStateStore);
+ new JsonObjectSerde())
+ .withCachingDisabled();
+ builder.addStateStore(streamBufferStateStore);
builder.globalTable(txContextDataTopic, Materialized.as(STORE_NAME));
@@ -50,7 +48,8 @@ public Topology buildTopology() {
.filter((id, changeEvent) -> changeEvent != null)
// exclude snapshot events
.filter((id, changeEvent) -> !changeEvent.getString("op").equals("r"))
- // enrich change events with transaction metadata via the statestore of the TX topic
+ // enrich change events with transaction metadata via the statestore of the TX
+ // topic
.transform(() -> new ChangeEventEnricher(), STREAM_BUFFER_NAME)
.to(vegetablesEnrichedTopic);
diff --git a/auditlog/register-postgres.json b/auditlog/register-postgres.json
index d56ab63378..96b90f1497 100644
--- a/auditlog/register-postgres.json
+++ b/auditlog/register-postgres.json
@@ -5,7 +5,8 @@
"database.port": "5432",
"database.user": "postgresuser",
"database.password": "postgrespw",
- "database.dbname" : "vegetablesdb",
+ "database.dbname": "vegetablesdb",
"database.server.name": "dbserver1",
- "table.include.list": "inventory.vegetable,inventory.transaction_context_data"
-}
+ "table.include.list": "inventory.vegetable,inventory.transaction_context_data",
+ "topic.prefix": "dbserver1"
+}
\ No newline at end of file
diff --git a/auditlog/vegetables-service/pom.xml b/auditlog/vegetables-service/pom.xml
index 8e64ffc332..eecfa611d6 100644
--- a/auditlog/vegetables-service/pom.xml
+++ b/auditlog/vegetables-service/pom.xml
@@ -7,16 +7,16 @@
1.0-SNAPSHOT
UTF-8
- 2.22.0
- 1.4.2.Final
UTF-8
- 1.8
- 1.8
+ 21
+ 21
+ 3.15.1
+ 3.2.5
- io.quarkus
+ io.quarkus.platform
quarkus-bom
${quarkus.version}
pom
@@ -27,30 +27,22 @@
io.quarkus
- quarkus-resteasy
+ quarkus-rest
io.quarkus
- quarkus-undertow
+ quarkus-rest-jsonb
+
io.quarkus
- quarkus-junit5
- test
-
-
- io.rest-assured
- rest-assured
- test
+ quarkus-undertow
+
io.quarkus
quarkus-smallrye-jwt
-
- io.quarkus
- quarkus-resteasy-jsonb
-
io.quarkus
quarkus-hibernate-orm
@@ -63,6 +55,17 @@
io.quarkus
quarkus-jdbc-postgresql
+
+
+ io.quarkus
+ quarkus-junit5
+ test
+
+
+ io.rest-assured
+ rest-assured
+ test
+
@@ -82,9 +85,10 @@
maven-surefire-plugin
${surefire-plugin.version}
-
+
org.jboss.logmanager.LogManager
-
+ ${maven.home}
+
@@ -99,21 +103,6 @@
-
- io.quarkus
- quarkus-maven-plugin
- ${quarkus.version}
-
-
-
- native-image
-
-
- true
-
-
-
-
maven-failsafe-plugin
${surefire-plugin.version}
@@ -124,9 +113,11 @@
verify
-
+
${project.build.directory}/${project.build.finalName}-runner
-
+ org.jboss.logmanager.LogManager
+ ${maven.home}
+
@@ -135,4 +126,4 @@
-
+
\ No newline at end of file
diff --git a/auditlog/vegetables-service/src/main/docker/Dockerfile.jvm b/auditlog/vegetables-service/src/main/docker/Dockerfile.jvm
index 833541894e..38d0c8cdad 100644
--- a/auditlog/vegetables-service/src/main/docker/Dockerfile.jvm
+++ b/auditlog/vegetables-service/src/main/docker/Dockerfile.jvm
@@ -14,10 +14,20 @@
# docker run -i --rm -p 8080:8080 quarkus/debezium-auditing-demo-jvm
#
###
-# FROM fabric8/java-alpine-openjdk8-jre
-FROM fabric8/java-centos-openjdk8-jdk
-ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
-ENV AB_ENABLED=jmx_exporter
-COPY target/lib/* /deployments/lib/
-COPY target/*-runner.jar /deployments/app.jar
-ENTRYPOINT [ "/deployments/run-java.sh" ]
\ No newline at end of file
+FROM registry.access.redhat.com/ubi8/openjdk-21:1.23
+
+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" ]
\ No newline at end of file
diff --git a/auditlog/vegetables-service/src/main/docker/Dockerfile.native b/auditlog/vegetables-service/src/main/docker/Dockerfile.native
index 4caf3be3b4..9e54ef2e87 100644
--- a/auditlog/vegetables-service/src/main/docker/Dockerfile.native
+++ b/auditlog/vegetables-service/src/main/docker/Dockerfile.native
@@ -14,9 +14,14 @@
# docker run -i --rm -p 8080:8080 quarkus/debezium-auditing-demo
#
###
-FROM registry.access.redhat.com/ubi8/ubi-minimal
+FROM registry.access.redhat.com/ubi8/ubi-minimal:8.10
WORKDIR /work/
-COPY target/*-runner /work/application
-RUN chmod 775 /work
+RUN chown 1001 /work \
+ && chmod "g+rwX" /work \
+ && chown 1001:root /work
+COPY --chown=1001:root --chmod=0755 target/*-runner /work/application
+
EXPOSE 8080
-CMD ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
+USER 1001
+
+ENTRYPOINT ["./application", "-Dquarkus.http.host=0.0.0.0"]
\ No newline at end of file
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/model/Vegetable.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/model/Vegetable.java
index 564b6f9724..1c81488974 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/model/Vegetable.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/model/Vegetable.java
@@ -1,10 +1,10 @@
package io.debezium.demos.auditing.vegetables.model;
-import javax.persistence.Entity;
-import javax.persistence.GeneratedValue;
-import javax.persistence.GenerationType;
-import javax.persistence.Id;
-import javax.persistence.SequenceGenerator;
+import jakarta.persistence.Entity;
+import jakarta.persistence.GeneratedValue;
+import jakarta.persistence.GenerationType;
+import jakarta.persistence.Id;
+import jakarta.persistence.SequenceGenerator;
@Entity
public class Vegetable {
@@ -14,11 +14,7 @@ public class Vegetable {
private String description;
@Id
- @SequenceGenerator(
- name = "vegetablesSequence",
- sequenceName = "vegetables_id_seq",
- allocationSize = 10,
- initialValue = 10)
+ @SequenceGenerator(name = "vegetablesSequence", sequenceName = "vegetables_id_seq", allocationSize = 10, initialValue = 10)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "vegetablesSequence")
public Long getId() {
return id;
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/VegetableResource.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/VegetableResource.java
index 8bdfd870d3..7173058184 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/VegetableResource.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/VegetableResource.java
@@ -1,24 +1,22 @@
package io.debezium.demos.auditing.vegetables.rest;
-import javax.annotation.security.RolesAllowed;
-import javax.enterprise.context.RequestScoped;
-import javax.inject.Inject;
-import javax.transaction.Transactional;
-import javax.ws.rs.Consumes;
-import javax.ws.rs.DELETE;
-import javax.ws.rs.POST;
-import javax.ws.rs.PUT;
-import javax.ws.rs.Path;
-import javax.ws.rs.Produces;
-import javax.ws.rs.core.MediaType;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-
-import org.jboss.resteasy.annotations.jaxrs.PathParam;
-
import io.debezium.demos.auditing.vegetables.model.Vegetable;
import io.debezium.demos.auditing.vegetables.service.VegetableService;
import io.debezium.demos.auditing.vegetables.transactioncontext.Audited;
+import jakarta.annotation.security.RolesAllowed;
+import jakarta.enterprise.context.RequestScoped;
+import jakarta.inject.Inject;
+import jakarta.transaction.Transactional;
+import jakarta.ws.rs.Consumes;
+import jakarta.ws.rs.DELETE;
+import jakarta.ws.rs.POST;
+import jakarta.ws.rs.PUT;
+import jakarta.ws.rs.Path;
+import jakarta.ws.rs.PathParam;
+import jakarta.ws.rs.Produces;
+import jakarta.ws.rs.core.MediaType;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
@Path("/vegetables")
@RequestScoped
@@ -30,9 +28,9 @@ public class VegetableResource {
VegetableService vegetableService;
@POST
- @RolesAllowed({"farmers"})
+ @RolesAllowed({ "farmers" })
@Transactional
- @Audited(useCase="CREATE VEGETABLE")
+ @Audited(useCase = "CREATE VEGETABLE")
public Response createVegetable(Vegetable vegetable) {
if (vegetable.getId() != null) {
return Response.status(Status.BAD_REQUEST.getStatusCode()).build();
@@ -45,9 +43,9 @@ public Response createVegetable(Vegetable vegetable) {
@Path("/{id}")
@PUT
- @RolesAllowed({"farmers"})
+ @RolesAllowed({ "farmers" })
@Transactional
- @Audited(useCase="UPDATE VEGETABLE")
+ @Audited(useCase = "UPDATE VEGETABLE")
public Vegetable updateVegetable(@PathParam("id") long id, Vegetable vegetable) {
vegetable.setId(id);
vegetable = vegetableService.updateVegetable(vegetable);
@@ -57,9 +55,9 @@ public Vegetable updateVegetable(@PathParam("id") long id, Vegetable vegetable)
@Path("/{id}")
@DELETE
- @RolesAllowed({"farmers"})
+ @RolesAllowed({ "farmers" })
@Transactional
- @Audited(useCase="DELETE VEGETABLE")
+ @Audited(useCase = "DELETE VEGETABLE")
public void deleteVegetable(@PathParam("id") long id) {
vegetableService.deleteVegetable(id);
}
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/util/ErrorMapper.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/util/ErrorMapper.java
index 7411558748..fc5a20c5c1 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/util/ErrorMapper.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/rest/util/ErrorMapper.java
@@ -1,11 +1,11 @@
package io.debezium.demos.auditing.vegetables.rest.util;
-import javax.json.Json;
-import javax.persistence.EntityNotFoundException;
-import javax.ws.rs.core.Response;
-import javax.ws.rs.core.Response.Status;
-import javax.ws.rs.ext.ExceptionMapper;
-import javax.ws.rs.ext.Provider;
+import jakarta.json.Json;
+import jakarta.persistence.EntityNotFoundException;
+import jakarta.ws.rs.core.Response;
+import jakarta.ws.rs.core.Response.Status;
+import jakarta.ws.rs.ext.ExceptionMapper;
+import jakarta.ws.rs.ext.Provider;
@Provider
public class ErrorMapper implements ExceptionMapper {
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/service/VegetableService.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/service/VegetableService.java
index 47dc696c6c..f5a687f1eb 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/service/VegetableService.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/service/VegetableService.java
@@ -1,10 +1,9 @@
package io.debezium.demos.auditing.vegetables.service;
-import javax.enterprise.context.ApplicationScoped;
-import javax.inject.Inject;
-import javax.persistence.EntityManager;
-
import io.debezium.demos.auditing.vegetables.model.Vegetable;
+import jakarta.enterprise.context.ApplicationScoped;
+import jakarta.inject.Inject;
+import jakarta.persistence.EntityManager;
@ApplicationScoped
public class VegetableService {
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/Audited.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/Audited.java
index 680fccc65c..58ef7b46d7 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/Audited.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/Audited.java
@@ -7,12 +7,13 @@
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
-import javax.enterprise.util.Nonbinding;
-import javax.interceptor.InterceptorBinding;
+import jakarta.enterprise.util.Nonbinding;
+import jakarta.interceptor.InterceptorBinding;
@InterceptorBinding
-@Target({METHOD, TYPE})
+@Target({ METHOD, TYPE })
@Retention(RUNTIME)
public @interface Audited {
- @Nonbinding String useCase();
+ @Nonbinding
+ String useCase();
}
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionContextData.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionContextData.java
index 514d858988..8887995f22 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionContextData.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionContextData.java
@@ -2,25 +2,25 @@
import java.time.ZonedDateTime;
-import javax.persistence.Column;
-import javax.persistence.Entity;
-import javax.persistence.Id;
-import javax.persistence.Table;
+import jakarta.persistence.Column;
+import jakarta.persistence.Entity;
+import jakarta.persistence.Id;
+import jakarta.persistence.Table;
@Entity
-@Table(name="transaction_context_data")
+@Table(name = "transaction_context_data")
public class TransactionContextData {
@Id
- @Column(name="transaction_id")
+ @Column(name = "transaction_id")
public long transactionId;
- @Column(name="user_name")
+ @Column(name = "user_name")
public String userName;
- @Column(name="client_date")
+ @Column(name = "client_date")
public ZonedDateTime clientDate;
- @Column(name="useCase")
+ @Column(name = "useCase")
public String useCase;
}
diff --git a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionInterceptor.java b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionInterceptor.java
index bd647dd90c..5a001539de 100644
--- a/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionInterceptor.java
+++ b/auditlog/vegetables-service/src/main/java/io/debezium/demos/auditing/vegetables/transactioncontext/TransactionInterceptor.java
@@ -1,20 +1,19 @@
package io.debezium.demos.auditing.vegetables.transactioncontext;
-import java.math.BigInteger;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
-import javax.annotation.Priority;
-import javax.inject.Inject;
-import javax.interceptor.AroundInvoke;
-import javax.interceptor.Interceptor;
-import javax.interceptor.InvocationContext;
-import javax.persistence.EntityManager;
-import javax.servlet.http.HttpServletRequest;
-import javax.ws.rs.core.HttpHeaders;
-
import org.eclipse.microprofile.jwt.JsonWebToken;
+import jakarta.annotation.Priority;
+import jakarta.inject.Inject;
+import jakarta.interceptor.AroundInvoke;
+import jakarta.interceptor.Interceptor;
+import jakarta.interceptor.InvocationContext;
+import jakarta.persistence.EntityManager;
+import jakarta.ws.rs.container.ContainerRequestContext;
+import jakarta.ws.rs.core.HttpHeaders;
+
@Interceptor
@Priority(value = Interceptor.Priority.APPLICATION + 100)
@Audited(useCase = "")
@@ -27,16 +26,16 @@ public class TransactionInterceptor {
EntityManager entityManager;
@Inject
- HttpServletRequest request;
+ ContainerRequestContext requestContext;
@AroundInvoke
public Object manageTransaction(InvocationContext ctx) throws Exception {
- BigInteger txtId = (BigInteger) entityManager.createNativeQuery("SELECT txid_current()").getSingleResult();
+ Long txtId = (Long) entityManager.createNativeQuery("SELECT txid_current()").getSingleResult();
String useCase = ctx.getMethod().getAnnotation(Audited.class).useCase();
TransactionContextData context = new TransactionContextData();
- context.transactionId = txtId.longValueExact();
+ context.transactionId = txtId;
context.userName = jwt.claim("sub").orElse("anonymous");
context.clientDate = getRequestDate();
context.useCase = useCase;
@@ -47,7 +46,7 @@ public Object manageTransaction(InvocationContext ctx) throws Exception {
}
private ZonedDateTime getRequestDate() {
- String requestDate = request.getHeader(HttpHeaders.DATE);
+ String requestDate = requestContext.getHeaderString(HttpHeaders.DATE);
return requestDate != null ? ZonedDateTime.parse(requestDate, DateTimeFormatter.RFC_1123_DATE_TIME) : null;
}
}
diff --git a/auditlog/vegetables-service/src/main/resources/application.properties b/auditlog/vegetables-service/src/main/resources/application.properties
index 0703c7bcdb..f8b67a7e96 100644
--- a/auditlog/vegetables-service/src/main/resources/application.properties
+++ b/auditlog/vegetables-service/src/main/resources/application.properties
@@ -1,12 +1,13 @@
mp.jwt.verify.issuer=farmshop
mp.jwt.verify.publickey=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjYWJ6Zt9Jo9dxVuMglo0rYN4vBV0T7AP+qD/aI7tTrus6ZMvTi/+JKlNpEAS0b6yasYjxuKmh3eYT0PbGmGERr07VDsVcV/iezl9pj+fceY4lebrExS36yGQJs6BUXYF4P8ynmvnKC40AuyxKFgb3T08h1jxoBsBKlPfAT620ZP1vwgGwZB7iAfzdNYtt3z2NtkyPMaD1mHU6rxewjVN9XVSSSPKO8nFPTYsm1i4ePohgWr9bxwFHkXzyk7DnpUBMZzlVUUXVPuEpkVCqnWZTslMw/pgsyXPw1pmV76rVwhI0Ay4XohPW2QvDoPKHhuiQtcNrfL++iEFG8A9hh1K3QIDAQAB
-quarkus.datasource.url=jdbc:postgresql://localhost:5432/vegetablesdb?currentSchema=inventory
-quarkus.datasource.driver=org.postgresql.Driver
+quarkus.datasource.db-kind=postgresql
+quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/vegetablesdb?currentSchema=inventory
+
quarkus.datasource.username=postgresuser
quarkus.datasource.password=postgrespw
-quarkus.datasource.max-size=8
-quarkus.datasource.min-size=2
+quarkus.datasource.jdbc.max-size=8
+quarkus.datasource.jdbc.min-size=2
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.log.sql=true
quarkus.hibernate-orm.jdbc.timezone=UTC