I am having problems getting an action of a managed bean to be called when certain other JSF elements from custom composite components are present in the same page as the h:commandButton that submits the h:form. I can narrow down the page elements that cause problems to those that perform the following harmless (to me) looking rendering tests:
<h:panelGroup rendered="#{not empty cc.attrs.element}">
or:
<h:panelGroup rendered="#{empty cc.attrs.element}">
where 'element' is a required attribute, loaded from a JPA entity by id. Something about that 'empty cc.attrs.element' or 'not empty cc.attrs.element' test blocks correct form submission and blocks action calling in any h:form in which it appears.
The form submission page debug.xhtml is:
<f:view>
<f:metadata>
<f:viewParam name="id" value="#{elementController.id}"/>
</f:metadata>
</f:view>
<h:head>
<title>DEBUG</title>
</h:head>
<h:body>
<h:form>
<util:view_link element="#{elementController.selected}"/>
<h:commandButton value="Apply" action="#{elementController.reflect}" />
</h:form>
</h:body>
Note the view parameter 'id' that via ElementController.setId will force the loading of the 'selected' or 'current' Element entity by id from JPA, not shown here. This should then move to test.xhtml via the action reflect():
@JSFaction
public Object reflect() {
String $i = "reflect";
log_debug($i);
if (current==null) {
log_warn($i, "can't generate reflect outcome for null current element");
return null;
}
//return "reflect?faces-redirect=true&includeViewParams=true&id="+current.getId();
//return "test?faces-redirect=true&includeViewParams=true&id="+current.getId();
//return "reflect?id="+current.getId();
return "/test?faces-redirect=true&id="+current.getId();
}
You can see above I have experimented with different outcome URLs, but it turns out the problem has nothing to do with that, it is simply that the action is not called at all (when the {not empty cc.attrs.element} test is performed in another page element.
The composite component that causes the problem is my util:view_link::
<composite:interface>
<composite:attribute name="element" required="true" type="com.greensoft.objectdb.test.entity.Element"/>
<composite:attribute name="name" required="false"/>
<composite:attribute name="showOwnerAsText" required="false" default="false"/>
<composite:attribute name="showModelClass" required="false" default="false"/>
<composite:attribute name="showEntityClass" required="false" default="false"/>
<composite:attribute name="showId" default="false"/>
<!--composite:attribute name="showHelp" required="false" default="false"/-->
<!--composite:attribute name="title" required="false"/-->
</composite:interface>
<composite:implementation>
<h:panelGroup rendered="#{empty cc.attrs.element}">
<span class="warn">NULL</span>
</h:panelGroup>
<h:panelGroup rendered="#{not empty cc.attrs.element}">
<h:panelGroup rendered="#{cc.attrs.showOwnerAsText}">
<h:outputText style="font-weight:bold" value="#{cc.attrs.element.owner.name}."/>
</h:panelGroup>
<h:panelGroup rendered="#{cc.attrs.showId}">
<h:link outcome="/view" value="<#{cc.attrs.element.id}>">
<f:param name="id" value="#{cc.attrs.element.id}"/>
</h:link>
</h:panelGroup>
<h:link outcome="/view"
value="#{empty cc.attrs.name ? cc.attrs.element.name: cc.attrs.name}"
>
<f:param name="id" value="#{cc.attrs.element.id}"/>
</h:link>
</h:panelGroup>
</composite:implementation>
You can see this is just a reusable way of creating a link to each Element, with the database id passed as parameter. If there is no Element a "NULL" is shown.
By commenting out bits at a time (bracketing) I can prove the problem has something to do with rendered="#{empty cc.attrs.element} and rendered="#{not empty cc.attrs.element} tests, which both prevent form submission and the action from being invoked by a h:commandButton in the same composed page (see debug.xhtml above). If for example I just use plain h:panelGroup elements without the 'rendered="#{empty cc.attrs.element}' and 'rendered="#{not empty cc.attrs.element}' tests, everything displays fine and the h:commandButton works as expected and the action is called ok, and the navigation works fine !
Q: Why does test 'rendered="#{empty cc.attrs.element}' or 'rendered="#{not empty cc.attrs.element}' prevent correct form submission and stop the action from being called ?
Grateful for ideas, Webel
EDIT: The problem only happens when I test on elementController.selected, where .selected is an @Entity Element. I tried it with a simple Duummy class with String name property, and a @RequestScoped DebugController, and it worked fine (the action was called).
<h:panelGroup rendered="#{not empty debugController.dummy}">
<h:outputText value="#{debugController.dummy.name}"/>
</h:panelGroup>
<h:commandButton value="Apply" action="#{elementController.reflect}" />
Reported as bug: http://java.net/jira/browse/JAVASERVERFACES-2343