类加载服务器部署的持久性单元

时间:2016-01-29 15:35:53

标签: java classloader wildfly

我在EAR包中遇到问题,该包在EJB模块中包含服务器部署的持久性单元,在WAR模块中包含Web应用程序

EAR
 |--- persistence unit (EJB module) 
 |--- web app (WAR)
 ...

一切都在编译,部署(在WildFly 10 CR5下)成功执行。正确部署了persistnce单元并创建了模式(在开发期间使用Hibernate模式生成)。

但是,当我试图坚持这样的实体之一时

MyEntitiy e = new MyEntitiy();
e.setId(UUID.randomUUID().toString());
e.setName("name");
entityService.save(e);

我遇到运行时错误,根本原因是:

Caused by: java.lang.IllegalArgumentException: Can not set java.lang.String field x.y.z.MyEntity.id to x.y.z.MyEntity
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(UnsafeFieldAccessorImpl.java:58)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.get(UnsafeObjectFieldAccessorImpl.java:36)
    at java.lang.reflect.Field.get(Field.java:393)
    at org.hibernate.property.access.spi.GetterFieldImpl.get(GetterFieldImpl.java:39)

潜入调试器,我追溯到方法sun.reflect.UnsafeFieldAccessorImpl.ensureObj,它通过类之间的方法Class.isAssignableFrom执行检查

  1. Field对象(Field.getDeclaredClass()
  2. 的类
  3. 要保留的实体的类
  4. 此检查返回false,因为to classes已加载了不同的ClassLoader s(它们在逻辑上是同一个类)。

    如何在不更改项目的一般情况的情况下克服此问题(即,将持久性单元保持为EJB模块以在各个模块之间共享)?

1 个答案:

答案 0 :(得分:0)

我相信,你可能在ejb jar和war文件中包含了MyEntity类(或实体),因此它们都被类加载器加载。您可能需要从war文件中删除域实体并对其进行测试。

根据jboss docs,默认情况下,ejb jar中定义的类可用于war文件中的类。因此它们只会被ejb类加载器加载一次,并且也将用于war文件中的类。