Jakarta ee 对来自其他项目的实体加载类时出错
我想创建一个实体转换器,它可以在我的项目的JSF页面中使用 我的项目结构如下: --项目ear.earJakarta ee 对来自其他项目的实体加载类时出错,jakarta-ee,classloader,Jakarta Ee,Classloader,我想创建一个实体转换器,它可以在我的项目的JSF页面中使用 我的项目结构如下: --项目ear.ear |---project1ejb.jar |---project2 web.war |---lib |---|---warframework.jar |---|---ekbframework.jar 在lib.jar中,我有一个abstract类EntityConverter在lib/warframework.jar中实现JSF转换器逻辑 public abstract class Entity
|---project1ejb.jar
|---project2 web.war
|---lib
|---|---warframework.jar
|---|---ekbframework.jar 在lib.jar中,我有一个abstract类
EntityConverter
在lib/warframework.jar
中实现JSF转换器逻辑
public abstract class EntityConverter implements Converter {
protected abstract EntityLoader getEntityLoader();
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (StringUtils.isBlank(value)) return null;
try {
String[] split = value.split(":");
return getEntityLoader().loadEntity(split[0], Long.valueOf(split[1]));
} catch (NumberFormatException e) {
return null;
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) return null;
if (value instanceof AbstractEntity) {
return value.getClass() + ":" + ((AbstractEntity) value).getSid();
} else {
return value.toString();
}
}
}
public interface EntityLoader {
AbstractEntity loadEntity(String className, Long sid);
}
以及lib/ejbframework.jar
中的接口EntityLoader
public abstract class EntityConverter implements Converter {
protected abstract EntityLoader getEntityLoader();
@Override
public Object getAsObject(FacesContext context, UIComponent component, String value) {
if (StringUtils.isBlank(value)) return null;
try {
String[] split = value.split(":");
return getEntityLoader().loadEntity(split[0], Long.valueOf(split[1]));
} catch (NumberFormatException e) {
return null;
}
}
@Override
public String getAsString(FacesContext context, UIComponent component, Object value) {
if (value == null) return null;
if (value instanceof AbstractEntity) {
return value.getClass() + ":" + ((AbstractEntity) value).getSid();
} else {
return value.toString();
}
}
}
public interface EntityLoader {
AbstractEntity loadEntity(String className, Long sid);
}
我正在使用MavensWarOverlay特性将不同的WAR文件合并到一个文件中。我有一个project1web.war
,它包含在project2web.war
中。
在该project1web.war
中,我定义了转换器的具体实现:
@Named
@FacesConverter("concreteEntityConverter")
public class ConcreteEntityConverter extends EntityConverter {
@Inject
private ConcreteEntityLoader entityLoader;
@Override
protected EntityLoader getEntityLoader() {
return entityLoader;
}
}
在project1-ejb.jar中,我定义了EntityLoader
实现:
public class ShsEntityLoader implements EntityLoader {
@Inject
Logger log;
@Inject
protected EntityManager entityManager;
@Override
public AbstractEntity loadEntity(String className, Long sid) {
AbstractEntity entity = null;
try {
entity = (AbstractEntity) entityManager.find(Class.forName(className), sid);
} catch (ClassNotFoundException ex) {
log.warn("Could not load entity for class: " + className, ex);
}
return entity;
}
}
部署ear
并触发转换器后,我得到以下错误:
无法从[Module“deployment.project ear.ear.project1 ejb.jar:main”服务模块加载器中加载类的实体:class de.example.com.user.model.MyEntity:java.lang.ClassNotFoundException:class de.example.com.user.model.MyEntity]位于org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:198)
位于org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
位于org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)
位于org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)
在java.lang.Class.forName0(本机方法)
在java.lang.Class.forName(Class.java:264)上
位于de.example.com.common.service.ConcreteEntityLoader.loadEntity(ConcreteEntityLoader.java:30) 类
de.example.com.user.model.MyEntity
与EntityLoader
一样存在于同一个jar中。我认为,出现这种异常是因为实体转换器是从project2web.war
文件调用的,该类加载器无法访问project1ejb.jar
中的类。这是正确的吗?我必须更改什么才能正确加载类?发现问题:
EntityConverter.getAsString()中的我的代码创建了错误的对象字符串表示形式:
return value.getClass() + ":" + ((AbstractEntity) value).getSid();
结果是:class de.example.com.user.model.MyEntity:1
,而不是预期的de.example.com.user.model.MyEntity:1
将上述代码更改为以下代码,使一切都按预期工作:
return value.getClass().getCanonicalName() + ":" + ((AbstractEntity) value).getSid();