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

如何在Jakarta EE 9中创建适配微服务的合规JCA资源适配器(.rar)

构建Jakarta EE 9兼容的JCA资源适配器(RAR)连接内存数据网格

以下是适配微服务场景、符合Jakarta EE 9规范的JCA资源适配器构建步骤,基于JCA 2.0规范(Jakarta EE 9对应的JCA版本):

一、核心组件梳理

JCA适配器必须包含以下核心组件,缺一不可:

  • ManagedConnectionFactory:核心工厂类,负责创建与内存数据网格的物理连接实例,处理地址、认证等配置参数
  • ManagedConnection:管理物理连接的生命周期,封装与内存数据网格的实际交互逻辑
  • ConnectionFactory:暴露给业务代码的客户端接口,用于获取连接实例
  • Connection:业务层直接调用的连接接口,封装内存数据网格的操作(如get/put)
  • ResourceAdapter:适配器入口,定义启动、停止等生命周期回调
  • ra.xml:部署描述符,声明适配器元数据、组件映射、默认配置

二、代码实现步骤

1. 依赖配置(Maven示例)

使用Jakarta EE 9命名空间的依赖,同时引入目标内存数据网格的客户端SDK:

<dependencies>
    <!-- Jakarta JCA 2.0 API -->
    <dependency>
        <groupId>jakarta.resource</groupId>
        <artifactId>jakarta.resource-api</artifactId>
        <version>2.0.0</version>
        <scope>provided</scope>
    </dependency>
    <!-- 以Hazelcast内存网格为例,替换为你的目标网格客户端 -->
    <dependency>
        <groupId>com.hazelcast</groupId>
        <artifactId>hazelcast</artifactId>
        <version>5.3.6</version>
        <scope>compile</scope>
    </dependency>
</dependencies>

2. 核心组件代码实现

(1)定义业务层接口

封装内存数据网格的操作,让业务代码无需感知底层实现:

// 业务层使用的连接接口
public interface IMDGConnection {
    Object get(String key);
    void put(String key, Object value);
    void close();
}

// 连接工厂接口
public interface IMDGConnectionFactory {
    IMDGConnection getConnection() throws ResourceException;
}

(2)实现ManagedConnectionFactory

处理配置参数,创建物理连接实例:

import jakarta.resource.annotation.ConnectionFactoryDefinition;
import jakarta.resource.annotation.ConnectionFactoryDefinitions;
import jakarta.resource.ResourceException;
import jakarta.resource.spi.ManagedConnection;
import jakarta.resource.spi.ManagedConnectionFactory;
import jakarta.resource.spi.ConnectionManager;
import java.io.Serializable;

@ConnectionFactoryDefinitions({
    @ConnectionFactoryDefinition(
        name = "java:/IMDGConnectionFactory",
        interfaceName = "com.example.IMDGConnectionFactory",
        resourceAdapter = "imdg-ra"
    )
})
public class IMDGManagedConnectionFactory implements ManagedConnectionFactory, Serializable {
    // 可配置的内存网格地址参数
    private String imdgServerAddress = "localhost:5701";

    @Override
    public Object createConnectionFactory(ConnectionManager cm) throws ResourceException {
        return cm.createConnectionFactory(this);
    }

    @Override
    public ManagedConnection createManagedConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException {
        // 创建物理连接实例
        return new IMDGManagedConnection(imdgServerAddress);
    }

    // 实现equals、hashCode,以及getter/setter方法
    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        IMDGManagedConnectionFactory that = (IMDGManagedConnectionFactory) obj;
        return imdgServerAddress.equals(that.imdgServerAddress);
    }

    @Override
    public int hashCode() {
        return imdgServerAddress.hashCode();
    }

    public String getImdgServerAddress() {
        return imdgServerAddress;
    }

    public void setImdgServerAddress(String imdgServerAddress) {
        this.imdgServerAddress = imdgServerAddress;
    }
}

(3)实现ManagedConnection

管理物理连接的生命周期,处理会话:

import com.hazelcast.client.HazelcastClient;
import com.hazelcast.client.config.ClientConfig;
import com.hazelcast.core.HazelcastInstance;
import jakarta.resource.ResourceException;
import jakarta.resource.spi.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

public class IMDGManagedConnection implements ManagedConnection {
    private final HazelcastInstance hazelcastInstance;
    private final List<IMDGConnection> connectionHandles = new ArrayList<>();
    private final ConnectionEventSupport eventSupport = new ConnectionEventSupport(this);

    public IMDGManagedConnection(String serverAddress) {
        // 初始化与内存网格的物理连接
        ClientConfig config = new ClientConfig();
        config.getNetworkConfig().addAddress(serverAddress);
        this.hazelcastInstance = HazelcastClient.newHazelcastClient(config);
    }

    @Override
    public Object getConnection(Subject subject, ConnectionRequestInfo cri) throws ResourceException {
        // 创建业务层连接句柄
        IMDGConnection connection = new IMDGConnectionImpl(this);
        connectionHandles.add(connection);
        return connection;
    }

    @Override
    public void cleanup() throws ResourceException {
        // 回收业务层连接句柄,保留物理连接
        connectionHandles.clear();
    }

    @Override
    public void destroy() throws ResourceException {
        // 关闭物理连接
        hazelcastInstance.shutdown();
    }

    @Override
    public void addConnectionEventListener(ConnectionEventListener listener) {
        eventSupport.addConnectionEventListener(listener);
    }

    @Override
    public void removeConnectionEventListener(ConnectionEventListener listener) {
        eventSupport.removeConnectionEventListener(listener);
    }

    // 暴露给业务层连接的操作方法
    public Object get(String key) {
        return hazelcastInstance.getMap("default").get(key);
    }

