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

com.caucho:resin:4.0.66与jakarta.persistence-api:2.2.3兼容问题及NPE求助

问题分析与解决方案

问题根源

使用com.caucho:resin:4.0.66搭配jakarta.persistence:jakarta.persistence-api:2.2.3时,com.caucho.amber.manager.AmberPersistenceProvider的getProviderUtil()方法未完成实现,直接返回null。当Apache BVal的JPATraversableResolver调用javax.persistence.Persistence$PersistenceUtilImpl.isLoaded()时,因provider.getProviderUtil()为null触发NullPointerException(NPE),栈跟踪信息如下:

Caused by: java.lang.NullPointerException
at javax.persistence.Persistence$PersistenceUtilImpl.isLoaded(Persistence.java:145)
at org.apache.bval.jsr303.resolver.JPATraversableResolver.isReachable(JPATraversableResolver.java:34)
at org.apache.bval.jsr303.resolver.DefaultTraversableResolver.isReachable(DefaultTraversableResolver.java:60)
at org.apache.bval.jsr303.resolver.CachingTraversableResolver.isReachable(CachingTraversableResolver.java:82)
at org.apache.bval.jsr303.ConstraintValidation.isReachable(ConstraintValidation.java:241)
... 37 more

触发NPE的核心代码(PersistenceUtilImpl.isLoaded):

for (PersistenceProvider provider : providers) {
    LoadState loadstate = provider.getProviderUtil().isLoadedWithoutReference(entity, attributeName); <<== LINE 145
    if(loadstate == LoadState.LOADED) {
        return true;
    } else if (loadstate == LoadState.NOT_LOADED) {
        return false;
    } // else continue
}

AmberPersistenceProvider的未实现方法:

@Override
public ProviderUtil getProviderUtil()
{
    // TODO Auto-generated method stub
    return null;
}

可行解决方案

1. 自定义PersistenceProvider包装类

实现代理类包装AmberPersistenceProvider,重写getProviderUtil()返回合法的ProviderUtil实例:

public class FixedAmberPersistenceProvider implements PersistenceProvider {
    private final PersistenceProvider delegate;

    public FixedAmberPersistenceProvider(PersistenceProvider delegate) {
        this.delegate = delegate;
    }

    // 代理其他所有PersistenceProvider方法,直接调用delegate对应实现
    @Override
    public EntityManagerFactory createEntityManagerFactory(String emName, Map map) {
        return delegate.createEntityManagerFactory(emName, map);
    }

    // 其余PersistenceProvider方法同理代理...

    @Override
    public ProviderUtil getProviderUtil() {
        return new ProviderUtil() {
            @Override
            public LoadState isLoadedWithoutReference(Object entity, String attributeName) {
                // 默认返回UNKNOWN,让遍历逻辑继续;也可根据Amber的实体加载逻辑自定义实现
                return LoadState.UNKNOWN;
            }

            @Override
            public LoadState isLoadedWithReference(Object entity, String attributeName) {
                return LoadState.UNKNOWN;
            }

            @Override
            public LoadState isLoaded(Object entity) {
                return LoadState.UNKNOWN;
            }
        };
    }
}

通过SPI机制替换原实现:在项目的META-INF/services/javax.persistence.spi.PersistenceProvider文件中,写入自定义类的全限定名,替换原com.caucho.amber.manager.AmberPersistenceProvider。

2. 替换Apache BVal的TraversableResolver

修改BVal配置,禁用依赖JPA的JPATraversableResolver,改用默认解析器:

  • 在bval.properties配置文件中添加:
org.apache.bval.jsr303.traversableResolver=org.apache.bval.jsr303.resolver.DefaultTraversableResolver

也可以自定义一个不依赖JPA的TraversableResolver实现,彻底避免调用PersistenceUtil.isLoaded()方法。

3. 升级Resin或更换JPA实现

  • 检查Resin 4.0.x后续版本(如4.0.67及以上)是否修复了Amber的getProviderUtil()未实现问题;
  • 若无法升级Resin,可替换JPA实现为Hibernate、EclipseLink等成熟框架,这些实现均正确完成了getProviderUtil()方法的实现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:32:56