JSF复合组件内的日期转换异常

时间:2011-05-30 08:09:22

标签: jsf-2 jpa-2.0 composite-component

当我从JSF访问JPA托管日期值时,它返回javax.faces.component.UdateModelException说

'Cannot convert 01.01.10 00:00 of type class java.util.Date to class org.apache.openjpa.util.java$util$Date$proxy 

使用JPA管理的日期值(这意味着它已被代理)在直接从EL使用它时可以正常工作:

'<h:outputLabel value="MyDateValue" for="input"/> 
'<h:inputText id="inputDate" value="#{bean.myDate}"/> 

但是,尝试将其与复合组件一起使用时会造成麻烦   并返回以下转换器异常,因此无法更新模型...

(简化的)JSF复合组件inputDate.xhtml  

    <head> 
            <title>A date input field</title> 
    </head> 

    <composite:interface> 
            <composite:attribute name="dateValue"/> 
    </composite:interface> 

    <composite:implementation> 
            <h:outputLabel value="MyDateValue" for="input"/> 
            <h:inputText id="input" value="#{cc.attrs.dateValue}"/> 
    </composite:implementation> 

假设: 当从复合内部访问值时,似乎OpenJPA中的代理替换处理方式不同。我的猜测是EL-resolver在传递给复合体时对对象值的处理方式不同。将它传递给复合材料意味着它首先在复合材料中被访问,这太晚了,并且没有完成所需的代理替换(因此转换器异常)

所以我尝试更改MyFaces的表达式语言,但它在Websphere中不起作用,即使我最后将类加载更改为父级,并在lib文件夹中提供了来自glassfish的el-impl和el-api并插入MyFaces的必要上下文参数

你们如何在复合组件中使用JPA管理的日期(或其他代理实体)?

2 个答案:

答案 0 :(得分:1)

这是解决方法。问题似乎是WebSpheres的ExpressionLanguage实现,或者更确切地说是执行了顺序解析器。在调用复合组件之前,注册JBoss EL实现可以工作并解析日期代理。我也尝试过Glassfish EL,但它也不起作用......

注册替代EL非常奇怪:MyFaces的web.xml中的设置是

<context-param>
   <param-name>org.apache.myfaces.EXPRESSION_FACTORY</param-name>
   <param-value>org.jboss.el.ExpressionFactoryImpl</param-value>
</context-param>

此外,在WebContent/META-INF/services/下,此单行javax.el.expressionFactory需要名为org.jboss.el.ExpressionFactoryImpl的文件。该课程来自jboss-el-2.0.2.CR1.jar (对不起,找不到maven repo的链接)

一旦找到更好的解决方案,我会及时通知您。

答案 1 :(得分:1)

如果您正在使用sun EL实现,您可以使用以下ELResolver解决此问题:

public class BugfixELResolver extends ELResolver {
//...
@Override
public Class<?> getType(ELContext anElContext, Object aBase, Object aProperty) {
    if (aBase.getClass().getCanonicalName().equals("com.sun.faces.el.CompositeComponentAttributesELResolver.ExpressionEvalMap")){
        Object tempProperty=((Map)aBase).get(aProperty);
        if (tempProperty!=null&&tempProperty.getClass().getCanonicalName().equals("org.apache.openjpa.util.java.util.Date.proxy")) {
            anElContext.setPropertyResolved(true);
            return java.util.Date.class;
        }
    }
    return null;
}


}

以这种方式将它添加到faces-config:

<el-resolver>
    xxx.BugfixELResolver
</el-resolver>

此解决方法也可用于无法更改EL实现的环境(如websphere等)。