ICEfaces
  1. ICEfaces
  2. ICE-5577

Sparkle metadata UIData row dependant properties

    Details

    • Type: New Feature New Feature
    • Status: Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.0-Alpha2
    • Fix Version/s: 2.0-Beta2, 2.0.0
    • Component/s: ICE-Components
    • Labels:
      None
    • Environment:
      ICEfaces 2
    • Affects:
      Documentation (User Guide, Ref. Guide, etc.)

      Description

      In ICEfaces 1.8, we employ several strategies for saving component fields, when in a UIData container, so that the field value will be distinct per UIData row. Sometimes we keep a Map<String clientId, Object field> and sometimes we use the SeriesStateHolder interface. In OutputResource, we found that we could not use the clientId, since if the OutputResource was in a UIData whose data model was having insertions or deletions, then the clientIds would not match up any more, which would break both of the previously mentioned strategies. One strategy that seems to work well, in all scenarios, is using settable properties, and making the app store the value in the row level object. The worst strategy is doing nothing, and applications unexpectedly failing.

      Whichever strategy we use, it would be nice if we could just specify that a property should be unique per UIData row, and have the generator create the appropriate getter and setter methods to handle that.

        Issue Links

          Activity

          Hide
          Mark Collette added a comment -

          My recommendation is that we use a combination of settable properties and the Map<String clientId, Object value>. This all has to work with JSF 2's StateHelper class, which our properties use for storing their state in. The implementation of which is in: mojarra2\jsf-api\src\main\java\javax\faces\component\ComponentStateHelper.java

          In the setter method, we could see if there's a ValueExpression, and if so use it. Otherwise we fall through to using the StateHelper. If we then use the PropertyKeys field as the key, we would get a Map<String clientId, Object value>. If that doesn't exist, create it and put it back into the StateHelper. Then put the value into the map using the clientId as the key.

          In the getter method, first try seeing if the StateHelper has the Map, using the PropertyKeys field as the key, if so, see if there's a value in the Map, using the clientId as the key. If not, then fall back to seeing if there's a ValueExpression, and evaluating it. If not, return the default value.

          Show
          Mark Collette added a comment - My recommendation is that we use a combination of settable properties and the Map<String clientId, Object value>. This all has to work with JSF 2's StateHelper class, which our properties use for storing their state in. The implementation of which is in: mojarra2\jsf-api\src\main\java\javax\faces\component\ComponentStateHelper.java In the setter method, we could see if there's a ValueExpression, and if so use it. Otherwise we fall through to using the StateHelper. If we then use the PropertyKeys field as the key, we would get a Map<String clientId, Object value>. If that doesn't exist, create it and put it back into the StateHelper. Then put the value into the map using the clientId as the key. In the getter method, first try seeing if the StateHelper has the Map, using the PropertyKeys field as the key, if so, see if there's a value in the Map, using the clientId as the key. If not, then fall back to seeing if there's a ValueExpression, and evaluating it. If not, return the default value.
          Hide
          Mark Collette added a comment -

          I think that the default should be for properties to do this. Either they will always do this, or maybe we could optionally to do it the old/basic way. It would be nice to know the impact on partial state saving, doing it the new way, versus the pre-existing way, to see if we need make the old way optional, or just discard it.

          Show
          Mark Collette added a comment - I think that the default should be for properties to do this. Either they will always do this, or maybe we could optionally to do it the old/basic way. It would be nice to know the impact on partial state saving, doing it the new way, versus the pre-existing way, to see if we need make the old way optional, or just discard it.
          Hide
          Greg Dick added a comment -

          I have changes to the generator code checked in. Testing should determine if there are any regressions.

          Show
          Greg Dick added a comment - I have changes to the generator code checked in. Testing should determine if there are any regressions.
          Hide
          Greg Dick added a comment -

          The strategy for using the StateHelper had a slight wrinkle. If a row level component had a default value, the default value is set on the component during the time of execution when the defaults are being defined. After this default setting phase has passed, the framework 'marks' the component and any subsequent puts on the StateHelper are stored in the deltaMap. The problem with looking for our map and instantiating it if missing and adding it to the StateHelper during initialization is that it wont get persisted by state saving.

          The solution was to create a map for default values and adding it to the component at default setup time, and then creating a separate instance of the values map and adding it to the stateHelper during the lifecycle if necessary for the row level values so it winds up in the delta map and gets state saved.

          One last wrinkle is that JSF moves the value map into the default map after a state saving cycle in the restoreView phase. This means that to continually persist state row values, the value map needs to be re-added to the stateHelper each time a row value changes otherwise it wont be persisted even though we're changing the contents of the map.

          Show
          Greg Dick added a comment - The strategy for using the StateHelper had a slight wrinkle. If a row level component had a default value, the default value is set on the component during the time of execution when the defaults are being defined. After this default setting phase has passed, the framework 'marks' the component and any subsequent puts on the StateHelper are stored in the deltaMap. The problem with looking for our map and instantiating it if missing and adding it to the StateHelper during initialization is that it wont get persisted by state saving. The solution was to create a map for default values and adding it to the component at default setup time, and then creating a separate instance of the values map and adding it to the stateHelper during the lifecycle if necessary for the row level values so it winds up in the delta map and gets state saved. One last wrinkle is that JSF moves the value map into the default map after a state saving cycle in the restoreView phase. This means that to continually persist state row values, the value map needs to be re-added to the stateHelper each time a row value changes otherwise it wont be persisted even though we're changing the contents of the map.

            People

            • Assignee:
              Greg Dick
              Reporter:
              Mark Collette
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: