来自其他项目的实体的类加载错误

时间:2018-01-12 09:01:55

标签: java-ee classloader

我想创建一个可以在我项目的JSF页面中使用的实体转换器。

我的项目结构如下:

- project-ear.ear
| --- project1-ejb.jar
| --- project2-web.war
| --- lib
| --- | --- warframework.jar
| --- | --- ekbframework.jar

在lib.jar中,我有一个absctract类EntityConverterlib/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();
        }
    }
}

EntityLoader中的界面lib/ejbframework.jar

public interface EntityLoader {
    AbstractEntity loadEntity(String className, Long sid);
}

我正在使用Mavens WAR-Overlay功能将不同的war文件合并为一个。我有一个project1-web.war,其中包含project2-web.war。 在project1-web.war中我定义了Converter的具体实现:

@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并触发转换器后,出现以下错误:

  

无法为类加载实体:class de.example.com.user.model.MyEntity:java.lang.ClassNotFoundException:来自[Module“deployment.project-ear的class de.example.com.user.model.MyEntity .ear.project1-ejb.jar:main“来自服务模块加载器”
    在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)
    at java.lang.Class.forName0(Native Method)
    在java.lang.Class.forName(Class.java:264)
    at de.example.com.common.service.ConcreteEntityLoader.loadEntity(ConcreteEntityLoader.java:30)

de.example.com.user.model.MyEntityEntityLoader一样存在于同一个jar中。我认为,会发生此异常,因为实体转换器是从project2-web.war文件调用的,该类加载器无法访问project1-ejb.jar中的类。它是否正确?我需要更改什么才能正确加载类?

1 个答案:

答案 0 :(得分:0)

发现问题:

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();