JSF Combine ui:param with composite component - jsf

you have saved me many times ago with this forum, but now I am really stuck and don't now where to search any longer...
I always get the following error message (warning level, but method is also not executed correctly):
javax.el.PropertyNotFoundException: Target Unreachable, identifier 'editor' resolved to null: javax.faces.FacesException: #{cc.attrs.selectionListener}
I have isolated the problem to a few lines of code:
This is my main file:
<c:forEach items="#{myBean.getEditors()}" var="currentEditor" >
<ui:include src="#{currentEditor.getPanel()} >
<ui:param name="editor" value="#{currentEditor} />
</ui:include>
</c:forEach>
The bean.getEditors() (session scoped) just returns a list with one single entry at the moment. The 'editor' is a POJO with some simple attributes and two listener methods. The listener method does only write a log entry. (Should of course do more in future)
The file which is included looks like this:
<h:selectOneMenu value="#{editor.menuValue}>
<f:selectItem itemValue="Value 1" />
<f:selectItem itemValue="Value 2" />
<a4j:ajax event="change" listener="#{editor.menutListener()}" />
</h:selectOneMenu>
<myComponent:treeComponent id="tree" selectionListener="#{editor.treeListener()} />
The component I created consists of a richfaces tree and when clicking on a node the following method is called:
<a4j:jsFunction name="performSelection" action="#{cc.attrs.selectionListener} />
I am quite confident that the composition itself is ok because I use it also at different places. When I remove the action from the a4j:jsFunction it also works perfect.
For me it smells a bit like the bug JSF 1223
The workaround does not work for me - probably because I create the param in the forEach.
I had similar problems (ui:param + component) before, but was able to solve them with giving the full path as attribute instead of a parameter. But this does not work here because it is used in too many different places.
Please help, I cannot be the only one with this problem, but I simply do not find any other threads for this.
Edit:
Today with a fresh mind I came even closer to the problem. You can forget the whole include/ forEach stuff...
<myComponent:treeComponent id="tree" selectionListener="#{myBean.getSingleEditor().treeListener()} />
Does work, while
<ui:param name="editor" value="#{myBean.getSingleEditor()} />
<myComponent:treeComponent id="tree" selectionListener="#{editor.treeListener()} />
does not work.
Well the JAVA code is performed, but the error is written to the log and the render and oncomplete method of the jsFunction do not work.
I also tried to use "data" instead of "action" for testing. No error is written to log, but JAVA method is not even called.

After many days of try&error I found a solution that is working for me:
I splitted up the listener method to one parameter with the JAVA class and one parameter with the the method name (as simple String)
The action method now looks like:
<a4j:jsFunction name="performSelection" action="#{cc.attrs.listenerClass[cc.attrs.listenerMethodName]}" />
Not nice but working... Perhaps it helps someone - or anybody can explain more...
By the way, the following was not working for me:
<a4j:jsFunction name="performSelection" action="#{cc.attrs.listenerClass[staticMethodName]}" />
While this was ok...
<a4j:jsFunction name="performSelection" action="#{cc.attrs.listenerClass.staticMethodName()}" />
Don't know - perhaps my head is running agains the same wall again and again...

Related

jsf methods expression valuechanged event don't work or work different in inputtext and selectOneMenu

i'm new with jsf technology and use of managed bean.
I'm reading the Java Platform, Enterprise Edition The Java EE Tutorial release 7 but it seems to be not clear, i have different problem how in example below :
<h:selectOneMenu value="#{user.age}" onchange="submit()" valueChangeListener="#{user.ageChanged}">
<f:selectItems value="#{user.ages}" />
<f:converter converterId="javax.faces.Integer"/>
</h:selectOneMenu>
<h:inputText id="name" value="#{user.name}" required="true" validator="#{user.validateName}" valueChangeListener="#{user.nameChanged}" onchange ="submit()" />
the first one do the job, but the second not it displays:
'managedBean.User' does not have the property nameChanged.
but ageChanged is not a property but the first example do the job
but i'm using method expression to refers method nameChanged that it's present on the bean user,
i'm confusing, too with use or not of the bracket on methods expression:
valueChangeListener="#{user.nameChanged}" or valueChangeListener="#{user.nameChanged()}" what is the properly way to use methods expression?
i say this cause in another example having method with no parameters, the two approaches had different behave, first the same error about property missing, the second Apparently worked.
any help? a speak about method expressions it's appreciated to. thank you.

