Dev Services
Quarkus supports the automatic provisioning of unconfigured services in dev and test mode. We refer to this capability as Dev Services. From a developer’s perspective this means that if you include an extension and don’t configure it then Quarkus will automatically start the relevant service (usually using Testcontainers behind the scenes) and wire up your application to use this service, even pre-configuring access credentials.
Dev Services will only be enabled in dev/test mode, so it will not affect the application running in production. If you want to disable all Dev Services you can use the quarkus.devservices.enabled=false config property, or you can simply configure the service in which case it will result in the Dev Service being disabled automatically. |
If you are using a proprietary database such as DB2 or MSSQL you will need to accept the license agreement. To do this, create a src/main/resources/container-license-acceptance.txt file in your project and add a line with the image name and tag of the database.
|
More on zero config setup of datasources can be found here.
Replace Database Extensions
Instead of the built-in h2 database, we’re now going to use an external database. Swapping out from one database provider to another is fairly trivial with Quarkus. Let’s start with updating the configuration in the application.properties.
You technically don’t need to add the db-kind property since there is only one jdbc driver in our application. We added it for clarity’s sake. |
# Configuration file
# key = value
greeting=Hello y'all!
quarkus.datasource.db-kind=postgresql
quarkus.hibernate-orm.database.generation=drop-and-create
Make sure the h2 db-kind and jdbc.url properties have been removed. |
Now let’s swap the h2 extension out for the postgresql extension:
./mvnw quarkus:remove-extension -Dextension=quarkus-jdbc-h2
./mvnw quarkus:add-extension -Dextension=quarkus-jdbc-postgresql
quarkus extension remove quarkus-jdbc-h2
quarkus extension add quarkus-jdbc-postgresql
Notice in the logs how Quarkus has reloaded and started up a Postgresql database dev service:
2023-03-16 08:06:56,882 INFO [io.qua.dat.dep.dev.DevServicesDatasourceProcessor] (build-13) Dev Services for the default datasource (postgresql) started - container ID is c7c9a6ccf029
Verify Postgresql testcontainer is running
Let’s verify in Docker/Podman that the dev services container is running. You should see 2 containers, one testcontainers/ryuk container which orchestrates the dev services, and another postgres container which is running the database and which is automatically wired into our Quarkus dev mode:
docker ps
Call the fruit endpoint again. The data is now coming from the postgresql database container.
curl localhost:8080/fruit?season=Spring
[
{
"id": 1,
"name": "Mango",
"season": "Spring"
},
{
"id": 2,
"name": "Strawberry",
"season": "Spring"
}
]
Run Unit Tests with TestContainers
Let’s stop dev mode for now to verify that the Postgres container also stops when we’re done with dev mode by sending a CTRL+C
in the terminal and checking again with docker ps. Notice that the postgres container has disappeared as expected.
docker ps
Run the tests:
./mvnw test
quarkus test
Reminder: Once the tests have run, send CTRL+C
since Quarkus CLI starts tests in continuous mode.
Notice in the logs that Quarkus and TestContainers work in unison to spin up the Postgres container again, run the tests, and then tear down the container again once done.
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.redhat.developers.GreetingResourceTest
2023-07-04 17:40:04,096 INFO [org.tes.doc.DockerClientProviderStrategy] (build-23) Found Docker environment with Environment variables, system properties and defaults. Resolved dockerHost=unix:///run/user/1000/podman/podman.sock
2023-07-04 17:40:04,100 INFO [org.tes.DockerClientFactory] (build-23) Docker host IP address is localhost
2023-07-04 17:40:04,235 INFO [org.tes.DockerClientFactory] (build-23) Connected to docker:
Server Version: 4.5.1
API Version: 1.41
Operating System: fedora
Total Memory: 31787 MB
2023-07-04 17:40:04,254 INFO [org.tes.uti.ImageNameSubstitutor] (build-23) Image name substitution will be performed by: DefaultImageNameSubstitutor (composite of 'ConfigurationFileImageNameSubstitutor' and 'PrefixingImageNameSubstitutor')
2023-07-04 17:40:04,257 INFO [org.tes.DockerClientFactory] (build-23) Checking the system...
2023-07-04 17:40:04,258 INFO [org.tes.DockerClientFactory] (build-23) ✔︎ Docker server version should be at least 1.6.0
2023-07-04 17:40:05,038 INFO [tc.doc.io/postgres:14] (build-23) Creating container for image: docker.io/postgres:14
[Optional] Re-deploy to Kubernetes
If you would like to redeploy to Kubernetes, this time you will need to provision a Postgresql database because as mentioned before, Dev Services are only enabled in dev/test mode.
We will also need to add credentials to connect to the external database. Make sure you have the following properties set:
%prod.quarkus.datasource.password=quarkus
%prod.quarkus.datasource.username=quarkus
%prod.quarkus.datasource.db-kind=postgresql
%prod.quarkus.datasource.jdbc.url=jdbc:postgresql://postgresql/quarkus
quarkus.hibernate-orm.database.generation=drop-and-create
quarkus.hibernate-orm.sql-load-script=import.sql
We added a %prod. prefix to some of the properties. This prefix makes it so these properties will only be evaluated with the (default) prod profile. In dev mode these values will be ignored, thus triggering the Dev Services creation. |
Create a postgresql database
There are several ways to deploy a Postgresql Database to Kubernetes. If you’re using Openshift, you could create one easily through the UI (Developer Perspective > +Add > Database > PostgreSQL). Make sure your database name, username and password match up with what you have configured in your application.properties or secrets.
Alternatively you can also create the following Kubernetes manifest for a simple ephemeral instance:
cat > postgres.yaml << EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: postgresql
spec:
selector:
matchLabels:
app: postgresql
template:
metadata:
labels:
app: postgresql
spec:
containers:
- name: postgresql
image: quay.io/redhatdemo/openshift-pgsql12-primary:centos7
imagePullPolicy: Always
ports:
- name: tcp
containerPort: 5432
env:
- name: PG_USER_PASSWORD
value: quarkus
- name: PG_USER_NAME
value: quarkus
- name: PG_DATABASE
value: quarkus
- name: PG_NETWORK_MASK
value: all
---
kind: Service
apiVersion: v1
metadata:
name: postgresql
spec:
ports:
- name: pgsql
protocol: TCP
port: 5432
targetPort: 5432
type: ClusterIP
selector:
app: postgresql
EOF
And deploy it to Kubernetes:
kubectl apply -f postgres.yaml
Rebuild and deploy your application
Rebuild the application and container, and push to your registry again:
./mvnw clean package -DskipTests -D"quarkus.container-image.push=true"
quarkus image push --also-build --no-tests
And finally, redeploy the application:
kubectl apply -f target/kubernetes/kubernetes.yml