<f:setPropertyActionListener> Parent is not of type ActionSource, type is: com.sun.faces.component.PassthroughElement - jsf

I'm using Passthrough elements in my JSF project, and need to do something similar to this:
<h:commandLink action="#{myBean.acao()}" value="click me">
<f:setPropertyActionListener target="#{myBean.object}" value="#{localObject}"/>
</h:commandLink>
but using Passthrough elements to have more control of my frontend like trying below:
<a href="#" jsf:action="#{myBean.acao()}">click me
<f:setPropertyActionListener target="#{myBean.object}" value="#{localObject}"/>
</a>
but apparently this is not working, I get the following error message:
<f:setPropertyActionListener> Parent is not of type ActionSource, type is: com.sun.faces.component.PassthroughElement
Does anyone know how I could solve this?

Looks like just a bug in your Mojarra version. It works for me with current latest 2.2.12 version.
You could workaround it by utilizing the EL 2.2 feature of passing method arguments. See also Invoke direct methods or methods with arguments / variables / parameters in EL. It's surely available in your environment as #{myBean.acao()} apparently didn't throw an EL exception (this syntax is not supported before EL 2.2).
click me
If you absolutely need to invoke a setter during an action listener event, e.g. because you'd like to control the invocation of action by throwing AbortProcessingException in case the set value is invalid, see also Differences between action and actionListener, then declare a jsf:actionListener.
click me

Related

primefaces update attribute not working on modal dialog opened from modal dialog [duplicate]

