SpringBoot 3.x升级:AQjmsFactory与Jakarta命名空间兼容问题
解决Spring Boot 3.x与Oracle Advanced Queue的JMS兼容问题
针对Spring Boot 3.x升级后,Oracle AQ的AQjmsFactory返回javax.jms.ConnectionFactory与Spring Boot 3.x依赖的jakarta.jms.ConnectionFactory不兼容的问题,提供以下几种可行方案:
方案1:升级至Oracle官方Jakarta兼容版AQ驱动
Oracle从19c开始提供适配Jakarta EE规范的AQ驱动包,替换旧的javax版本依赖即可解决核心兼容问题:
- 更新Maven/Gradle依赖
移除旧的ojdbc(如ojdbc8)和aqapi依赖,替换为支持Jakarta的版本:
<!-- Maven依赖 --> <dependency> <groupId>com.oracle.database.jdbc</groupId> <artifactId>ojdbc11</artifactId> <version>23.3.0.23.09</version> </dependency> <dependency> <groupId>com.oracle.database.jms</groupId> <artifactId>aqapi-jakarta</artifactId> <version>23.3.0.23.09</version> </dependency>
同时确保项目中不再引入javax.jms:jms-api或其他旧版JMS依赖,避免依赖冲突。
- 配置连接工厂
此时AQjmsFactory的静态方法将直接返回jakarta.jms.ConnectionFactory实例,可直接用于Spring Boot的JMS配置:
@Configuration public class AQConfig { @Bean public ConnectionFactory aqConnectionFactory() throws SQLException, JMSException { OracleDataSource dataSource = new OracleDataSource(); dataSource.setURL("jdbc:oracle:thin:@//your-db-host:1521/your-db-service"); dataSource.setUser("db-user"); dataSource.setPassword("db-password"); return AQjmsFactory.getConnectionFactory(dataSource); } }
方案2:自定义适配器桥接javax与jakarta JMS接口
若暂时无法升级Oracle驱动,可通过适配器模式将javax.jms.ConnectionFactory转换为jakarta.jms.ConnectionFactory:
- 编写适配器类
import jakarta.jms.*; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.JMSException; public class JavaxToJakartaConnectionFactoryAdapter implements jakarta.jms.ConnectionFactory { private final ConnectionFactory javaxConnectionFactory; public JavaxToJakartaConnectionFactoryAdapter(ConnectionFactory javaxConnectionFactory) { this.javaxConnectionFactory = javaxConnectionFactory; } @Override public jakarta.jms.Connection createConnection() throws JMSException { Connection javaxConn = javaxConnectionFactory.createConnection(); return new JavaxToJakartaConnectionAdapter(javaxConn); } @Override public jakarta.jms.Connection createConnection(String userName, String password) throws JMSException { Connection javaxConn = javaxConnectionFactory.createConnection(userName, password); return new JavaxToJakartaConnectionAdapter(javaxConn); } // 实现Jakarta ConnectionFactory的默认方法(按需补充) @Override public jakarta.jms.JMSContext createContext() { throw new UnsupportedOperationException("暂未实现"); } // 内部Connection适配器类 private static class JavaxToJakartaConnectionAdapter implements jakarta.jms.Connection { private final Connection javaxConnection; public JavaxToJakartaConnectionAdapter(Connection javaxConnection) { this.javaxConnection = javaxConnection; } @Override public void start() throws JMSException { javaxConnection.start(); } @Override public void stop() throws JMSException { javaxConnection.stop(); } @Override public void close() throws JMSException { javaxConnection.close(); } @Override public jakarta.jms.Session createSession(boolean transacted, int acknowledgeMode) throws JMSException { javax.jms.Session javaxSession = javaxConnection.createSession(transacted, acknowledgeMode); return new JavaxToJakartaSessionAdapter(javaxSession); } // 内部Session适配器类 private static class JavaxToJakartaSessionAdapter implements jakarta.jms.Session { private final javax.jms.Session javaxSession; public JavaxToJakartaSessionAdapter(javax.jms.Session javaxSession) { this.javaxSession = javaxSession; } @Override public void commit() throws JMSException { javaxSession.commit(); } @Override public void rollback() throws JMSException { javaxSession.rollback(); } @Override public jakarta.jms.MessageProducer createProducer(jakarta.jms.Destination destination) throws JMSException { javax.jms.MessageProducer javaxProducer = javaxSession.createProducer((javax.jms.Destination) destination); return new JavaxToJakartaProducerAdapter(javaxProducer); } // 内部Producer适配器类 private static class JavaxToJakartaProducerAdapter implements jakarta.jms.MessageProducer { private final javax.jms.MessageProducer javaxProducer; public JavaxToJakartaProducerAdapter(javax.jms.MessageProducer javaxProducer) { this.javaxProducer = javaxProducer; } @Override public void send(jakarta.jms.Message message) throws JMSException { javaxProducer.send((javax.jms.Message) message); } } } } }
- 在Spring配置中使用适配器
@Configuration public class AQConfig { @Bean public javax.jms.ConnectionFactory javaxAqConnectionFactory() throws SQLException, JMSException { OracleDataSource dataSource = new OracleDataSource(); dataSource.setURL("jdbc:oracle:thin:@//your-db-host:1521/your-db-service"); dataSource.setUser("db-user"); dataSource.setPassword("db-password"); return AQjmsFactory.getConnectionFactory(dataSource); } @Bean public jakarta.jms.ConnectionFactory aqConnectionFactory(javax.jms.ConnectionFactory javaxAqConnectionFactory) { return new JavaxToJakartaConnectionFactoryAdapter(javaxAqConnectionFactory); } }
方案3:结合Spring Boot自动配置扩展
若使用Spring Boot的JMS自动配置,可通过@ConfigurationProperties自定义配置并结合适配器:
@Configuration @EnableConfigurationProperties(AQProperties.class) public class AQAutoConfig { private final AQProperties aqProperties; public AQAutoConfig(AQProperties aqProperties) { this.aqProperties = aqProperties; } @Bean public javax.jms.ConnectionFactory javaxAqConnectionFactory() throws SQLException, JMSException { OracleDataSource dataSource = new OracleDataSource(); dataSource.setURL(aqProperties.getUrl()); dataSource.setUser(aqProperties.getUsername()); dataSource.setPassword(aqProperties.getPassword()); return AQjmsFactory.getConnectionFactory(dataSource); } @Bean public jakarta.jms.ConnectionFactory connectionFactory(javax.jms.ConnectionFactory javaxAqConnectionFactory) { return new JavaxToJakartaConnectionFactoryAdapter(javaxAqConnectionFactory); } } @ConfigurationProperties(prefix = "spring.aq") class AQProperties { private String url; private String username; private String password; // Getters and Setters }
在application.yml中配置:
spring: aq: url: jdbc:oracle:thin:@//your-db-host:1521/your-db-service username: db-user password: db-password
内容的提问来源于stack exchange,提问作者Gajanana Ganjigatti
相关产品推荐
相关产品推荐

