I'm having a problem in an EAR package which contains a server deployed persistence unit in an EJB mdule, and a web app in a WAR module
EAR
|--- persistence unit (EJB module)
|--- web app (WAR)
...
Everything compiles and the deploy (under WildFly 10 CR5) is performed successfully. The persistnce unit is correctly deployed and the schema is created (using Hibernate schema generation during development).
Though, when I try to persist one of the entities like that
MyEntitiy e = new MyEntitiy();
e.setId(UUID.randomUUID().toString());
e.setName("name");
entityService.save(e);
I get a runtime error which root cause is:
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)
Diving into the debugger, I tracked down to the method sun.reflect.UnsafeFieldAccessorImpl.ensureObj
which perform a check via the method Class.isAssignableFrom
between the classes
Field
object (Field.getDeclaredClass()
) This check returns false, due to the fact that the to classes have been loaded with different ClassLoader
s (they are logically the same class).
How can I overcome this issue without changing the general layuot of the project (ie, keep the persistence unit as an EJB module to be shared across various modules)?
I believe, you might have included MyEntity class(or entities) in both ejb jar and war file and so they are getting loaded by both the class loaders. You may need to remove domain entities from war file and test it.
As per jboss docs, classes defined in ejb jar are available for classes in war file by default. And so they will loaded only once by ejb classloader only and will be used/available for classes in the war file as well.