Turn a facelet tag into composite component

Some time ago, based on one of #BalusC answers (really don't know which one of them) I wrote a facelet tag that is a kind of a button generator, that generates a variable number of buttons disposed side-by-side, each one with some parameters passed through the attributes.
Now I want to turn the facelet tag into a composite component (because on the latter, I have the cc:interface tag, that provides information to others developers who wants to use the custom component).
In the rewriting process I must deal with the actions attributes of the dynamically generated buttons. In the facelet tag approach I don't have to declare them as methods, so I can pass their names as simple strings and process them inside the facelet tag also as simple strings and call the action methods. In the composite component approach it seems that I must pass the methods names as actual methods names (by using the method-signature attribute of cc:attribute). The problem is: as I don't know previously the number of buttons (it generates the buttons dinamically), I'm not able to declare the action methods in the cc:interface section.
A simplified version of my working facelet tag is:
<c:set var="idValues" value="#{fn:split(ids,',')}" />
<c:set var="actionValues" value="#{fn:split(actions,',')}" />
<c:set var="numberOfButtons" value="#{fn:length(idValues)}" />
<h:panelGrid id="#{id}" columns="#{numberOfButtons}">
<c:forEach begin="0" end="#{numberOfButtons-1}" varStatus="i">
<p:commandButton id="#{idValues[i.index]}"
action="#{bean[actionValues[i.index]]}" />
</c:forEach>
</h:panelGrid>
and the facelet tag can be used like this:
<my:button id="idButton"
ids="btnSave,btnCancel"
actions="onSave,onCancel"
bean="#{myBean}" />
[EDIT]
As sugested by #BalusC in the answers, adding code like below in the taglib.xml file was enough for the Eclipse autocompletion to work fine:
<tag>
<tag-name>button</tag-name>
<source>tags/bottons.xhtml</source>
<attribute><name>id</name></attribute>
<attribute><name>ids</name></attribute>
<attribute><name>actions</name></attribute>
<attribute><name>bean</name></attribute>
</tag>

Exceptions in actionMethods are packed inside PropertyNotFoundException

We are currently using the OmniFaces FullAjaxExceptionHandlerFactory to redirect any exceptions in the application to a general error page. This page then examines the exception and determines its type so that we can display a particular (and hopefully more helpful) message for certain known error cases.
However, under certain circumstances all we get is a PropertyNotFoundException with no attached causes or details instead of the actual exception that the program throws. This thwarts my attempt to recognize known error cases.
I figured out the circumstances under which this happens: I wrote a composite component that encapsulates an h:commandLink. To pass in the action method I used retargeting like so:
<cc:attribute name="action" targets="link" required="true" />
and, accordingly,
<h:commandLink id="link" value="test" />
This works fine, but as said above: If the action stumbles upon an exception during execution, this original exception will not be handed to the error page. Only a PropertyNotFoundException shows up and tells me, the action method could not be found - without any info about the actual problem.
I tried to pass in the method in a different way, for example as
<cc:attribute name="bean" required="true" />
<cc:attribute name="method" required="true" />
<cc:attribute name="param" />
and
<h:commandLink id="link"
value="test"
action="#{cc.attrs.bean[cc.attrs.method](cc.attrs.param)}" />
In this case I get the right exceptions handed over, but the method fails for cases where the using page does not pass a param. A method like doSomething() will then not be found (IllegalArgumentException). However, I'd rather like to use one component throughout the application with or without parameters instead of forcing some workaround here for the different usages.
Are there other ways to avoid the retargeting approach or can we change something, so that a retargeted method does not result in the unhelpful PropertyNotFoundExecption?
EDIT: If possible, I'd prefer the retargeting, as it's less of an limitation to the use of the component. The above alternative for example would only allow for actions with one parameter. :/
As per comments, this is a known Mojarra issue. We upgraded to Mojarra 2.1.21 and I can confirm that the issue is fixed in this version and exceptions end up in the interface pure and unaltered as the code intended ;)
Thanks for the help!

filtering <rich:column> in composition component

