Bug 52440 - Wrong getValueReference behaviour with Facelets parameter expressions
Summary: Wrong getValueReference behaviour with Facelets parameter expressions
Status: RESOLVED FIXED
Alias: None
Product: Tomcat 7
Classification: Unclassified
Component: Servlet & JSP API (show other bugs)
Version: 7.0.22
Hardware: PC All
: P2 normal (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-01-09 09:11 UTC by JustasR
Modified: 2012-01-12 19:38 UTC (History)
0 users



Attachments
Test case for ValueReference returning null (7.20 KB, application/zip)
2012-01-10 09:39 UTC, JustasR
Details

Note You need to log in before you can comment on or make changes to this bug.
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()