MyFaces Core
  1. MyFaces Core
  2. MYFACES-1492

valueChangeListener is being called before the setters, even with immediate="true"

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Invalid
    • Affects Version/s: 1.1.4
    • Fix Version/s: 1.1.4
    • Component/s: General
    • Labels:
      None

      Description

      valueChangeListener is being called before the setters, even with immediate="true".
      This is not the right behavior since it overwrites any property modified in the event handler.

      <t:panelGrid columns="2" cellpadding="0" cellspacing="5px" columnClasses="left top, left top">
      <t:outputLabel for="infoId" value="Options"/>
      <t:selectOneMenu id="infoId" value="#

      {productBean.infoId}

      " onchange="submit()" valueChangeListener="#

      {productBean.valueChangedHandler}

      " immediate="true">
      <f:selectItem itemValue="-1" itemLabel="<new short info>"/>
      <f:selectItems value="#

      {productBean.shortInfoSelectItems}

      "/>
      </t:selectOneMenu>

      <t:outputLabel for="descText" value="Description"/>
      <t:inputTextarea id="descText" rows="8" value="#

      {productBean.description}

      "/>

      <t:outputLabel for="utilText" value="Usage"/>
      <t:inputTextarea id="utilText" styleClass="wXXXL" rows="8" value="#

      {productBean.usage}

      "/>
      </t:panelGrid>

      public class ProductBean {

      private Long infoId;
      private String description;
      private String usage;

      // .... setters and getters for the above properties

      public void valueChangedHandler(ValueChangeEvent event) {
      Long infoId = (Long) event.getNewValue();
      if ((infoId != null) && (infoId > 0))

      { //DataService and ProductInfo are related to Hibernate ProductInfo info = DataService.getProductInfo(infoId); this.description = info.getDescription(); this.usage = info.getUsage(); }

      }
      }

      Description and Usage properties can never be changed since they get overwritten with the initial values.
      ((((((((((((((((((((((((

        Activity

        Hide
        Cagatay Civici added a comment -

        This is the nature of the JSF lifecycle, try calling renderResponse of FacesContext to avoid the lifecycle to overwrite the values you've changed in the valuechangelistener.

        Show
        Cagatay Civici added a comment - This is the nature of the JSF lifecycle, try calling renderResponse of FacesContext to avoid the lifecycle to overwrite the values you've changed in the valuechangelistener.
        Hide
        Mircea Zahan added a comment -

        Already tryed that, the getters are not called because the view is not re-created.

        Anyway, this lifecycle is wrong, the documentation says that with immediate="true" the event would be fired after the setters.
        I quote from myfaces doc:
        "A boolean value that identifies the phase during which value change events should fire. During normal event processing, value change events are fired during the "invoke application" phase of request processing. If this attribute is set to "true", these methods are fired instead at the end of the "apply request values" phase."

        AND DAMN, YOU ARE QUICK ON SETTING ISSUES ON INVALID. GIVE IT SOME THINKING BEFORE YOU DO IT !!!!!!!

        Show
        Mircea Zahan added a comment - Already tryed that, the getters are not called because the view is not re-created. Anyway, this lifecycle is wrong, the documentation says that with immediate="true" the event would be fired after the setters. I quote from myfaces doc: "A boolean value that identifies the phase during which value change events should fire. During normal event processing, value change events are fired during the "invoke application" phase of request processing. If this attribute is set to "true", these methods are fired instead at the end of the "apply request values" phase." AND DAMN, YOU ARE QUICK ON SETTING ISSUES ON INVALID. GIVE IT SOME THINKING BEFORE YOU DO IT !!!!!!!
        Hide
        Mircea Zahan added a comment -

        Mr. Cagatay Civici, don't be so quickhanded on setting issues on invalid !!!!

        Show
        Mircea Zahan added a comment - Mr. Cagatay Civici, don't be so quickhanded on setting issues on invalid !!!!
        Hide
        Mircea Zahan added a comment -

        The doc quote above was about the "immediate" attribute.

        Show
        Mircea Zahan added a comment - The doc quote above was about the "immediate" attribute.
        Hide
        Cagatay Civici added a comment -

        Well first of all please take it easy, you seem stressed a little bit

        I don't get what you mean by "Already tryed that, the getters are not called because the view is not re-created". The doc you've pasted is wrong, "invoke application" should be replaced by "process validations", the doc should be fixed.

        Show
        Cagatay Civici added a comment - Well first of all please take it easy, you seem stressed a little bit I don't get what you mean by "Already tryed that, the getters are not called because the view is not re-created". The doc you've pasted is wrong, "invoke application" should be replaced by "process validations", the doc should be fixed.
        Hide
        Mario Ivankovits added a comment -

        I've never seen valueChangeEvents fired during the "invoke application" phase, and yes, I too think the documentation is wrong here. See [1] for a documentation with what matching my knowledge.

        So, one solution can be to use the valueChangeNotifier (tomahawk sandbox), its events are fired AFTER the update model phase (regardless of the immediate attribute) and thus should work as expected.

        Hope this helps ...

        [1] http://www.oracle.com/webapps/online-help/jdeveloper/10.1.3/state/content/navId.4/navSetId._/vtTopicFile.jsf_apps%7Ceventvalidate%7Csf_aev_valuechange~html/

        Show
        Mario Ivankovits added a comment - I've never seen valueChangeEvents fired during the "invoke application" phase, and yes, I too think the documentation is wrong here. See [1] for a documentation with what matching my knowledge. So, one solution can be to use the valueChangeNotifier (tomahawk sandbox), its events are fired AFTER the update model phase (regardless of the immediate attribute) and thus should work as expected. Hope this helps ... [1] http://www.oracle.com/webapps/online-help/jdeveloper/10.1.3/state/content/navId.4/navSetId._/vtTopicFile.jsf_apps%7Ceventvalidate%7Csf_aev_valuechange~html/
        Hide
        Martin Marinschek added a comment -

        Cagatay was absolutely right in closing this...

        regards,

        Martin

        Show
        Martin Marinschek added a comment - Cagatay was absolutely right in closing this... regards, Martin
        Hide
        Mircea Zahan added a comment -

        Ok, let me summarize, looks like some people do not read carefully

        1. I tried calling renderResponse() from inside the listener, it's not helping because the getters won't get called. So it's useless.
        2. I emphasize the following piece from the doc I pasted: "If this attribute is set to "true", these methods are fired instead at the end of the "apply request values" phase." In real life, the immediate attribute has no effect on the time the event is fired. The way I see it the doc is right and the implementation is wrong. It's common sense. I don't care "this is the nature of the JSF life cycle", firing the event before the setters it's plain wrong.

        So, will you choose doing some quality work or will you choose getting stuck in fixed ideas ?
        And yes, I'm a little bit stressed because, in my opinion, you didn't consider to realy understand the problem, which, in some users' opinion, is critical, hence the priority of the issue. Just google for this one, see how big is the issue.

        I really hope this is not my last post here, but it's certainly going that direction.

        Thank you for your time.

        Special thanks to Mario Iankovits, the only one who really did read what I was writing.

        Show
        Mircea Zahan added a comment - Ok, let me summarize, looks like some people do not read carefully 1. I tried calling renderResponse() from inside the listener, it's not helping because the getters won't get called. So it's useless. 2. I emphasize the following piece from the doc I pasted: "If this attribute is set to "true", these methods are fired instead at the end of the "apply request values" phase." In real life, the immediate attribute has no effect on the time the event is fired. The way I see it the doc is right and the implementation is wrong. It's common sense. I don't care "this is the nature of the JSF life cycle", firing the event before the setters it's plain wrong. So, will you choose doing some quality work or will you choose getting stuck in fixed ideas ? And yes, I'm a little bit stressed because, in my opinion, you didn't consider to realy understand the problem, which, in some users' opinion, is critical, hence the priority of the issue. Just google for this one, see how big is the issue. I really hope this is not my last post here, but it's certainly going that direction. Thank you for your time. Special thanks to Mario Iankovits, the only one who really did read what I was writing.
        Hide
        Mario Ivankovits added a comment -

        Now, please, let us try not to heat up this situation any more.
        We're all nice guys, stressed by our day jobs and more often then not our nerves are overwought.

        Well, Mircea, next time, please start in our myfaces-user [1] mailinglist.
        Developer sometimes ... often ... always (? ) tend to knee-jerk reactions when new JIRA tickes come in without having them discussed on the mailinglist before - Dont treat it personal. JIRA should not be used to start off new discussions.

        Have a nice day!
        Ciao,
        Mario

        [1] http://myfaces.apache.org/mail-lists.html

        Show
        Mario Ivankovits added a comment - Now, please, let us try not to heat up this situation any more. We're all nice guys, stressed by our day jobs and more often then not our nerves are overwought. Well, Mircea, next time, please start in our myfaces-user [1] mailinglist. Developer sometimes ... often ... always (? ) tend to knee-jerk reactions when new JIRA tickes come in without having them discussed on the mailinglist before - Dont treat it personal. JIRA should not be used to start off new discussions. Have a nice day! Ciao, Mario [1] http://myfaces.apache.org/mail-lists.html
        Hide
        Mircea Zahan added a comment -

        Being given the gravity of the problem, I considered it's worth opening a JIRA issue.
        Looks like I'm the only one considering this one critical.

        So, back to mailing lists.

        Thanx again for your time.

        Show
        Mircea Zahan added a comment - Being given the gravity of the problem, I considered it's worth opening a JIRA issue. Looks like I'm the only one considering this one critical. So, back to mailing lists. Thanx again for your time.
        Hide
        Martin Marinschek added a comment -

        Hi Mircea,

        why shouldn't your getters be called if you call renderResponse?

        Of course they will be called in the rendering phase, as they are supposed to be. The only getters which will not be called are getters which are bound to binding="..." attributes. If the getters wouldn't be called even if the tree is not recreated, we couldn't build dynamic JSF pages, and all of us sure do.

        I suggest reading Core JSF on this topic - you'll find a nice example there explaining the issue with the valueChangeListeners.

        regards,

        Martin

        Show
        Martin Marinschek added a comment - Hi Mircea, why shouldn't your getters be called if you call renderResponse? Of course they will be called in the rendering phase, as they are supposed to be. The only getters which will not be called are getters which are bound to binding="..." attributes. If the getters wouldn't be called even if the tree is not recreated, we couldn't build dynamic JSF pages, and all of us sure do. I suggest reading Core JSF on this topic - you'll find a nice example there explaining the issue with the valueChangeListeners. regards, Martin
        Hide
        Mario Ivankovits added a comment -

        Martin,

        it looks like the "not called getter" is a known "feature" http://forum.java.sun.com/thread.jspa?threadID=720889

        Though, not sure if this thread tells the truth ...

        Show
        Mario Ivankovits added a comment - Martin, it looks like the "not called getter" is a known "feature" http://forum.java.sun.com/thread.jspa?threadID=720889 Though, not sure if this thread tells the truth ...
        Hide
        Martin Marinschek added a comment -

        Ah,

        now I know what you're talking about - you're talking about a dynamically bound value to an input-field. So the specific case of the "value" attribute of the EditableValueHolder-Interface.

        Well, for an input-field, the submitted value by the user always takes precedence, and the getter will never be called again - only if you call

        myComp.setSubmittedValue(null);
        myComp.setValue(null);
        myComp.setLocalValueSet(false);

        (you can do this iteratively for a block of components, well, not with UIData-instances)

        you can make sure that the getter really gets called for the value-attribute of this field.

        regards,

        Martin

        Show
        Martin Marinschek added a comment - Ah, now I know what you're talking about - you're talking about a dynamically bound value to an input-field. So the specific case of the "value" attribute of the EditableValueHolder-Interface. Well, for an input-field, the submitted value by the user always takes precedence, and the getter will never be called again - only if you call myComp.setSubmittedValue(null); myComp.setValue(null); myComp.setLocalValueSet(false); (you can do this iteratively for a block of components, well, not with UIData-instances) you can make sure that the getter really gets called for the value-attribute of this field. regards, Martin
        Hide
        Mircea Zahan added a comment -

        They just aren't. Try it and see for yourself. Use my example above, no binding attributes in it.
        And I am talking about the particular case of calling renderResponse() from valueChangeListener method.

        But let's not stray from the main issue: firing the event before the setters. It's ... unnatural, twisted.

        In theory everything is (frustratingly) wonderful

        I already read Geary & Horstmann's book, but hey, I don't want to be stuborn, so I'll read the sugested section
        again. But I doubt that I'll find an argument for firing the event before the setters.

        Thank you and best regards,
        Mircea.

        Show
        Mircea Zahan added a comment - They just aren't. Try it and see for yourself. Use my example above, no binding attributes in it. And I am talking about the particular case of calling renderResponse() from valueChangeListener method. But let's not stray from the main issue: firing the event before the setters. It's ... unnatural, twisted. In theory everything is (frustratingly) wonderful I already read Geary & Horstmann's book, but hey, I don't want to be stuborn, so I'll read the sugested section again. But I doubt that I'll find an argument for firing the event before the setters. Thank you and best regards, Mircea.
        Hide
        Mario Ivankovits added a comment -

        I too find its "strange" that they fire the event before the update_model phase ... I'll say thats the "technical point of view", hmmm, and maybe you can use it to veto this particular change ... is this possible?

        Anyway, thats why we developed the valueChangeNotifier ..... so everything is wonderful again :-D

        Show
        Mario Ivankovits added a comment - I too find its "strange" that they fire the event before the update_model phase ... I'll say thats the "technical point of view", hmmm, and maybe you can use it to veto this particular change ... is this possible? Anyway, thats why we developed the valueChangeNotifier ..... so everything is wonderful again :-D
        Hide
        Mircea Zahan added a comment -

        So "the submitted value by the user always takes precedence".
        I can really live with that. As I was saying before is common sense.

        But I can't live with the way the event is fired. I'm repeating myself intentionally.

        And Mario, I will use valueChangeNotifier (didn't try it yet) but this looks to
        me like a nice looking patch glued over an ugly hole No offence intended
        for anyone. Not to mention the redundancy, which is a bad thing,
        any way you look at it.

        The way I see things, I would repair the hole instead of patching it.
        The simplest things are the most efficient ones.

        Kind regards,
        Mircea.

        Show
        Mircea Zahan added a comment - So "the submitted value by the user always takes precedence". I can really live with that. As I was saying before is common sense. But I can't live with the way the event is fired. I'm repeating myself intentionally. And Mario, I will use valueChangeNotifier (didn't try it yet) but this looks to me like a nice looking patch glued over an ugly hole No offence intended for anyone. Not to mention the redundancy, which is a bad thing, any way you look at it. The way I see things, I would repair the hole instead of patching it. The simplest things are the most efficient ones. Kind regards, Mircea.
        Hide
        Mario Ivankovits added a comment -

        Well, you know, there is a JSF spec, we cant do anything which makes our implementation behave different from the spec.
        We have to pass TCK tests.

        Show
        Mario Ivankovits added a comment - Well, you know, there is a JSF spec, we cant do anything which makes our implementation behave different from the spec. We have to pass TCK tests.
        Hide
        Martin Marinschek added a comment -

        Hi Mircea,

        we're implementing a specification here - we cannot implement the basic valueChangeListener differently, the way it works is laid out in the spec. As for a reason, look at Mario's last posting and my response to him down below.

        You'll have to go bug the spec-group over on dev.java.net to fix this ugly hole, as you want to call it...

        @Mario: yes, you can revert the change, by resetting the submitted-value and then calling renderResponse.

        regards,

        Martin

        Show
        Martin Marinschek added a comment - Hi Mircea, we're implementing a specification here - we cannot implement the basic valueChangeListener differently, the way it works is laid out in the spec. As for a reason, look at Mario's last posting and my response to him down below. You'll have to go bug the spec-group over on dev.java.net to fix this ugly hole, as you want to call it... @Mario: yes, you can revert the change, by resetting the submitted-value and then calling renderResponse. regards, Martin
        Hide
        Mircea Zahan added a comment -

        WOW. That didn't cross my mind

        In this case I owe appologies to everyone involved in this discussion, especially to Cagatay.

        But it would have been good from him to say in the first line "it's the specs, dude"

        I will dig the specs then and bug the guys who wrote it, because it really bugs me.

        Thank you all for your patience,
        Mircea.

        Show
        Mircea Zahan added a comment - WOW. That didn't cross my mind In this case I owe appologies to everyone involved in this discussion, especially to Cagatay. But it would have been good from him to say in the first line "it's the specs, dude" I will dig the specs then and bug the guys who wrote it, because it really bugs me. Thank you all for your patience, Mircea.
        Hide
        Cagatay Civici added a comment -

        No problem By the way I've fixed the error in the doc. Mircea as a quick fix you may try the component approach with the binding attribute and try setting the values of the descText-utilText in your value change listener. Hope you got my point.

        Show
        Cagatay Civici added a comment - No problem By the way I've fixed the error in the doc. Mircea as a quick fix you may try the component approach with the binding attribute and try setting the values of the descText-utilText in your value change listener. Hope you got my point.
        Hide
        Mircea Zahan added a comment -

        Yes, I got your point. Hope it works, I'll test it today.

        Thanx again,
        Mircea.

        Show
        Mircea Zahan added a comment - Yes, I got your point. Hope it works, I'll test it today. Thanx again, Mircea.

          People

          • Assignee:
            Cagatay Civici
            Reporter:
            Mircea Zahan
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development