[JAVASERVERFACES-3539] JSF page calls wrong remove() method. Created: 20/Nov/14  Updated: 05/Jan/15  Resolved: 01/Dec/14

Status: Closed
Project: javaserverfaces
Component/s: facelets
Affects Version/s: 2.2.8-02
Fix Version/s: None

Type: Bug Priority: Major
Reporter: salih1989 Assignee: Manfred Riem
Resolution: Works as designed Votes: 0
Labels: None
Remaining Estimate: 2 days
Time Spent: Not Specified
Original Estimate: 2 days
Environment:

GlassFish 4, Windows 8


Attachments: Zip Archive ELBug-master.zip    
Tags: method-param, methodexpression

 Description   

In my JSF page, i am trying to remove an element from a collection. But instead of calling the `Collection.remove(Object o)` method, i think the jsf page calls `Vector.remove(int i)`.

With the code below i get the following error:

> java.lang.IllegalArgumentException: Cannot convert
> com.question.entities.Tags[ tagId=12 ] of type class
> com.question.entities.Tags to int

<ui:repeat value="#

{backingBean.question.tagsCollection}

" var="tag" >
<li>
<span>#

{tag.tagTitle}

</span>
<h:commandButton>
<f:ajax event="click" listener="#

{backingBean.question.tagsCollection.remove(tag)}

" render="@form" execute="@form"/>
</h:commandButton>
</li>
</ui:repeat>

Implementation Details of Tags Collection :
private Collection<Tags> tagsCollection;
tagsCollection is instantiated by JPA.



 Comments   
Comment by salih1989 [ 20/Nov/14 ]

Here is the minimum code to generate this bug:
index.xhtml

<?xml version='1.0' encoding='UTF-8' ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
<h:head>
<title>Facelet Title</title>
</h:head>
<h:body>
<h:form id="form">
<ui:repeat value="#

{backingBean.myList}

" var="tag">
#

{tag.booleanValue()}

<h:commandButton value="Delete">
<f:ajax listener="#

{backingBean.myList.remove(tag)}

" execute="@form" render="@form"/>
</h:commandButton>
</ui:repeat>
</h:form>
</h:body>
</html>

BackingBean.java
@Named
@ViewScoped
public class BackingBean implements Serializable {

private Collection<Boolean> myList = new Vector<Boolean>();

public BackingBean()

{ myList.add(true); myList.add(false); myList.add(true); }

public Collection<Boolean> getMyList()

{ return myList; }

public void setMyList(Collection<Boolean> myList)

{ this.myList = myList; }

}

Comment by Manfred Riem [ 24/Nov/14 ]

Can you please send the reproducer (with sources) to issues@javaserverfaces.java.net? Thanks!

Comment by Manfred Riem [ 01/Dec/14 ]

As you can notice by the stack trace this is how EL does method resolution. The easiest to work around this is having a method on the backing bean like so:

public void remove(Object object)

{ myStringList.remove(object); }

With the page adjusted to:

backingBean.remove(stringVar)

Closing this as "Works as Designed"





[JAVASERVERFACES-2095] MethodExpression parameters not honored inside composite component Created: 03/Jun/11  Updated: 08/May/13  Resolved: 08/May/13

Status: Closed
Project: javaserverfaces
Component/s: expression language
Affects Version/s: 2.1.1
Fix Version/s: None

Type: Bug Priority: Trivial
Reporter: franck_garcia Assignee: Unassigned
Resolution: Incomplete Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified
Environment:

jboss6.0.0.Final
weld 1.0.0-CR2
mojarra 2.1.1.FCS


Issue Links:
Related
is related to JAVASERVERFACES-2839 composite component umbrella task Closed
Tags: MethodExpression, composite_components, parameters

 Description   

I have the following component
{.....
<cc:interface name="sayHello">
<cc:attribute name="to" shortDescription="the person to salute"/>
<cc:attribute name="helloSayer" type="com.acme.HelloSayer" shortDescription="The Component that will say hello to 'cc.attrs.to'!" />
</cc:interface>

<cc:implementation>
<h:form>
<h:commandLink action="#

{cc.attrs.helloSayer.hello(cc.attrs['to'])}" value="Hello!"/>
</h:form>
</cc:implementation>
....}

