Skip to content

Migration Guide

This guide helps you migrate from framework-specific configuration to Forage's unified approach.

Why Migrate to Forage?

Forage solves a fundamental problem: configuration fragmentation across runtimes. Spring Boot and Quarkus use completely different property naming conventions for the same functionality, making it difficult to:

  • Maintain consistent configuration across environments
  • Migrate between runtimes
  • Support multiple databases or message brokers without custom code

Forage provides a single configuration format that works identically across all runtimes.


The Configuration Fragmentation Problem

JDBC Example: Three Different Ways

The same PostgreSQL datasource requires different configuration in each runtime:

spring.datasource.url=jdbc:postgresql://localhost:5432/orders
spring.datasource.username=admin
spring.datasource.password=secret
spring.datasource.driver-class-name=org.postgresql.Driver
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/orders
quarkus.datasource.username=admin
quarkus.datasource.password=secret
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5
quarkus.datasource.jdbc.acquisition-timeout=30
forage.ordersDb.jdbc.db.kind=postgresql
forage.ordersDb.jdbc.url=jdbc:postgresql://localhost:5432/orders
forage.ordersDb.jdbc.username=admin
forage.ordersDb.jdbc.password=secret
forage.ordersDb.jdbc.pool.max.size=20
forage.ordersDb.jdbc.pool.min.size=5
forage.ordersDb.jdbc.pool.acquisition.timeout.seconds=30

Key differences: - Property prefixes: spring.datasource.* vs quarkus.datasource.* vs forage.<name>.jdbc.* - Pool configuration: hikari.* vs jdbc.* vs pool.* - Timeout units: milliseconds vs duration strings vs seconds - Pool implementation: HikariCP vs Agroal vs Agroal (unified)


JDBC Migration

From Spring Boot

Before: Spring Boot Configuration

application.properties:

# Primary datasource
spring.datasource.url=jdbc:postgresql://localhost:5432/orders
spring.datasource.username=admin
spring.datasource.password=secret
spring.datasource.driver-class-name=org.postgresql.Driver

# HikariCP connection pool
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=5
spring.datasource.hikari.connection-timeout=30000
spring.datasource.hikari.idle-timeout=600000
spring.datasource.hikari.max-lifetime=1800000

# Multiple datasources require custom configuration
orders.datasource.url=jdbc:postgresql://localhost:5432/orders
orders.datasource.username=orders_user
orders.datasource.password=orders_pass

analytics.datasource.url=jdbc:mysql://localhost:3306/analytics
analytics.datasource.username=analytics_user
analytics.datasource.password=analytics_pass

DataSourceConfig.java (required for multiple datasources):

@Configuration
public class DataSourceConfig {

    @Bean
    @ConfigurationProperties("orders.datasource")
    public DataSourceProperties ordersDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("orders.datasource.hikari")
    public DataSource ordersDataSource() {
        return ordersDataSourceProperties()
            .initializeDataSourceBuilder()
            .type(HikariDataSource.class)
            .build();
    }

    @Bean
    @ConfigurationProperties("analytics.datasource")
    public DataSourceProperties analyticsDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("analytics.datasource.hikari")
    public DataSource analyticsDataSource() {
        return analyticsDataSourceProperties()
            .initializeDataSourceBuilder()
            .type(HikariDataSource.class)
            .build();
    }
}

After: Forage Configuration

application.properties (all runtimes):

# Orders database - no Java code needed
forage.ordersDb.jdbc.db.kind=postgresql
forage.ordersDb.jdbc.url=jdbc:postgresql://localhost:5432/orders
forage.ordersDb.jdbc.username=orders_user
forage.ordersDb.jdbc.password=orders_pass
forage.ordersDb.jdbc.pool.max.size=20
forage.ordersDb.jdbc.pool.min.size=5
forage.ordersDb.jdbc.pool.acquisition.timeout.seconds=30
forage.ordersDb.jdbc.pool.idle.validation.timeout.minutes=10
forage.ordersDb.jdbc.pool.leak.timeout.minutes=30

