Skip to content

JDBC

Forage creates pooled datasources with connection management, optional XA transactions, and auxiliary repositories.

Quick Start

forage.myDb.jdbc.db.kind=postgresql
forage.myDb.jdbc.url=jdbc:postgresql://localhost:5432/mydb
forage.myDb.jdbc.username=admin
forage.myDb.jdbc.password=secret
- to:
    uri: sql
    parameters:
      query: select * from orders
      dataSource: "#myDb"

Supported Databases

Name Description
postgresql PostgreSQL database
db2 IBM DB2 database
h2 H2 database
hsqldb HSQLDB database
mariadb MariaDB database
mssql Microsoft SQL Server database
mysql MySQL database
oracle Oracle database

Properties

Property Description Type Default Required
forage.jdbc.db.kind The database kind/type bean-name Yes
forage.jdbc.url The JDBC connection URL string Yes
forage.jdbc.transaction.enabled Enable transaction management boolean false
forage.jdbc.aggregation.repository.enabled Enable aggregation repository (requires transactions to be enabled) boolean false
forage.jdbc.idempotent.repository.enabled Enable idempotent repository boolean false
forage.jdbc.idempotent.repository.table.name Table name for idempotent repository string

Security

Property Description Type Default Required
forage.jdbc.username The database username string Yes
forage.jdbc.password The database password password Yes

Advanced

Property Description Type Default Required
forage.jdbc.pool.initial.size Initial size of the connection pool integer 5
forage.jdbc.pool.min.size Minimum size of the connection pool integer 2
forage.jdbc.pool.max.size Maximum size of the connection pool integer 20
forage.jdbc.pool.acquisition.timeout.seconds Timeout for acquiring a connection from the pool (seconds) integer 5
forage.jdbc.pool.validation.timeout.seconds Timeout for validating a connection (seconds) integer 3
forage.jdbc.pool.leak.timeout.minutes Timeout for detecting connection leaks (minutes) integer 10
forage.jdbc.pool.idle.validation.timeout.minutes Timeout for validating idle connections (minutes) integer 3
forage.jdbc.transaction.timeout.seconds Timeout for transactions (seconds) integer 30
forage.jdbc.transaction.node.id The transaction node identifier string
forage.jdbc.transaction.object.store.id The transaction object store identifier string
forage.jdbc.transaction.enable.recovery Enable transaction recovery boolean false
forage.jdbc.transaction.recovery.period.seconds Interval between periodic transaction recovery scans, in seconds integer 120
forage.jdbc.transaction.recovery.backoff.seconds Delay between the first and second pass of a recovery scan, in seconds integer 10
forage.jdbc.transaction.recovery.modules Comma-separated list of transaction recovery modules string
forage.jdbc.transaction.expiry.scanners Comma-separated list of transaction expiry scanners string com.arjuna.ats.internal.arjuna.recovery.ExpiredTransactionStatusManagerScanner
forage.jdbc.transaction.xa.resource.orphan.filters Comma-separated list of XA resource orphan filters string
forage.jdbc.transaction.object.store.directory Directory for transaction object store string ObjectStore
forage.jdbc.transaction.object.store.type Type of transaction object store (file-system or jdbc) string file-system
forage.jdbc.transaction.object.store.datasource DataSource name for JDBC object store string
forage.jdbc.transaction.object.store.create.table Create object store table if not exists boolean false
forage.jdbc.transaction.object.store.drop.table Drop object store table on shutdown boolean false
forage.jdbc.transaction.object.store.table.prefix Prefix for object store tables string forage_
forage.jdbc.aggregation.repository.name Name of the aggregation repository string
forage.jdbc.aggregation.repository.headers.to.store Comma-separated list of headers to store string
forage.jdbc.aggregation.repository.store.body Store message body in repository boolean
forage.jdbc.aggregation.repository.dead.letter.uri Dead letter queue URI for failed aggregations string
forage.jdbc.aggregation.repository.allow.serialized.headers Allow serialized headers in repository boolean
forage.jdbc.aggregation.repository.maximum.redeliveries Maximum number of redelivery attempts integer
forage.jdbc.aggregation.repository.use.recovery Enable recovery for aggregation repository boolean
forage.jdbc.aggregation.repository.propagation.behaviour.name Transaction propagation behaviour name string
forage.jdbc.idempotent.repository.table.create Create idempotent table if not exists boolean true
forage.jdbc.idempotent.repository.processor.name Processor name for idempotent repository string

Unknown db.kind

Setting an unrecognized db.kind value now fails at startup with an error listing the available providers, instead of producing a NullPointerException later.

Multiple Datasources

Use different names to configure multiple databases:

forage.ordersDb.jdbc.db.kind=postgresql
forage.ordersDb.jdbc.url=jdbc:postgresql://db1:5432/orders

forage.analyticsDb.jdbc.db.kind=mysql
forage.analyticsDb.jdbc.url=jdbc:mysql://db2:3306/analytics

XA Transactions

Setting forage.jdbc.transaction.enabled=true switches the module to XA mode: the Agroal pool enlists connections in the Narayana transaction manager (initialized from the forage.jdbc.transaction.* properties), and JTA transaction policies (PROPAGATION_REQUIRED, REQUIRES_NEW, ...) are registered for use with the transacted EIP.

Crash Recovery

If the application crashes between the prepare and commit phase of an XA transaction, the transaction branch is left in doubt on the database until someone resolves it. Setting forage.jdbc.transaction.enable.recovery=true makes Forage run Narayana's periodic recovery in-process:

  • A recovery manager is started once per JVM (shared with the JMS module) as soon as the first XA-enabled datasource is created, and stopped when the Camel context stops (or the Spring application context closes).
  • Every XA-enabled datasource — including named/prefixed ones — is registered with the recovery manager through Agroal's Narayana integration, so Narayana can obtain fresh connections and resolve in-doubt branches after a restart.
  • Every forage.jdbc.transaction.recovery.period.seconds (default 120) a recovery scan replays the transaction log: branches whose commit decision was recorded are committed, unresolved prepared branches are rolled back once the orphan filters approve.

For recovery to work across restarts:

  • The object store must be persistent and stable. forage.jdbc.transaction.object.store.directory defaults to ObjectStore, resolved against the process working directory — in production point it to an absolute path on durable storage, and make sure the restarted instance uses the same directory.
  • forage.jdbc.transaction.node.id must be stable and unique per node. Narayana tags every transaction branch with it; a restarted instance only recovers branches created under the same node id, and two nodes sharing an id would steal each other's transactions.

With forage.jdbc.transaction.enable.recovery=false (the default) no recovery thread is started.

Quarkus

On Quarkus, recovery is owned by the quarkus-narayana-jta extension: Forage translates enable.recovery, the object store settings, and the node id to the corresponding quarkus.transaction-manager.* properties. The recovery scan interval is not configurable through Quarkus properties — use the Narayana system property -DRecoveryEnvironmentBean.periodicRecoveryPeriod=<seconds> if you need to change it.