This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.
Currently, the Visual Web Pack requires that every component event correspond to a property of type MethodBinding. The association is specified in the component's BeanInfo, using a constant defined by the Design-Time API. When the user choses to implement a handler for an event (e.g. by double-clicking on an action component in order to create an action handler), a handler method for the event is created in the page bean, and the corresponding property is updated such that its value contains a method binding expression pointing to the newly injected method. This strategy for supporting JSF component events has a number problems. * The "property events" (e.g. the "actionListener" property present on all action components) that were present in JSF 1.1 were deprecated in JSF 1.2. As of JSF 1.2, it is expected that all event handlers specified in a JSP are done so via a listener tag that is a child of the component tag. * The co-existence of both the event and its corresponding property on the properties sheet confuses users. * When more than one handler is registered for the same event, and one of those is referenced via the event property, it is not specified in which order the handlers will be invoked.
The semantics of binding expressions as used in the so-called "event properties" is different than that of the binding expressions used in tags for event listeners. The event property takes a method binding, and the only requirement is that the bound method conform to the signature of the method defined by the listener for that event (the standard JSF event listener interfaces, ActionListener and ValueChangeListener, define only one method per interface). The standard event listener tags, ActionListenerTag and ValueChangeListenerTag, have a property that binds them to an instance of a class that implements the ActionListener or ValueChangeListener interface, respectively. The default listener tags are not suited to our current event handling strategy, since we support events not by creating a new instance of a class that implements the event listener interface, but rather by injecting a method into the page bean. However, instead of saving the binding to this injected method as a the value of an "event property", we could save it as the value of a property on a special event listener tag. This tag would be made the child of the component tag, and in that it would look just like other event tags like ActionListenerTag of ValueChangeListenerTag. However, this tag would not correspond to a component. Upon evaluation of the JSP, the tag class would create an instance of a listener whose handler method wraps a call to the bound handler method, and add the instance to the component's list of event listeners. The JSP fragment for a button and its action listener might look something like this: <webuijsf:button binding="#{Page1.button1}" id="button1"> <f:actionListenerWrapper method="#{Page1.button1_action}"/> </webuijsf:button> Initially, the wrapper tags could be defined by Visual Web Pack, but we should consider suggesting these as additions for JSF 2.0. If Visual Web Pack were to support events in this way, the Design-Time API could be simplified, as the mechanics needed to associated events with properties would no longer be needed. This would also greatly simplify the annotation processor used for component development. Quite a bit of logic is needed to generate these associations.
I was able to use tags and classes already provided by JSF to hook up an event-handling method. The ActionListenerTag and ValueChangeListenerTag can be used to associate their parent tag's component with a property that returns the appropriate action listener. There are also concrete listener classes provided in JSF 1.2, MethodExpressionActionListener and MethodExpressionValueChangeListener, which can be used to wrap a method expression. To handle a button action, in the page bean I added the following: public ActionListener getButton1ActionListener() { MethodExpression methodExpression = this.getApplication().getExpressionFactory().createMethodExpression( FacesContext.getCurrentInstance().getELContext(), "#{Page1.button1_action}", null, new Class[] {ActionEvent.class}); return new MethodExpressionActionListener(methodExpression); } public void button1_action(ActionEvent event) { this.staticText1.setText("Action occurred"); } In the JSP I added: <webuijsf:button binding="#{Page1.button1}" id="button1"> <f:actionListener binding="#{Page1.button1ActionListener}"/> </webuijsf:button> A strategy like this would provide support for the actions defined by JSF, however, it is not readily extensible to other, custom actions.
Changing this in to enhancement as it is actually an enhancement, not a defect. Inteterestingly, in Creator 1.0 we had the same strategy as Grgory mentioned about creating Action Listener (hidden inside the folds of constructor). Then for Creaor 2 we moved on to use the simple "action" property, which looked simple for Creator Users. But with power users like NB users for VWP, it makes sense to revert back.