将代理的EntityManager注入资源时,出现IncompatibleClassChangeError

如何解决将代理的EntityManager注入资源时,出现IncompatibleClassChangeError

我正在尝试将EntityManager注入jersey资源和相关的存储库服务中。这个想法是在REST请求的边界启动和提交事务,因此必须使用相同的实体管理器。为此,我使用an operation创建了一个自定义HK2范围@TransactionScope

该应用程序作为Java SE应用程序运行,球衣资源仅是其中的一部分。其他服务在后台运行,通过调度程序或JMS触发,它们也使用相同的作用域。 Java 11,最新版本的jersey,HK2,Eclipselink等。

定义了范围@Proxiable

    @Scope
    @Proxiable(proxyForSameScope = false)
    @Retention(RetentionPolicy.RUNTIME)
    @Target(ElementType.TYPE)
    public @interface TransactionScope { }

使用范围在根服务定位器中注册EntityManager的创建:

    bindFactory(EMFactory.class)
            .to(EntityManager.class)
            .in(TransactionScope.class);

使用EntityManager的存储库服务为@Singleton。这些提供围绕数据库实体的CRUD操作。多亏了代理注入,他们在相同的范围内获得了相同的实体管理器。

想法是:

  1. 在交易边界处,开始HK2操作。对于球衣REST请求,这是通过ContainerRequestFilter实现的;对于后台服务,是运行作业的调度程序,或者是接收JMS消息的消息侦听器。
  2. 球衣资源/计划的作业/消息处理器开始数据库事务entityManager.getTransaction().begin(),然后执行特定的逻辑。
  3. 已注入存储库服务,并为数据库实体提供CRUD操作。
  4. 交易已提交。
  5. HK2操作已关闭。

将实体管理器注入后台服务时,所有这些都可以正常工作。但是,一旦我尝试将其注入到球衣资源中,就会抛出IncompatibleClassChangeError

ERROR c.s.s.e.RuntimeExceptionMapper - Caught A MultiException has 2 exceptions.  They are:
1. java.lang.IncompatibleClassChangeError: class javax.persistence.EntityManager_$$_jvsted_0 has interface javax.persistence.EntityManager as super class
2. java.lang.IllegalArgumentException: While attempting to create a Proxy for javax.persistence.EntityManager in scope com.skalio.rsem.TransactionScope an error occured while creating the proxy
 at org.jvnet.hk2.internal.ProxyUtilities.generateProxy(ProxyUtilities.java:211)

研究此错误后,通常建议检查类路径上是否存在重复和冲突的库。我相信这里不是这种情况(至少我什么也找不到)。

我不能使用@RequestScoped,因为它只能用于球衣资源,而不能用于后台服务。

有什么建议我可以做什么?

更新

我注意到以下工作原理:

  • @TransactionScope被标记为@Unproxiable
  • 通过EntityManager注入javax.inject.Provider

这对我来说可能是前进的方向,即使我发现它不是那么干净。开发人员可能会忘记必须使用提供者注入。

有关依赖项的更新

我已经研究了更多的依赖关系。给我带来一点惊喜:EclipseLink不使用javax.persistence:javax.persistence-api,而是使用org.eclipse.persistence:jakarta.persistence。无论如何,它仍然是包含javax.persistence包的类路径上的唯一位置。

[INFO] +- org.eclipse.persistence:eclipselink:jar:2.7.7:compile
[INFO] |  +- org.eclipse.persistence:jakarta.persistence:jar:2.2.3:compile
[INFO] |  \- org.eclipse.persistence:commonj.sdo:jar:2.1.1:compile
[INFO] +- org.eclipse.persistence:org.eclipse.persistence.jpa.modelgen.processor:jar:2.7.7:provided
[INFO] |  +- org.eclipse.persistence:org.eclipse.persistence.core:jar:2.7.7:provided
[INFO] |  |  \- org.eclipse.persistence:org.eclipse.persistence.asm:jar:2.7.7:provided
[INFO] |  \- org.eclipse.persistence:org.eclipse.persistence.jpa:jar:2.7.7:provided
[INFO] |     +- org.eclipse.persistence:org.eclipse.persistence.antlr:jar:2.7.7:provided
[INFO] |     \- org.eclipse.persistence:org.eclipse.persistence.jpa.jpql:jar:2.7.7:provided

有关服务定位器的更新

由于仅部分代码位于jersey,其余部分位于“后台”,因此我尽可能在“根” ServiceLocator中进行注册。为了提供球衣访问权限,我将定位器从球衣连接到了根定位器。

    // configures the jersey container
    public class ApplicationConfig extends ResourceConfig {

        public ApplicationConfig(ServiceLocator parentLocator) {
    
            // These services need to be registered into jersey's locator
            register(new JerseyContainerBinder());

            // bridge services into jersey
            register(new ServiceLocatorBridge(parentLocator));
        }
    }

JerseyContainerBinder当前为空,我可以使用它来扩展或覆盖根定位符绑定。 ServiceLocatorBridge获取球衣的定位器并将其连接:ExtrasUtilities.bridgeServiceLocator(jerseyLocator,sourceLocator);

因此,这是在背景中注入某些东西与在球衣资源中注入东西之间的区别:它必须首先经过桥。不确定是否重要。啊,如果球衣人只允许重复使用现有的定位器...

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-