    public void put(String key, Object value) {
        hazelcastInstance.getMap("default").put(key, value);
    }

    // 其他接口方法实现(如getLogWriter、setLogWriter等)
    @Override
    public void setLogWriter(java.io.PrintWriter out) throws ResourceException {}

    @Override
    public java.io.PrintWriter getLogWriter() throws ResourceException { return null; }

    @Override
    public XAResource getXAResource() throws ResourceException { return null; }

    @Override
    public LocalTransaction getLocalTransaction() throws ResourceException { return null; }

    @Override
    public ManagedConnectionMetaData getMetaData() throws ResourceException { return null; }
}

(4)实现业务层连接句柄

封装物理连接的调用,处理关闭逻辑:

public class IMDGConnectionImpl implements IMDGConnection {
    private final IMDGManagedConnection managedConnection;
    private boolean closed = false;

    public IMDGConnectionImpl(IMDGManagedConnection managedConnection) {
        this.managedConnection = managedConnection;
    }

    @Override
    public Object get(String key) {
        checkClosed();
        return managedConnection.get(key);
    }

    @Override
    public void put(String key, Object value) {
        checkClosed();
        managedConnection.put(key, value);
    }

    @Override
    public void close() {
        if (!closed) {
            closed = true;
            managedConnection.cleanup();
        }
    }

    private void checkClosed() {
        if (closed) {
            throw new IllegalStateException("Connection has been closed");
        }
    }
}

(5)实现ResourceAdapter

定义适配器的生命周期回调:

import jakarta.resource.ResourceAdapterInternalException;
import jakarta.resource.spi.BootstrapContext;
import jakarta.resource.spi.ResourceAdapter;
import jakarta.resource.spi.endpoint.MessageEndpointFactory;
import java.io.Serializable;

public class IMDGResourceAdapter implements ResourceAdapter, Serializable {
    @Override
    public void start(BootstrapContext ctx) throws ResourceAdapterInternalException {
        // 适配器启动时的初始化逻辑,如加载全局配置
    }

    @Override
    public void stop() {
        // 适配器停止时的清理逻辑
    }

    // 其他接口方法实现(适配消息驱动场景,若仅用于连接则返回空实现)
    @Override
    public void endpointActivation(MessageEndpointFactory factory, ActivationSpec spec) throws ResourceException {}

    @Override
    public void endpointDeactivation(MessageEndpointFactory factory, ActivationSpec spec) {}

    @Override
    public XAResource[] getXAResources(ActivationSpec[] specs) throws ResourceException { return new XAResource[0]; }
}

3. 编写部署描述符ra.xml

放在src/main/resources/META-INF目录下,符合Jakarta EE 9规范:

<?xml version="1.0" encoding="UTF-8"?>
<connector xmlns="https://jakarta.ee/xml/ns/jakartaee"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xsi:schemaLocation="https://jakarta.ee/xml/ns/jakartaee https://jakarta.ee/xml/ns/jakartaee/connector_2_0.xsd"
           version="2.0">
    <display-name>IMDG Resource Adapter</display-name>
    <vendor-name>Example Corp</vendor-name>
    <eis-type>In-Memory Data Grid</eis-type>

    <resourceadapter>
        <resourceadapter-class>com.example.IMDGResourceAdapter</resourceadapter-class>
        <managedconnectionfactory-class>com.example.IMDGManagedConnectionFactory</managedconnectionfactory-class>

        <config-property>
            <config-property-name>imdgServerAddress</config-property-name>
            <config-property-type>java.lang.String</config-property-type>
            <config-property-value>localhost:5701</config-property-value>
        </config-property>

        <connection-definition>
            <managedconnectionfactory-class>com.example.IMDGManagedConnectionFactory</managedconnectionfactory-class>
            <connectionfactory-interface>com.example.IMDGConnectionFactory</connectionfactory-interface>
            <connection-interface>com.example.IMDGConnection</connection-interface>
        </connection-definition>
    </resourceadapter>
</connector>

三、微服务场景适配要点

  • 轻量打包:剔除冗余依赖,使用内存网格的轻量客户端版本,控制RAR体积
  • 配置外置化:支持通过环境变量、Kubernetes ConfigMap等覆盖ra.xml中的配置,适配动态部署
  • 健康检查:在ResourceAdapter的start方法中添加连接校验逻辑,或暴露健康检查端点,配合微服务治理平台做存活探针
  • 连接池优化:配置合理的连接池参数(最大连接数、空闲超时),适配微服务短连接、高并发的特点
  • 可观察性:集成SLF4J日志、Micrometer指标,监控连接状态与操作性能

四、打包与测试

1. 打包RAR

使用Maven的maven-rar-plugin打包:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-rar-plugin</artifactId>
            <version>3.0.0</version>
            <executions>
                <execution>
                    <goals>
                        <goal>rar</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

执行mvn package生成target/imdg-ra.rar

2. 部署测试

  • 在Jakarta EE 9兼容的服务器(如Payara 6、WildFly 26+)部署RAR
  • 在微服务中注入连接工厂并测试:
import jakarta.ejb.Stateless;
import jakarta.annotation.Resource;
import jakarta.resource.ResourceException;

@Stateless
public class IMDGService {
    @Resource(lookup = "java:/IMDGConnectionFactory")
    private IMDGConnectionFactory connectionFactory;

    public void storeData(String key, Object value) throws ResourceException {
        try (IMDGConnection conn = connectionFactory.getConnection()) {
            conn.put(key, value);
        }
    }

    public Object retrieveData(String key) throws ResourceException {
        try (IMDGConnection conn = connectionFactory.getConnection()) {
            return conn.get(key);
        }
    }
}

内容的提问来源于stack exchange,提问作者Tarun Patel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 21:10:38