The component's client xhtml:
....
<util:sayHello to="my dog" helloSayer="#{helloSayer}"/>
....

and the cdi backing bean:

package com.acme;

import javax.enterprise.context.RequestScoped;
import javax.inject.Named;

@Named
@RequestScoped
public class HelloSayer {

public HelloSayer() {
}

public void hello(String to){ System.out.println("Hello "+to + "!!!"); }
}

and this stack trace:
javax.el.MethodNotFoundException: //home/franck/workspace/acme/acme-web/target/classes/META-INF/resources/component/sayHello.xhtml @19,20 action="#{cc.attrs.helloSayer.hello(cc.attrs['to'])}

": Method not found: com.acme.HelloSayer@1069836.hello()
10:54:24,297 INFO [STDOUT] at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:109)
10:54:24,297 INFO [STDOUT] at com.sun.faces.facelets.el.ContextualCompositeMethodExpression.invoke(ContextualCompositeMethodExpression.java:177)
10:54:24,297 INFO [STDOUT] at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
10:54:24,297 INFO [STDOUT] at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
10:54:24,297 INFO [STDOUT] at javax.faces.component.UICommand.broadcast(UICommand.java:315)
10:54:24,297 INFO [STDOUT] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
10:54:24,297 INFO [STDOUT] at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
10:54:24,298 INFO [STDOUT] at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)

If I add the following method to my backing bean:

public void hello()

{ System.out.println("Hello anonymous!!!"); }

No more error and the message is shown in the console.
Am I doing something wrong?



 Comments   
Comment by Rinner23 [ 03/Jun/11 ]

Does it work if you define an Interface with that method, then implement the Interface in your bean and pass the Interface type as the 'type' on the attribute?

Matt

Comment by franck_garcia [ 03/Jun/11 ]

Does it work if you define an Interface with that method, then implement the Interface in your bean and pass the Interface type as the 'type' on the attribute?

Matt

No it doesn't thanks

