Bug 52440

Summary: Wrong getValueReference behaviour with Facelets parameter expressions
Product: Tomcat 7 Reporter: JustasR <justas.ratkevicius>
Component: Servlet & JSP APIAssignee: Tomcat Developers Mailing List <dev>
Status: RESOLVED FIXED    
Severity: normal    
Priority: P2    
Version: 7.0.22   
Target Milestone: ---   
Hardware: PC   
OS: All   
Attachments: Test case for ValueReference returning null

Description JustasR 2012-01-09 09:11:20 UTC
ValueExpression method getValueReference should return base object and property. But it returns null if ValueExpression is Facelets parameter.
Example:

someVar = #{concreteObject.property}

ValueExpression for #{someVar} return null from method getValueReference (guess because it is simple expression #{someVar}), but logicaly it should return parent expressions ValueReference (need hierachical ValueReference lookup).

I made workaround with Java Reflect API in my code and it illustrates problem:

ELContext elContext = FacesContext.getCurrentInstance().getELContext();
ValueReference reference = exp.getValueReference(elContext);
        
if (reference == null && exp instanceof TagValueExpressionUEL) {
	ValueExpressionImpl origExp = (ValueExpressionImpl) ((TagValueExpressionUEL) exp).getWrapped();
            
	// TODO: JR: find better way to get base and property. ! Code is not portable because uses Tomcat EL implementation details. ! 
	Field field = ReflectionUtils.findField(origExp.getClass(), EL_IMPL_VAR_PROPERTY);
	field.setAccessible(true);
	VariableMapper varMapper = (VariableMapper) ReflectionUtils.getField(field, origExp);
    field = ReflectionUtils.findField(origExp.getClass(), EL_IMPL_NODE_PROPERTY);
    field.setAccessible(true);
    SimpleNode node = (SimpleNode) ReflectionUtils.getField(field, origExp);

    if (varMapper != null && node != null) {
		ValueExpression parentExp = varMapper.resolveVariable(node.getImage());
        if (parentExp != null) {
			try {
				reference = parentExp.getValueReference(elContext);

                if (reference == null) {
					reference = getValueReference(parentExp);
                }
            } catch (PropertyNotFoundException e) {
				LOG.warn("Property not found: " + e.getMessage());
            }
        }
    }
}
Comment 1 Konstantin Kolinko 2012-01-09 18:09:03 UTC
Can you provide small simple web application that demonstrates the problem?

That SimpleNode that you operate on - what is its exact className? (Which one of subclasses of SimpleNode that is?)
Comment 2 JustasR 2012-01-10 09:39:08 UTC
Created attachment 28130 [details]
Test case for ValueReference returning null

I use SystemEventListener event javax.faces.event.PreRenderComponentEvent to intercept component render process ant try to get component ValueExpression and ValueReference from it (class TestSystemEventListener).

I use Facelets custom components with taglib file (not composite component).

Returned ValueReference is always null.

Null is returned from node AstIdentifier (super class SimpleNode)

I print returned ValueReference value to console.
Comment 3 Mark Thomas 2012-01-12 18:41:13 UTC
I think I have this fixed but I'd like to confirm this with the test case. Please provide some details (the URL being the most important) of how this test case is meant to be used.
Comment 4 Mark Thomas 2012-01-12 19:38:26 UTC
Fixed based on the spec language for getValueReference()