我想创建一个可以在项目的 JSF 页面中使用的实体转换器。
我的项目结构如下:
-- project-ear.ear
|--- project1-ejb.jar|--- project2-web.war|--- lib
|---|--- warframework
.jar|---|--- ekbframework.jar
在库中.jar我有一个在lib/warframework.jar
中实现 JSF 转换器逻辑EntityConverter
absctract 类。
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();
}
}
}
并在lib/ejbframework.jar
中EntityLoader
一个界面.
public interface EntityLoader {
AbstractEntity loadEntity(String className, Long sid);
}
我正在使用Mavens WAR-Overlay功能将不同的战争文件合并为一个。我有一个包含在project2-web.war
中的project1-web.war
。 在该project1-web.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
并触发转换器后,出现以下错误:
无法加载类的实体:类 de.example.com.user.model.MyEntity:java.lang.ClassNotFoundException: class de.example.com.user.model.MyEntity 来自 [Module "deployment.project-ear.ear.project1-ejb.jar:main" from Service Module Loader]at org.jboss.modules.ModuleClassLoader.findClass(
ModuleClassLoader.java:198)
at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:363)
at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:351)at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:93)at java.lang.Class.forName0(Native Method)at java.lang.Class.forName(Class.java:264)at de.example.com.common.service.ConcreteEntityLoader.loadEntity(ConcreteEntityLoader.java:30)
类de.example.com.user.model.MyEntity
与EntityLoader
一样存在于同一个罐子中。我认为,会发生此异常,因为实体转换器是从project2-web.war
文件中调用的,该类加载器无法访问project1-ejb.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();