Skip to content

Commit

Permalink
Migrate jpa-idempotent-repository example from deprecated derby conta…
Browse files Browse the repository at this point in the history
…iner image to MariaDB
  • Loading branch information
jamesnetherton committed Jan 8, 2024
1 parent a89c384 commit 7ee831b
Show file tree
Hide file tree
Showing 9 changed files with 203 additions and 236 deletions.
72 changes: 16 additions & 56 deletions jpa-idempotent-repository/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -64,46 +64,23 @@ The camel application should produce logs as below:
2023-09-15 15:48:20,804 INFO [org.acm.jpa.ide.rep.CostlyApiService] (vert.x-worker-thread-1) Costly API has been called with new content => GOOD
----
When running in dev mode, the idempotent consumer is storing the list of already processed messages in-memory, into a h2 database.
Later on, another database will be used when we'll package and run the application.
Indeed, the duplicate messages will then be stored in files, into a derby database.
The idempotent consumer is storing the list of already processed messages into a MariaDB database.
== Starting and initializing the derby database in a container
If you're wondering how the database schema was created, it happens automatically thanks to `quarkus-flyway`. On application startup, it
creates the `my-db` database and the required `CAMEL_MESSAGEPROCESSED` table. You can find the Flyway migration script at `src/main/resources/db/migration/V1.0.0__add_camel_message_processed.sql`.
You can find more information about Flyway in the https://quarkus.io/guides/flyway[Quarkus Flyway guide].
Before packaging and running the application in JVM mode, we need to start and initialize a derby database in a container.
So, in a first shell, please launch a derby database container:
== Starting and initializing the MariaDB database in a container
[source,shell]
----
docker run -p 1527:1527 az82/docker-derby:10.16
----
And from a second shell, please run the commands below in order to initialize the derby database:
Before packaging and running the application in JVM mode, we need to start and initialize a MariaDB database in a container.
So, in a first shell, please launch a MariaDB database container:
[source,shell]
----
DERBY_DOCKER_ID=$(docker ps -q --filter ancestor=az82/docker-derby)
docker cp src/test/resources/init.sql ${DERBY_DOCKER_ID}:/init.sql
docker exec -it ${DERBY_DOCKER_ID} java -Djdbc.drivers=org.apache.derbbc.EmbeddedDriver org.apache.derby.tools.ij /init.sql
----
It should output some logs like below:
[source,shell]
docker run -e MARIADB_USER=mariadb -e MARIADB_PASSWORD=mariadb -e MARIADB_DATABASE=my-db -e MARIADB_ROOT_PASSWORD=secret -p 3306:3306 docker.io/mariadb:10.11
----
$ DERBY_DOCKER_ID=$(docker ps -q --filter ancestor=az82/docker-derby)
$ docker cp src/test/resources/init.sql ${DERBY_DOCKER_ID}:/init.sql
Successfully copied 2.05kB to c88edda502f7:/init.sql
$ docker exec -it ${DERBY_DOCKER_ID} java -Djdbc.drivers=org.apache.derbbc.EmbeddedDriver org.apache.derby.tools.ij /init.sql
ij version 10.16
ij> CONNECT 'jdbc:derby:my-db;create=true';
ij> CREATE TABLE CAMEL_MESSAGEPROCESSED ( processorName VARCHAR(255), messageId VARCHAR(100), createdAt TIMESTAMP, PRIMARY KEY (processorName, messageId) );
0 rows inserted/updated/deleted
ij> CREATE SEQUENCE CAMEL_MESSAGEPROCESSED_SEQ AS INT MAXVALUE 999999 CYCLE;
0 rows inserted/updated/deleted
----
If successful, you should see the message `mariadbd: ready for connections` output to the console.
=== Package and run the application
Expand All @@ -120,26 +97,7 @@ mvn clean package -DskipTests
java -jar target/quarkus-app/quarkus-run.jar
----
Please, note that the shell running the derby database should react by printing some logs as below:
[source,shell]
----
Booting Derby version The Apache Software Foundation - Apache Derby - 10.16.1.1 - (1901046): instance a816c00e-018a-996e-54bf-00003e718008
on database directory /dbs/my-db with class loader jdk.internal.loader.ClassLoaders$AppClassLoader@5c626da3
Loaded from file:/derby/lib/derby.jar
java.vendor=Eclipse Adoptium
java.runtime.version=17.0.4.1+1
user.dir=/dbs
os.name=Linux
os.arch=amd64
os.version=4.18.0-477.21.1.el8_8.x86_64
derby.system.home=null
derby.stream.error.field=java.lang.System.out
Database Class Loader started - derby.database.classpath=''
----
Beyond that, notice how the application behaves the same way.
The only variation compared to the dev mode is actually that the idempotent repository is now a derby database running in a container.
As mentioned above, `quarkus-flyway` will automatically create the required database and tables for you.
==== Native mode
Expand Down Expand Up @@ -184,12 +142,14 @@ Check pods are running by executing:
kubectl get pods
----
We expect a list of two pods similar to below:
We expect a list of three pods similar to below.
Note that the `camel-quarkus-examples-jpa-idempotent-repository-flyway` pod will transition from `running` to `completed`, after it has completed initializing the MariaDB database.
[source,shell]
----
NAME READY STATUS RESTARTS AGE
camel-quarkus-examples-derby-database-deployment-76f6dc9bdnwwxn 1/1 Running 0 23s
camel-quarkus-examples-mariadb-database-deployment-76f6dc9bdnwwxn 1/1 Running 0 23s
camel-quarkus-examples-jpa-idempotent-repository-flyway-in2q5n5 0/1 Completed 0 23s
camel-quarkus-examples-jpa-idempotent-repository-7c74b9cf5ph68r 1/1 Running 1 (18s ago) 23s
----
Expand All @@ -205,8 +165,8 @@ To clean up do:
[source,shell]
----
kubectl delete all -l app.kubernetes.io/name=camel-quarkus-examples-jpa-idempotent-repository
kubectl delete all -l app.kubernetes.io/name=camel-quarkus-examples-derby-database
kubectl delete configmap -l app.kubernetes.io/name=camel-quarkus-examples-derby-database
kubectl delete all -l job-name=camel-quarkus-examples-jpa-idempotent-repository-flyway-init
kubectl delete all -l app.kubernetes.io/name=camel-quarkus-examples-mariadb-database
----
[NOTE]
Expand Down
15 changes: 10 additions & 5 deletions jpa-idempotent-repository/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,21 @@
<groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-timer</artifactId>
</dependency>
<!-- Note we added a dependency to quarkus-h2 to have an in memory
database during dev mode -->