# Analytics database - different database type, same pattern
forage.analyticsDb.jdbc.db.kind=mysql
forage.analyticsDb.jdbc.url=jdbc:mysql://localhost:3306/analytics
forage.analyticsDb.jdbc.username=analytics_user
forage.analyticsDb.jdbc.password=analytics_pass
forage.analyticsDb.jdbc.pool.max.size=15

No Java code required - Delete DataSourceConfig.java

Migration Steps

  1. Add Forage dependencies:
<!-- Remove Spring Boot JDBC starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<!-- Add Forage JDBC starter -->
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jdbc-starter</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jdbc-postgresql</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jdbc-mysql</artifactId>
    <version>1.1</version>
</dependency>
  1. Convert properties:
Spring Boot Forage
spring.datasource.url forage.<name>.jdbc.url
spring.datasource.username forage.<name>.jdbc.username
spring.datasource.password forage.<name>.jdbc.password
spring.datasource.hikari.maximum-pool-size forage.<name>.jdbc.pool.max.size
spring.datasource.hikari.minimum-idle forage.<name>.jdbc.pool.min.size
spring.datasource.hikari.connection-timeout (ms) forage.<name>.jdbc.pool.acquisition.timeout.seconds
  1. Delete configuration classes:

Remove all @Configuration classes that create DataSource beans.

  1. Update route references:
// Before
@Autowired
@Qualifier("ordersDataSource")
private DataSource dataSource;

from("timer:query")
    .to("sql:select * from orders?dataSource=#ordersDataSource");
# After
- route:
    from:
      uri: timer:query
      steps:
        - to:
            uri: sql
            parameters:
              query: select * from orders
              dataSource: "#ordersDb"
  1. Test:
mvn spring-boot:run

From Quarkus

Before: Quarkus Configuration

application.properties:

# Primary datasource
quarkus.datasource.db-kind=postgresql
quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/orders
quarkus.datasource.username=admin
quarkus.datasource.password=secret

# Agroal connection pool
quarkus.datasource.jdbc.max-size=20
quarkus.datasource.jdbc.min-size=5
quarkus.datasource.jdbc.acquisition-timeout=30
quarkus.datasource.jdbc.idle-removal-interval=10M
quarkus.datasource.jdbc.max-lifetime=30M

# Multiple datasources use named configuration
quarkus.datasource.orders.db-kind=postgresql
quarkus.datasource.orders.jdbc.url=jdbc:postgresql://localhost:5432/orders
quarkus.datasource.orders.username=orders_user
quarkus.datasource.orders.password=orders_pass
quarkus.datasource.orders.jdbc.max-size=20

quarkus.datasource.analytics.db-kind=mysql
quarkus.datasource.analytics.jdbc.url=jdbc:mysql://localhost:3306/analytics
quarkus.datasource.analytics.username=analytics_user
quarkus.datasource.analytics.password=analytics_pass
quarkus.datasource.analytics.jdbc.max-size=15

After: Forage Configuration

application.properties (all runtimes):

# Orders database
forage.ordersDb.jdbc.db.kind=postgresql
forage.ordersDb.jdbc.url=jdbc:postgresql://localhost:5432/orders
forage.ordersDb.jdbc.username=orders_user
forage.ordersDb.jdbc.password=orders_pass
forage.ordersDb.jdbc.pool.max.size=20
forage.ordersDb.jdbc.pool.min.size=5
forage.ordersDb.jdbc.pool.acquisition.timeout.seconds=30
forage.ordersDb.jdbc.pool.idle.validation.timeout.minutes=10
forage.ordersDb.jdbc.pool.leak.timeout.minutes=30

# Analytics database
forage.analyticsDb.jdbc.db.kind=mysql
forage.analyticsDb.jdbc.url=jdbc:mysql://localhost:3306/analytics
forage.analyticsDb.jdbc.username=analytics_user
forage.analyticsDb.jdbc.password=analytics_pass
forage.analyticsDb.jdbc.pool.max.size=15