Hopefully someone can help, because I am quite stuck on this issue. I cannot find much help elsewhere...
The high-level goal: creating a custom tag that will aid in the reuse of an extendedDataTable in Richfaces. I have a custom tag that I would like to be similar to:
<mytag:customTable bean="#{myBean}"/>
The (simplified) file that contains code for the table is as follows (table.xhtml)
<!--...header stuff -->
<ui:component>
<a4j:outputPanel>
<h:form>
<rich:extendedDataTable
value="#{bean.theData}"
var="entity"
id="table">
<rich:column filterMethod="#{...}">
<f:facet name="header">
<h:inputText value="#{bean.filterValue}">
<a4j:support event="onkeyup" reRender="table"/>
</h:inputText>
</f:facet>
<h:outputText value="#{entity.item}"/>
</rich:column>
</rich:extendedDataTable>
</h:form>
</a4j:outputPanel>
</ui:component>
Due to the constraints of the application, using the filterBy="#{...}" attribute inside the <rich:column> tag does not give me what I need.
Accordingly, I have to use the filterMethod attribute. When I hardcode the table with,
<rich:column filterMethod="#{bean.filterFunction}">
then everything works fine. However, I would like to keep the tag more general and NOT hardcode this. Instead, I would like
to also pass the name of the filtering function (e.g. <mytag:customTable bean="#{myBean}" flFcn="#{myBean.filterFunction}"> ). The problem is that
I cannot get any version of this to work properly.
From searching other threads, I see that the way to pass a method to an 'action' attribute has a syntax like: action="#{bean[fcnName]}" where fcnName is just a String (see http://digitaljoel.nerd-herders.com/2009/08/25/passing-action-methods-in-facelets-using-array-notation/).
I have confirmed that this way works correctly when it's an action . However,
this does not seem to help me in this case with filterMethod (perhaps b/c the function signature is different?). Based on those solutions, I would need something like:
<mytag:customTable bean="#{myBean}" flFcn="filterFunction"> with <rich:column filterMethod="#{bean[flFcn]}">
I have not found anything among the many permutations of EL syntax that works. Everytime, this approach throws an exception saying that 'bean' resolved to null.
To check that the bean was actually recognized, I had it print a String via <h:outputText value="#{bean.someString}"/>
(removing the offending filterMethod=...)and there is NO problem. Therefore the problem seems to lay entirely on whatever filterMethod receives. I found what I believe to be a very similar issue here, but that does not seem to be answered.
Thanks in advance!
I'm facing the same problem using RichFaces 3.3.3 and JSF 1.2 without having a usable solution.
Found a JIRA-entry at RichFaces which is still open and thus probably will not be fixed anymore.

Iterating List of Lists in JSF view

I'm trying to iterate a List> on my JSF view using ui:repeat tags. It looks like this:
<h:form>
<ui:repeat value="#{myController.currentEntry.pages}" var="page" varStatus="pageStatus">
<p:fieldset rendered="#{myController.currentEntryPage == pageStatus.index}">
<ui:repeat value="#{page}" var="item" varStatus="itemStatus">
<h:outputText value="#{itemStatus.index + 1}. #{item.anotherClass.text}" />
</ui:repeat>
<p:fieldset>
</ui:repeat>
</h:form>
My class Item, located in models package, contains a reference to an object of AnotherClass, also in models package. I have checked in debugger and, just before the redirect to my view is returned, myController.currentEntry.pages is well formed.
I get the following error, however:
javax.servlet.ServletException: /my_view.xhtml #10,109 value="#{itemStatus.index + 1}. #{item.anotherClass.text}": Property 'anotherClass' not readable on type models.AnotherClass
javax.faces.webapp.FacesServlet.service(FacesServlet.java:422)
org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:393)
filters.Auth.doFilter(Auth.java:19)
filters.Encoding.doFilter(Encoding.java:28)
What is this all about? How is JSF managing to map item to item.anotherClass? I know ui:repeat is full of bugs, but none of what I found points to this kind of problem.
Is there any other way to achieve what I'm trying to do? My project uses Primefaces. It is close to the end and even closer to delivery deadline, so switching to another library is not an option.
EDIT:
I've switched to a more elegant solution that doesn't require me to iterate the whole matrix:
<ui:repeat value="#{myController.currentEntryPageItems}" var="item" varStatus="itemStatus">
getCurrentEntryPageItems() being a method that returns myController.currentEntry.pages.get(myController.currentEntryPage).
I would still like to know if 2d iteration can be done with ui:repeat so I'll leave the question open.

Resources