<!-- Use MariaDB for the database -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-h2</artifactId>
<artifactId>quarkus-jdbc-mariadb</artifactId>
</dependency>
<!-- While in test and prod we use a derby database -->

<!-- Flyway is used to set up the MariaDB database -->
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-jdbc-derby</artifactId>
<artifactId>quarkus-flyway</artifactId>
</dependency>
<dependency>
<groupId>org.flywaydb</groupId>
<artifactId>flyway-mysql</artifactId>
</dependency>

<!-- Test -->
Expand Down
79 changes: 40 additions & 39 deletions jpa-idempotent-repository/src/main/kubernetes/kubernetes.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,77 +18,78 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: camel-quarkus-examples-derby-database-deployment
name: camel-quarkus-examples-mariadb-database-deployment
labels:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
template:
metadata:
labels:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
spec:
containers:
- name: derby-database
# Use a default configured derby database for example purpose, think twice before deploying to production
image: az82/docker-derby:10.16
- name: mariadb-database
image: docker.io/mariadb:10.11
ports:
- containerPort: 1527
- containerPort: 3306
env:
- name: MARIADB_USER
valueFrom:
secretKeyRef:
name: mariadb-secret
key: db-user
- name: MARIADB_PASSWORD
valueFrom:
secretKeyRef:
name: mariadb-secret
key: db-password
- name: MARIADB_DATABASE
value: my-db
- name: MARIADB_RANDOM_ROOT_PASSWORD
value: generate
volumeMounts:
# The /derby-init folder contains the SQL init script to create the database, the table and the sequence
- name: derby-database-init-script-volume
mountPath: /derby-init
# The /dbs folder is where the actual database content is stored
- name: derby-database-data-volume
mountPath: /dbs
lifecycle:
postStart:
# Execute the SQL init script after the derby container has started
exec:
command: ["java", "-Djdbc.drivers=org.apache.derbbc.EmbeddedDriver", "org.apache.derby.tools.ij", "/derby-init/init.sql"]
# The /var/lib/mysql folder is where the actual database content is stored
- name: mariadb-database-data-volume
mountPath: /var/lib/mysql
volumes:
# Create a volume in order to store the SQL init file
- name: derby-database-init-script-volume
configMap:
name: derby-database-init-script-config-map
defaultMode: 0744
# Explicitly create an empty dir volume in order to ensure read/write access needed to store database files
- name: derby-database-data-volume
- name: mariadb-database-data-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
labels:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
name: derby-database
name: mariadb-database
spec:
ports:
- name: derby
port: 1527
targetPort: 1527
- name: mariadb
port: 3306
targetPort: 3306
selector:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
type: ClusterIP
---
apiVersion: v1
kind: ConfigMap
kind: Secret
metadata:
name: derby-database-init-script-config-map
labels:
app.kubernetes.io/name: camel-quarkus-examples-derby-database
app.kubernetes.io/name: camel-quarkus-examples-mariadb-database
app.kubernetes.io/version: 3.7.0-SNAPSHOT
name: mariadb-secret
type: Opaque
data:
init.sql: |
CONNECT 'jdbc:derby:my-db;create=true';
CREATE TABLE CAMEL_MESSAGEPROCESSED ( processorName VARCHAR(255), messageId VARCHAR(100), createdAt TIMESTAMP, PRIMARY KEY (processorName, messageId) );
CREATE SEQUENCE CAMEL_MESSAGEPROCESSED_SEQ AS INT MAXVALUE 999999 CYCLE;
---
# mariadb
db-user: bWFyaWFkYg==
# s3cr3t
db-password: czNjcjN0
Loading

0 comments on commit 7ee831b

Please sign in to comment.