Migration Steps

  1. Add Forage dependencies:
<!-- Remove Quarkus JDBC extension -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jdbc-postgresql</artifactId>
</dependency>

<!-- Add Forage Quarkus extension -->
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-quarkus-jdbc-deployment</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jdbc-postgresql</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jdbc-mysql</artifactId>
    <version>1.1</version>
</dependency>
  1. Convert properties:
Quarkus Forage
quarkus.datasource.db-kind forage.<name>.jdbc.db.kind
quarkus.datasource.jdbc.url forage.<name>.jdbc.url
quarkus.datasource.username forage.<name>.jdbc.username
quarkus.datasource.password forage.<name>.jdbc.password
quarkus.datasource.jdbc.max-size forage.<name>.jdbc.pool.max.size
quarkus.datasource.jdbc.min-size forage.<name>.jdbc.pool.min.size
quarkus.datasource.jdbc.acquisition-timeout (duration) forage.<name>.jdbc.pool.acquisition.timeout.seconds
  1. Update route references:
# Before
- route:
    from:
      uri: timer:query
      steps:
        - to:
            uri: sql
            parameters:
              query: select * from orders
              dataSource: "#orders"  # Quarkus named datasource

# After
- route:
    from:
      uri: timer:query
      steps:
        - to:
            uri: sql
            parameters:
              query: select * from orders
              dataSource: "#ordersDb"  # Forage bean name
  1. Test:
mvn quarkus:dev
  1. Build native image:
mvn clean package -Pnative

JMS Migration

From Spring Boot

Before: Spring Boot Configuration

application.properties:

# ActiveMQ Artemis
spring.artemis.mode=native
spring.artemis.host=localhost
spring.artemis.port=61616
spring.artemis.user=admin
spring.artemis.password=secret

# Connection pool
spring.artemis.pool.enabled=true
spring.artemis.pool.max-connections=10
spring.artemis.pool.idle-timeout=30000

# Multiple brokers require custom configuration
primary.artemis.host=broker1.example.com
primary.artemis.port=61616

backup.artemis.host=broker2.example.com
backup.artemis.port=61617

JmsConfig.java (required for multiple brokers):

@Configuration
public class JmsConfig {

    @Bean
    @ConfigurationProperties("primary.artemis")
    public ActiveMQConnectionFactory primaryConnectionFactory() {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL("tcp://broker1.example.com:61616");
        factory.setUser("admin");
        factory.setPassword("secret");
        return factory;
    }

    @Bean
    public JmsTemplate primaryJmsTemplate() {
        return new JmsTemplate(primaryConnectionFactory());
    }

    @Bean
    @ConfigurationProperties("backup.artemis")
    public ActiveMQConnectionFactory backupConnectionFactory() {
        ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
        factory.setBrokerURL("tcp://broker2.example.com:61617");
        factory.setUser("admin");
        factory.setPassword("secret");
        return factory;
    }

    @Bean
    public JmsTemplate backupJmsTemplate() {
        return new JmsTemplate(backupConnectionFactory());
    }
}

After: Forage Configuration

application.properties (all runtimes):

# Primary broker - no Java code needed
forage.primaryBroker.jms.kind=artemis
forage.primaryBroker.jms.broker.url=tcp://broker1.example.com:61616
forage.primaryBroker.jms.username=admin
forage.primaryBroker.jms.password=secret
forage.primaryBroker.jms.pool.max.connections=10
forage.primaryBroker.jms.pool.idle.timeout.millis=30000

# Backup broker - same pattern
forage.backupBroker.jms.kind=artemis
forage.backupBroker.jms.broker.url=tcp://broker2.example.com:61617
forage.backupBroker.jms.username=admin
forage.backupBroker.jms.password=secret
forage.backupBroker.jms.pool.max.connections=10

No Java code required - Delete JmsConfig.java