2011-06-03 12:41:17,765 ERROR (com.acme.passage.handler.ExceptionHandler)[] Exception caught:
12:41:17,766 INFO [STDOUT] java.lang.NoSuchMethodError: com/acme/HelloSayer.hello()V
12:41:17,766 INFO [STDOUT] at com.acme.HelloSayer.hello(HelloSayer.java:65531)
12:41:17,766 INFO [STDOUT] at com.acme.org$jboss$weld$bean-jboss$classloader:id="vfs:$$$home$franck$jboss-6$0$0$Final$server$default$deploy$passage-ear$ear"-ManagedBean-class_com$fedextnc$passage$HelloSayer_$$WeldClientProxy.hello(org$jboss$weld$bean-jboss$classloader:id="vfs:$$$home$franck$jboss-6$0$0$Final$server$default$deploy$passage-ear$ear"-ManagedBean-class_com$acme$HelloSayer$$_WeldClientProxy.java)
12:41:17,766 INFO [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
12:41:17,766 INFO [STDOUT] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
12:41:17,766 INFO [STDOUT] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
12:41:17,766 INFO [STDOUT] at java.lang.reflect.Method.invoke(Method.java:597)
12:41:17,767 INFO [STDOUT] at org.apache.el.parser.AstValue.invoke(AstValue.java:196)
12:41:17,767 INFO [STDOUT] at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
12:41:17,767 INFO [STDOUT] at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
12:41:17,767 INFO [STDOUT] at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
12:41:17,767 INFO [STDOUT] at org.jboss.weld.util.el.ForwardingMethodExpression.invoke(ForwardingMethodExpression.java:43)
12:41:17,767 INFO [STDOUT] at org.jboss.weld.el.WeldMethodExpression.invoke(WeldMethodExpression.java:56)
12:41:17,767 INFO [STDOUT] at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
12:41:17,767 INFO [STDOUT] at com.sun.faces.facelets.el.ContextualCompositeMethodExpression.invoke(ContextualCompositeMethodExpression.java:177)
12:41:17,767 INFO [STDOUT] at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
12:41:17,767 INFO [STDOUT] at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
12:41:17,767 INFO [STDOUT] at javax.faces.component.UICommand.broadcast(UICommand.java:315)
12:41:17,767 INFO [STDOUT] at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
.....

Comment by schar00 [ 21/Nov/11 ]

i've got the same problem but i found a workaround for this bug: try to put the "HelloSayer"-Bean in parentheses!

#

{(cc.attrs.helloSayer).hello(cc.attrs['to'])}

should work!

...at least in my case with mojarra 2.1.3 (SNAPSHOT 20110825) it works fine!

Comment by Manfred Riem [ 25/Jan/13 ]

Can you verify if this is still a problem in the latest 2.1 release?

Comment by Manfred Riem [ 04/Mar/13 ]

Lowering priority because of no response

Comment by Manfred Riem [ 01/Apr/13 ]

Lowering priority because of no response

Comment by Manfred Riem [ 08/May/13 ]

Closing because of inactivity





[EL_SPEC-11] Clarify how single variable evaluates to method Created: 08/Jan/13  Updated: 19/Mar/13  Resolved: 19/Mar/13

Status: Resolved
Project: el-spec
Component/s: None
Affects Version/s: None
Fix Version/s: None

Type: Improvement Priority: Major
Reporter: arjan tijms Assignee: Unassigned
Resolution: Fixed Votes: 2
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Tags: clarification, evaluation, methodexpression

 Description   

Section 1.2.1.2 in the EL specification mentions that a method expression can consist of a single variable:

 
A method expression shares the same syntax as an lvalue. 
That is, it can only consist of either a single variable
(e.g. ${name}) or a property resolution on some object, 
via the . or [] operator (e.g. ${employee.name}).

As it appears, it's not entirely clear how such single variable should be evaluated.

In the reference implementation for example, we see that in this case a MethodExpressionImpl will reference an AstIdentifier, which will use the context's variable mapper to obtain a ValueExpression. The value is then obtained from this value expression, and it's expected to be a MethodExpression, which is then invoked.

This can be seen at http://java.net/projects/el-spec/sources/source-code/content/trunk/impl/src/main/java/com/sun/el/parser/AstIdentifier.java?rev=198 where the method getMethodExpression at line 198 demonstrates the "value expression wrapping a method expression" assumption. invoke at line 183 then shows this obtained method expression is simply invoked.

Comments on line 198 and 209 explicitly mention 2 cases:

case A: ValueExpression exists, getValue which must
be a MethodExpression

[...]

case B: evaluate the identity against the ELResolver, again, must be
a MethodExpression to be able to invoke

These cases however are not outlined in the specification. As a result, alternative EL implementations (like JUEL) have taken a completely different approach. In the case of JUEL, it also expects a ValueExpression, but then guessed that this value expression should be wrapping a Method. This on its turn leads to unexpected behavior and bugs such as reported here: http://code.google.com/p/omnifaces/issues/detail?id=100

In order to ensure portability between EL implementations, I would like to request this specific case to be clarified in the specification.



 Comments   
Comment by beckchr [ 08/Jan/13 ]

See also this issue from 2006: http://java.net/jira/browse/JSP_SPEC_PUBLIC-164

Comment by kchung [ 19/Mar/13 ]

What about adding the following clarification to 1.2.1.2

When a MethodExpression created from an EL expression of the form $

{name}

is invoked,

1. The identifier "name" is first evaluated.
a. If "name" is an EL variable, the ValueExpression associated with the variable is evaluated.
b. Else obtain the value resolved in the ELResolvers.
2. If the identifier evaluates to a MethodExpression, it is invoked and its result is returned.
3. Else error.

Comment by kchung [ 19/Mar/13 ]

Added a new section 1.5.4. in EL 3.0 spec to clarify the issue.

Comment by arjan tijms [ 19/Mar/13 ]

What about adding the following clarification to 1.2.1.2 [...]

It sounds okay to me, thanks!





Generated at Sat Sep 05 16:25:09 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.