Dev Services

Quarkus supports the automatic provisioning of unconfigured services in development 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. We just remove the h2 extension and add the postgresql extension instead:

  • Maven

  • Quarkus CLI

mvn quarkus:remove-extension -Dextension=quarkus-jdbc-h2
mvn quarkus:add-extension -Dextension=quarkus-jdbc-postgresql
quarkus extension remove quarkus-jdbc-h2
quarkus extension add quarkus-jdbc-postgresql

Update configuration

We’ll also need to update the configuration and change h2 to postgresql:

Technically you don’t need to add the db-kind property since there is only one jdbc driver in this case. 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

You will now see that Quarkus has reloaded and started up a Postgresql database dev service:

--
Checking Docker Environment
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

You can now also verify/access the dev services container via Docker or Podman:

docker ps
Dev Services Container

You can check to see that the fruit endpoint is still working, but in this case the data is coming from the postgresql database.

curl localhost:8080/fruit?season=Spring
[
  {
    "id": 1,
    "name": "Mango",
    "season": "Spring"
  },
  {
    "id": 2,
    "name": "Strawberry",
    "season": "Spring"
  }
]

[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 property 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). Just make sure your database name, username and password match up with what you have configured in your application.properties or secrets.

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:

  • Maven

  • Quarkus CLI

mvn clean package -DskipTests -Dquarkus.container-image.push=true
quarkus image push --also-build --no-tests

And finally, redeploy the application:

kubectl apply -f target/kubernetes/kubernetes.yml