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
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¶
- 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>
- 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 |
- Delete configuration classes:
Remove all @Configuration classes that create DataSource beans.
- 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"
- Test:
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¶
- 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>
- 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 |
- 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
- Test:
- Build native image:
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¶
- 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>
- 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 |
- Delete configuration classes:
Remove all @Configuration classes that create ConnectionFactory beans.
- 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¶
- 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>
- 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¶
- 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>
- 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 |
- 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
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:
- Check the troubleshooting guide:
-
Review examples:
- JDBC Examples
- JMS Examples
-
Ask for help:
- GitHub Discussions
-
Include your current configuration and target runtime
-
Report migration issues:
- Create an issue
- Tag with
migrationlabel