I have a question about the idea behind the fact, that only UIForm got the attribute prependId. Why is the attribute not specified in the NamingContainer interface? You will now probably say that's because of backward compability but I would preferre breaking the compability and let users which implement that interface, also implement methods for the prependId thing.
The main problem from my perspective about the prependId in the UIForm component is, that it will break findComponent()
I would expect that if I use prependId, then the NamingContainer behaviour would change, not only related to rendering but also when wanting to search for components in the component tree.
Here a simple example:
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
Now when i want to get the panelGroup component I would expect to pass the string "group" to the method findComponent(), but it won't find anything, I have to use "test:group" instead.
The concrete problem with that is, when using ajax with prependId="false". The ajax tag expects in the attributes update and process, that the values care of naming containers. It's a bit strange that when I use prependId="false" that I have to specify the full id or path, but okay.
<h:form id="test" prependId="false">
<h:panelGroup id="group"/>
</h:form>
<h:form id="test1" prependId="false">
<h:commandButton value="go">
<f:ajax render="test:group"/>
</h:commandButton>
</h:form>
Well this code will render without problems but it won't update the panelGroup because it cannot find it. The PartialViewContext will contain only the id "group" as element of the renderIds. I don't know if this is expected, probably it is but I don't know the code. Now we come to the point where the method findComponent() can not find the component because the expression passed as parameter is "group" where the method would expect "test:group" to find the component.
One solution is to write your own findComponent() which is the way I chose to deal with this problem. In this method i handle a component which is a NamingContainer and has the property prependId set to false like a normal UIComponent. I will have to do that for every UIComponent which offers a prependId attribute and that is bad. Reflection will help to get around the static definition of types but it's still not a really clean solution.
The other way would be introducing the prependId attribute in the NamingContainer interface and change the behaviour of findComponent() to work like described above.
The last proposed solution would be changing the behaviour of the ajax tag to pass the whole id, but this would only solve the ajax issue and not the programmatic issues behind the findComponent() implementation.
What do you think about that and why the hell is it implemented like that? I can't be the first having this problem, but I wasn't able to find related topics?!
Indeed, UIComponent#findComponent() as done by <f:ajax render> fails when using <h:form prependId="false">. This problem is known and is a "Won't fix": JSF spec issue 573.
In my humble opinion, they should never have added the prependId attribute to the UIForm during the JSF 1.2 ages. It was merely done to keep j_security_check users happy who would like to use a JSF form with JSF input components for that (j_security_check requires exact input field names j_username and j_password which couldn't be modified by configuration). But they didn't exactly realize that during JSF 1.2 another improvement was introduced which enables you to just keep using <form> for that instead of sticking to <h:form>. And then CSS/jQuery purists start abusing prependId="false" to avoid escaping the separator character : in their poorly chosen CSS selectors.
Just don't use prependId="false", ever.
For j_security_check, just use <form> or the new Servlet 3.0 HttpServletRequest#login(). See also Performing user authentication in Java EE / JSF using j_security_check.
For CSS selectors, in case you absolutely need an ID selector (and thus not a more reusable class selector), simply wrap the component of interest in a plain HTML <div> or <span>.
See also:
How to select JSF components using jQuery?
How to use JSF generated HTML element ID with colon ":" in CSS selectors?
By default, JSF generates unusable ids, which are incompatible with css part of web standards

setActionListener no longer executed (first) in combination with actionListener after switching to Facelets

We have this Trinidad 1.2 application which we converted to use Facelets (1.1.14) recently. Most of the problems we were able to solve using some find and replace actions. Now we ran into an issue I was unable to solve without modifying multiple instances of code.
The problem is that if we use an actionListener on a command button in combination with a child <tr:setActionListener />:
<tr:commandButton actionListener="#{someBean.toggleSomeObject}"
immediate="true"
...>
<tr:setActionListener from="#{rowObject}" to="#{someBean.someObject}"/>
</tr:commandButton>
After switching to Facelets the <tr:setActionListener /> is no longer executed (first). I tried replacing the <tr:setActionListener /> with a <f:setPropertyActionListener />, but the result was the same.
The only option I can think of is using an <f:attribute/> and read the attribute in the action listener, but that would require me to change several action listener methods.
I hope there are other options which requires less work.
This behavior is expected. That it "worked" previously is just caused by a bug. You should not rely on buggy behavior.
Use <tr:commandButton action> instead (and don't forget to get rid of ActionEvent argument).
See also:
Differences between action and actionListener

Why is InputHidden readonly attribute not in JSF documentation?

I have recently encountered a case where I wanted to set the index value from ui:repeat varStatus="v" using <h:inputHidden="#{v.index}/>. If you try this and execute the component using AJAX you will get an exception that the property is not writeable. While looking around I found that inputHidden supports a readonly="true" attribute that does just that making the error go away.
Is there a reason why this is not in documentation? (i.e. special, passthrough, other)
Is it safe to use?
After doing some digging Core JavaServer Faces 3e had this to say :
The h:inputHidden tag has the same attributes as the other input tags, except that it does not support the standard HTML and DHTML tags
So, the reason why readonly is not in the docs for inputHidden and also why it's not being rendered in your HTML is because inputHidden does not support it. This was also confirmed by Netbeans when I tried to add readonly as an attribute to inputHidden'(red squiggly lines with an error message). I was able to get that exception when I submitted a form with no setter defined for my bean property that was placed in inputHidden. Since inputHidden calls the setter when a form is submitted (for my case) and since none is defined in my code, it will of course throw that exception, namely:
javax.el.PropertyNotWritableException: /index.xhtml #14,56 value="#{bean.x}": The class 'Bean' does not have a writable property 'x'.
As for why it works when you do that I have no idea. Since you're worried about safety, I would suggest you do as BalusC says and simply use <input type="hidden"> or you define a setter for that property. Don't use it like that.
So long time since this question started, however just FYI, this works:
<h:inputHidden id="compId" readonly="#{true}" value="#{myBean.attribute}" />

PropertyNotFoundException EL Expressions not resolving?

I have code similar to this in my facelet...
<c:foreach items=#{myBean.listOfA} var="a">
<c:foreach items=#{myBean.listOfB} var="b">
<c:set var="aName" value="#{a.name}">
<c:set var="component" value="#{b.associatedComponent(aName)}">//this wont resolve
//do stuff with component
</c:foreach>
</c:foreach>
myBean is a session scoped bean. Both A and B classes are maintained in lists inside the bean but are just model objects not managed beans.
That being said the method b.associatedComponent(a) I am assuming should resolve to b.getAssociatedComponent(A a) which I have checked many times. All methods are public. What can I do to make the method accessible to EL?
No matter what I try I get a PropertyNotFoundException on associatedComponent.
P.S. I also tried moving the method to the bean like this...
<c:set var="component" value="#{myBean.associatedComponent(b, aName)}">
This also does not work and throws the same PropertyNotFoundException.
This will not work, as the c:set tag expects a ValueExpression for the value attribute.
This means that you are only able to use properties - not methods.
If you use arguments like here #{b.associatedComponent(aName)} then what you have is a method call, not a property call. This however is a valid MethodExpression and can be used in places like the action attribute of a command link.
See the API documentation and spec for more details on this.

Jsf dynamically created actionListener parameter

I have a custom facelet component (custom tag) but there is one thing that currently annoys me a lot. I'm trying to pass an action listener as a parameter to the custom tag, in order to make it more dynamic and just doesn't work.
Environment: JSF 1.2, IceFaces 1.8
Here's the way I'm trying to achieve this:
the command link uses the passed parameter 'paginationController'
<h:commandLink id="#{id}-link-three" value="click"
actionListener="#{paginationController.paginationLinkClicked}" />
the parameter 'paginationController' is passed like this:
paginationController="rowSelectController"
when I click the link, there's what I receive:
Received 'javax.el.MethodNotFoundException' when invoking action listener
'#{paginationController.paginationLinkClicked}' for component 'entity-list-apps-link-three'
2011-02-22 12:49:47,803 SEVERE [javax.faces.event] (http-127.0.0.1-8080-4)
javax.el.MethodNotFoundException: /WEB-INF/jsf/common/components/facelets
/applicationList.xhtml #107,71 actionListener="#{paginationController.paginationLinkClicked}":
Method not found: rowSelectController.paginationLinkClicked(javax.faces.event.ActionEvent)
So it seems that it successfully resolves the bean name to rowSelectController, but it complaints it can't find the method, and the method IS there!
One more thing, if I replace the parameter with the correct controller's name, it just works! Any ideas?
Because paginationController is variable you need to use the [] syntax here. Assuming paginationLinkClicked is a fixed method name:
<h:commandLink actionListener="#{paginationController['paginationLinkClicked']}" />
If paginationLinkClicked would also be variable, you need to omit the single quotes:
<h:commandLink actionListener="#{paginationController[paginationLinkClicked]}" />

Resources