1
votes

When I access a JPA managed date value from JSF, it comes back with an javax.faces.component.UdateModelException saying

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

Using a JPA-managed date value (which means it is proxied) works fine when it is used directly from the EL likes this:

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

However, it causes trouble when trying to use it with composite components and gives back the following converter exception and thus can't update the model...

The (simplified) JSF composite component 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> 

Assumption: It seems the proxy replacement in OpenJPA is handled differently when the value is being accessed from inside a composite. My guess is the EL-resolver handles calls to object values differently when it is passed to composites. Passing it to composites means it is first accessed within the composite, which is too late and the required replacement of the proxy is not accomplished (thus the converter exception)

So I tried to change the Expression Language for MyFaces, but it didn't work in Websphere, even though I changed the class loading to parent last and provided el-impl and el-api from glassfish in the lib folder and inserted the necessary context-param for MyFaces

How do you guys use JPA-managed dates (or other proxied entities) in composite components???

2
You seem to be implying that it works when not using a composite component (so when using the component directly in the page "the usual way"). Is this true? - BalusC
@BalusC Right. Using it "directly" works as expected. I discovered MyFaces Resolver can be sorted cwiki.apache.org/MYFACES/elresolver-ordering.html and played a little with it, but no success. Using a different ELFactoryImpl (JBoss El 2.0.1) does the trick for JPA proxied dates, even though it was tricky to register it in WebSphere 8. However method calls don't work with that el anymore... - jonnie119
I've never seen this problem before, but I am also not using MyFaces. Do you have any chance to try Mojarra instead of MyFaces, even though it's just to exclude the one and other. - BalusC
@BalusC Not easy to change, but I will try tomorrow. FYI: I use MyFaces with OWB and OpenJPA in Beta 3 Version of WebSphere 8. All used providers come as default, thus it is hard to change the RI to Mojarra. cheers - jonnie119
Ah ok. Well, I feel sorry that I can't say more than "good luck". - BalusC

2 Answers

1
votes

Here is the workaround. The problem seems to be WebSpheres' ExpressionLanguage Implementation or rather the order resolvers are executed. Registering the JBoss EL implementation works and resolves the date proxies before calling the composite component. I also tried the Glassfish EL, but it didn't work either...

Registering a alternative EL is quite strange: The setting in web.xml for MyFaces is

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

Additionally under WebContent/META-INF/services/ a file named javax.el.expressionFactory is needed with this single line org.jboss.el.ExpressionFactoryImpl. The class comes from jboss-el-2.0.2.CR1.jar (sorry, couldn't find the link to a maven repo)

I will keep you updated once I find a better solution...

1
votes

If you are using the sun EL implementation you might use the following ELResolver which works around this issue:

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;
}


}

Add it to the faces-config this way:

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

This workaround can also be used in environments where you can not change the EL implementation (like websphere etc.).