[JAVASERVERFACES-2588] clientbehavior rendered multiple times with nested composite components Created: 12/Nov/12  Updated: 08/Jan/14  Resolved: 14/Oct/13

Status: Closed
Project: javaserverfaces
Component/s: None
Affects Version/s: 2.1.14
Fix Version/s: 2.2.5

Type: Bug Priority: Major
Reporter: chris_dezide Assignee: Manfred Riem
Resolution: Works as designed Votes: 1
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Attachments: Zip Archive test.zip    
Issue Links:
Related
is related to JAVASERVERFACES-2839 composite component umbrella task Closed

 Description   

Hi,

I'd like to have a couple of composite components: "toolbar" and "editor".

The toolbar is used in several edit pages, but can also be nested within the editor component.

I need ajax behavior on some pages, so I have the toolbar declare a clientbehavior like this:

toolbar.xhtml: <cc:clientBehavior name="save" targets="toolbarSaveBtn" event="action" />

When I use the toolbar directly in pages everything is fine, but if I attempt to nest the toolbar into the editor component and "bridge" the clientbehavior with:

editor.xhtml: <cc:clientBehavior name="save" targets="toolbar" event="save" />

(Where toolbar is the toolbar component id).

The containing page has:

<form>
<editor:editor id="editor">
<f:ajax event="save" listener="#

{backingBean.saveNew}

" execute="@form" render="@all"
</editor:editor>
</form>

When the toolbar internals are "inlined/copied" directly into "editor" it behaves like expected, when I put the toolbar into the editor component I see my listener getting triggered multiple (4 i think) times per click on the toolbar button.

When I do a view source in the browser it looks like the client behavior has been included twice in "onclick".



 Comments   
Comment by Manfred Riem [ 12/Nov/12 ]

Can you please attach an example application (with sources) and no external dependencies that demonstrates the problem?

Comment by chris_dezide [ 12/Nov/12 ]

I've manged to create a minimalistic example (maven project) that illustrates what I'm seeing.

You can run it with: "mvn jetty:run-war"

Clicking the first save button / cancel link works (toolbar directly included in page). Clicking second save button results in the listener being triggered twice - the second cancel link does not do this, so I assume it is a h:commandButton "feature".

I noticed that the nested component seemed to work properly if there was just one clientbehavior bound for the toolbar save button. In the actual code where I see the error, we have more than one client behavior bound - So I added a "Cancel" link with a clientbehavior to the sample project and then the Save button started resulting in double submits.

I really hope this can get fixed as it makes it really hard to create building blocks for more complex pages.

Comment by chris_dezide [ 26/Nov/12 ]

Hi, dug a little more into this.

I'm pretty sure it is a mojarra bug as it works in myfaces and as the order of the unrelated <f:ajax> behaviors influences the faulty behavior (first defined behavior, screws up).

This is really a big blocker for our project, not being able to create/use components with externalized ajax behavior totally destroys the component-oriented approach. Having to copy the same complex code/templates around for every component use, just to get different ajax behavior is a maintenance nightmare waiting around the corner.

Anyway here are my findings:

Original case from attached project
<a:editor>
	<f:ajax event="save" listener="#{backingBean.saveClicked}"/>
	<f:ajax event="cancel" listener="#{backingBean.cancelClicked}"/>
</a:editor>

Results in:
<input id="j_idt5:j_idt9:toolbar:saveBtn" type="button" onclick="jsf.util.chain(this,event,'mojarra.ab(this,event,\'action\',0,0)','mojarra.ab(this,event,\'action\',0,0)');return false" value="Save" name="j_idt5:j_idt9:toolbar:saveBtn">
<a id="j_idt5:j_idt9:toolbar:cancelLnk" onclick="mojarra.ab(this,event,'action',0,0);return false" href="#">Cancel</a>

Notice the jsf.util.chain chaining the same behavior twice.

Behavior order swapped
<a:editor>
	<f:ajax event="cancel" listener="#{backingBean.cancelClicked}"/>
	<f:ajax event="save" listener="#{backingBean.saveClicked}"/>
</a:editor>

Results in:
<input id="j_idt5:j_idt9:toolbar:saveBtn" type="button" onclick="mojarra.ab(this,event,'action',0,0);return false" value="Save" name="j_idt5:j_idt9:toolbar:saveBtn">
<a id="j_idt5:j_idt9:toolbar:cancelLnk" onclick="jsf.util.chain(this,event,'mojarra.ab(this,event,\'action\',0,0)','mojarra.ab(this,event,\'action\',0,0)');return false" href="#" name="j_idt5:j_idt9:toolbar:cancelLnk">Cancel</a>

Notice that the faulty chaining now happens on the cancelLnk instead.

Comment by Manfred Riem [ 26/Mar/13 ]

Can you reproduce the problem with the latest 2.1 release?

Comment by chris_dezide [ 27/Mar/13 ]

Yes, the last release 2.1.20 also exhibits the faulty behavior.

Comment by Manfred Riem [ 02/May/13 ]

Can you verify against the latest 2.1.22-SNAPSHOT?

Available from https://maven.java.net/content/repositories/snapshots/org/glassfish/javax.faces/

I am unable to reproduce it with that version.

Thanks!

Comment by chris_dezide [ 08/May/13 ]

Hi,

Just found the time to get the sample up and running with the snapshot repo.

I still see the original error with the 2.1.22 snapshot as of now. I get the server-error below twice ( and the generated javascript still contains a chain that results in two attempted calls).

And the snapshot seems even more broken, none of the event handlers are resolvable. Clicking a button yields:

serverError: class javax.el.PropertyNotFoundException /index.xhtml @13,73 listener="#

{backingBean.saveClicked}

": Target Unreachable, identifier 'backingBean' resolved to null

Comment by Manfred Riem [ 14/Oct/13 ]

The way you have structured your nested component it will indeed trigger the listener multiple times as it will be added to both the editor and the toolbar.

Comment by chris_dezide [ 21/Oct/13 ]

Hi,

I can live with this feature being "by-design", but would you please explain how to obtain the behavior I expect in Mojarra?

I want to create a composite component (the editor) which internally uses a toolbar component that is also used in other parts of the system.

The behavior of the toolbar in an editor in a given page should be linked to methods in the backing bean for the page declaring the editor.

  • Or are you saying that Mojarra is not designed to fully support nesting of composite components?

By the way my sample code works like I expect with MyFaces.

Comment by Manfred Riem [ 21/Oct/13 ]

In the top-level component pass it as an attribute defined in the editor, then in the editor pass it again then as a clientBehavior.

Comment by chris_dezide [ 21/Oct/13 ]

Thank you for the quick response.

I'm not familiar with any way of passing a "<f:ajax />" client behavior into a <f:attribute>,
are you suggesting that I pass all the f:ajax attributes (potentially 7-8 per behavior I want to pass to inner component) manually?

Btw. I can see that I managed to work around the issue by passing in the complete, configured toolbar using <cc:insertChildren/> and
an attribute specifying the name of a javascript object that the behaviors collaborate with.

I still think the behavior that myfaces exhibits, is the one that I would expect, but that may just be me.

Generated at Mon May 25 20:35:40 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.