Migration Steps

  1. Add Forage dependencies:
<!-- Remove Spring Boot JMS starter -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-artemis</artifactId>
</dependency>

<!-- Add Forage JMS starter -->
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jms-starter</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jms-artemis</artifactId>
    <version>1.1</version>
</dependency>
  1. Convert properties:
Spring Boot Forage
spring.artemis.host + port forage.<name>.jms.broker.url (tcp://host:port)
spring.artemis.user forage.<name>.jms.username
spring.artemis.password forage.<name>.jms.password
spring.artemis.pool.max-connections forage.<name>.jms.pool.max.connections
spring.artemis.pool.idle-timeout (ms) forage.<name>.jms.pool.idle.timeout.millis
  1. Delete configuration classes:

Remove all @Configuration classes that create ConnectionFactory beans.

  1. Update route references:
# Before
- route:
    from:
      uri: jms:queue:orders
      parameters:
        connectionFactory: "#primaryConnectionFactory"

# After
- route:
    from:
      uri: jms:queue:orders
      parameters:
        connectionFactory: "#primaryBroker"

From Quarkus

Before: Quarkus Configuration

application.properties:

# ActiveMQ Artemis
quarkus.artemis.url=tcp://localhost:61616
quarkus.artemis.username=admin
quarkus.artemis.password=secret

# Connection pool
quarkus.pooled-jms.max-connections=10
quarkus.pooled-jms.idle-timeout=30s

# Multiple brokers use named configuration
quarkus.artemis.primary.url=tcp://broker1.example.com:61616
quarkus.artemis.primary.username=admin
quarkus.artemis.primary.password=secret

quarkus.artemis.backup.url=tcp://broker2.example.com:61617
quarkus.artemis.backup.username=admin
quarkus.artemis.backup.password=secret

After: Forage Configuration

application.properties (all runtimes):

# Primary broker
forage.primaryBroker.jms.kind=artemis
forage.primaryBroker.jms.broker.url=tcp://broker1.example.com:61616
forage.primaryBroker.jms.username=admin
forage.primaryBroker.jms.password=secret
forage.primaryBroker.jms.pool.max.connections=10
forage.primaryBroker.jms.pool.idle.timeout.millis=30000

# Backup broker
forage.backupBroker.jms.kind=artemis
forage.backupBroker.jms.broker.url=tcp://broker2.example.com:61617
forage.backupBroker.jms.username=admin
forage.backupBroker.jms.password=secret
forage.backupBroker.jms.pool.max.connections=10

Migration Steps

  1. Add Forage dependencies:
<!-- Remove Quarkus Artemis extension -->
<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-artemis-jms</artifactId>
</dependency>

<!-- Add Forage Quarkus extension -->
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-quarkus-jms-deployment</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-jms-artemis</artifactId>
    <version>1.1</version>
</dependency>
  1. Convert properties:
Quarkus Forage
quarkus.artemis.url forage.<name>.jms.broker.url
quarkus.artemis.username forage.<name>.jms.username
quarkus.artemis.password forage.<name>.jms.password
quarkus.pooled-jms.max-connections forage.<name>.jms.pool.max.connections
quarkus.pooled-jms.idle-timeout (duration) forage.<name>.jms.pool.idle.timeout.millis

AI Agent Migration

From Manual LangChain4j Setup

Before: Manual Configuration

AgentConfig.java:

@Configuration
public class AgentConfig {

    @Bean
    public ChatLanguageModel openAiModel() {
        return OpenAiChatModel.builder()
            .apiKey(System.getenv("OPENAI_API_KEY"))
            .modelName("gpt-4")
            .temperature(0.7)
            .build();
    }

    @Bean
    public ChatLanguageModel ollamaModel() {
        return OllamaChatModel.builder()
            .baseUrl("http://localhost:11434")
            .modelName("granite4:3b")
            .build();
    }

    @Bean
    public ChatMemory chatMemory() {
        return MessageWindowChatMemory.withMaxMessages(20);
    }

    @Bean
    public Agent openAiAgent(ChatLanguageModel openAiModel, ChatMemory chatMemory) {
        return Agent.builder()
            .chatLanguageModel(openAiModel)
            .chatMemory(chatMemory)
            .tools(toolRegistry)
            .build();
    }

    @Bean
    public Agent ollamaAgent(ChatLanguageModel ollamaModel) {
        return Agent.builder()
            .chatLanguageModel(ollamaModel)
            .build();
    }
}

After: Forage Configuration

application.properties (all runtimes):

# OpenAI agent with memory
forage.openAiAgent.agent.model.kind=openai
forage.openAiAgent.agent.model.name=gpt-4
forage.openAiAgent.agent.api.key=${OPENAI_API_KEY}
forage.openAiAgent.agent.temperature=0.7
forage.openAiAgent.agent.features=memory
forage.openAiAgent.agent.memory.kind=message-window
forage.openAiAgent.agent.memory.max.messages=20

# Ollama agent (memoryless)
forage.ollamaAgent.agent.model.kind=ollama
forage.ollamaAgent.agent.model.name=granite4:3b
forage.ollamaAgent.agent.base.url=http://localhost:11434
forage.ollamaAgent.agent.features=memoryless

No Java code required - Delete AgentConfig.java

Migration Steps

  1. Add Forage dependencies:
<!-- Add Forage agent dependencies -->
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-agent</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-model-open-ai</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-model-ollama</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>io.kaoto.forage</groupId>
    <artifactId>forage-memory-message-window</artifactId>
    <version>1.1</version>
</dependency>
  1. Convert configuration:
Manual Setup Forage
OpenAiChatModel.builder().apiKey() forage.<name>.agent.api.key
OpenAiChatModel.builder().modelName() forage.<name>.agent.model.name
OpenAiChatModel.builder().temperature() forage.<name>.agent.temperature
OllamaChatModel.builder().baseUrl() forage.<name>.agent.base.url
MessageWindowChatMemory.withMaxMessages() forage.<name>.agent.memory.max.messages
  1. Update route references:
# Before
- route:
    from:
      uri: timer:chat
      steps:
        - to:
            uri: langchain4j-agent:chat
            parameters:
              agent: "#openAiAgent"  # Bean from @Configuration

# After
- route:
    from:
      uri: timer:chat
      steps:
        - to:
            uri: langchain4j-agent:chat
            parameters:
              agent: "#openAiAgent"  # Bean from Forage

Configuration Comparison Tables

JDBC Configuration

Aspect Spring Boot Quarkus Forage (All Runtimes)
Property prefix spring.datasource.* quarkus.datasource.* forage.<name>.jdbc.*
Database kind driver-class-name db-kind db.kind
Pool max size hikari.maximum-pool-size jdbc.max-size pool.max.size
Pool min size hikari.minimum-idle jdbc.min-size pool.min.size
Timeout format Milliseconds Duration string Seconds (consistent)
Multiple datasources Custom @Configuration Named config Named config (no code)
Pool implementation HikariCP Agroal Agroal (all runtimes)

JMS Configuration

Aspect Spring Boot Quarkus Forage (All Runtimes)
Property prefix spring.artemis.* quarkus.artemis.* forage.<name>.jms.*
Connection URL host + port url broker.url (consistent)
Pool max pool.max-connections pooled-jms.max-connections pool.max.connections
Timeout format Milliseconds Duration string Milliseconds (consistent)
Multiple brokers Custom @Configuration Named config Named config (no code)

Real-World Example: Multi-Database Application

Scenario

An organization has: - Development: Camel JBang (manual bean creation) - Staging: Spring Boot (HikariCP, custom configuration) - Production: Quarkus (Agroal, native compilation)

Each environment requires different configuration files and code.

Before: Three Different Configurations

// Manual bean creation
DataSource ordersDb = createDataSource(
    "jdbc:postgresql://localhost:5432/orders",
    "admin", "secret");

DataSource analyticsDb = createDataSource(
    "jdbc:mysql://localhost:3306/analytics",
    "admin", "secret");

camelContext.getRegistry().bind("ordersDb", ordersDb);
camelContext.getRegistry().bind("analyticsDb", analyticsDb);
spring.datasource.orders.url=jdbc:postgresql://staging-db:5432/orders
spring.datasource.orders.username=staging_user
spring.datasource.orders.password=staging_pass
spring.datasource.orders.hikari.maximum-pool-size=20

spring.datasource.analytics.url=jdbc:mysql://staging-db:3306/analytics
spring.datasource.analytics.username=staging_user
spring.datasource.analytics.password=staging_pass
spring.datasource.analytics.hikari.maximum-pool-size=15
@Configuration
public class DataSourceConfig {
    @Bean
    public DataSource ordersDb() { ... }

    @Bean
    public DataSource analyticsDb() { ... }
}
quarkus.datasource.orders.db-kind=postgresql
quarkus.datasource.orders.jdbc.url=jdbc:postgresql://prod-db:5432/orders
quarkus.datasource.orders.username=prod_user
quarkus.datasource.orders.password=prod_pass
quarkus.datasource.orders.jdbc.max-size=20

quarkus.datasource.analytics.db-kind=mysql
quarkus.datasource.analytics.jdbc.url=jdbc:mysql://prod-db:3306/analytics
quarkus.datasource.analytics.username=prod_user
quarkus.datasource.analytics.password=prod_pass
quarkus.datasource.analytics.jdbc.max-size=15

After: Single Unified Configuration

application.properties (all environments):

# Orders database (PostgreSQL)
forage.ordersDb.jdbc.db.kind=postgresql
forage.ordersDb.jdbc.url=jdbc:postgresql://${DB_HOST:localhost}:5432/orders
forage.ordersDb.jdbc.username=${ORDERS_USER:admin}
forage.ordersDb.jdbc.password=${ORDERS_PASS:secret}
forage.ordersDb.jdbc.pool.max.size=20

# Analytics database (MySQL)
forage.analyticsDb.jdbc.db.kind=mysql
forage.analyticsDb.jdbc.url=jdbc:mysql://${DB_HOST:localhost}:3306/analytics
forage.analyticsDb.jdbc.username=${ANALYTICS_USER:admin}
forage.analyticsDb.jdbc.password=${ANALYTICS_PASS:secret}
forage.analyticsDb.jdbc.pool.max.size=15

# Inventory database (Oracle)
forage.inventoryDb.jdbc.db.kind=oracle
forage.inventoryDb.jdbc.url=jdbc:oracle:thin:@${DB_HOST:localhost}:1521:inventory
forage.inventoryDb.jdbc.username=${INVENTORY_USER:admin}
forage.inventoryDb.jdbc.password=${INVENTORY_PASS:secret}
forage.inventoryDb.jdbc.pool.max.size=10

Environment-specific values via environment variables:

# Development
export DB_HOST=localhost
export ORDERS_USER=dev_user
export ORDERS_PASS=dev_pass

# Staging
export DB_HOST=staging-db
export ORDERS_USER=staging_user
export ORDERS_PASS=staging_pass

# Production
export DB_HOST=prod-db
export ORDERS_USER=prod_user
export ORDERS_PASS=prod_pass

Benefits:

  • Same configuration file across all environments
  • Environment-specific values via environment variables
  • No code changes when switching runtimes
  • Consistent pool behavior across dev/staging/prod
  • Easy to add new databases without code changes

Getting Help

If you encounter issues during migration:

  1. Check the troubleshooting guide:
  2. Troubleshooting

  3. Review examples:

  4. JDBC Examples
  5. JMS Examples
  6. AI Agent Examples

  7. Ask for help:

  8. GitHub Discussions
  9. Include your current configuration and target runtime

  10. Report migration issues:

  11. Create an issue
  12. Tag with migration label