You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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版本依赖即可解决核心兼容问题:

  1. 更新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依赖,避免依赖冲突。

  1. 配置连接工厂
    此时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:

  1. 编写适配器类
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);
                }
            }
        }
    }
}
  1. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 09:14:58