Kuali Rice Development
  1. Kuali Rice Development
  2. KULRICE-6845

Problems with UifBeanFactoryPostProcessor expression handling that is causing bean property overrides (such as fieldInquiry.render) to not work

    Details

    • Type: Bug Fix Bug Fix
    • Status: Closed Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.2.0-rc1, 2.2
    • Component/s: Development
    • Security Level: Public (Public: Anyone can view)
    • Labels:
      None
    • Similar issues:
      KULRICE-8425Problems with UifBeanFactoryPostProcessor expression handling for nested properties and lists prevent bean property overrides (such as fieldInquiry.render) from working
      KULRICE-7384Problem with reloading dictionary and expression factory
      KULRICE-8432Peformance: remove default readOnly expression and handle it code
      KULRICE-12815 Expressions in field labels not carried through for table headers
      KULRICE-5376Uif Framework - Refactor conditional expressions for non String fields
      KULRICE-8295Null handling in DocumentSearchCriteriaBo.groovy needs work
      KULRICE-9079replacing a property that has a spring expression
      KULRICE-7053spring expression error on refresh
      KULRICE-9722Error using spring expressions inside rich messaging components
      KULRICE-7859Spring Expressions in render property not working as expected
    • Rice Module:
      KRAD
    • KAI Review Status:
      Not Required
    • KTI Review Status:
      Not Required

      Description

      The UifBeanFactoryPostProcessor is a Spring bean post processor (http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/beans.html#beans-factory-extension-bpp) that is used to handle expressions defined in beans. These are special property values that contain the @

      {...}

      syntax that the UIF framework uses to evaluate conditional statements. These are allowed for any property type (string, boolean, integer). However, Spring does not know how to handle them. So when spring creates the objects from a bean definition and tries to set a value containing one of these for a non-string type (like boolean) an exception will be thrown (of course the string '@

      {foo}

      ' is not a valid boolean). Therefore we pull these expressions out before Spring creates the objects.

      Basically the post processor iterates through all the container beans and finds ones that implement the Configurable interface. For those that do, it then iterates through all the configured properties and inspects the configured value. If the value has the expression placeholder, it pulls the expression out to a Map. The Map key gives the property name that contained the expression and the Map value is the expression. This Map is then set as a property on the object (named 'propertyExpressions'). The original configured property is then removed (so it appears to Spring as if it was never set). When the view is being processed in code, the expressions are then evaluated and the evaluation result is used to set the property value.

      This sounds simple but is actually very complicated due to bean inheritance. Consider the following example:

      <bean id="MyBean" class="MyClass">
      <property name="field1" value="@

      {1 eq 1}"/>
      </bean>

      <bean id="YourBean" parent="MyBean">
      <property name="field1" value="false"/>
      </bean>

      The UIF processor will first process MyBean, finds the expression, and changes the bean definition to:

      <bean id="MyBean" class="MyClass">
      <property name="propertyExpressions">
      <map>
      <entry key="field1" value="@{1 eq 1}

      "/>
      </map>
      </property>
      </bean>

      Now YourBean doesn't have any expressions, so it is left alone. Spring will now merge these definitions and YourBean becomes:

      <bean id="YourBean" class="MyClass">
      <property name="field1" value="false"/>
      <property name="propertyExpressions">
      <map>
      <entry key="field1" value="@

      {1 eq 1}

      "/>
      </map>
      </property>
      </bean>

      These are two separate properties, so Spring populates them both on the object. Field1 is initially set to false (what we expect it to be). However, since there is an expression in the view processing it will get evaluated, in this case (1 does equal 1) will result in true, so the framework sets field1 to true.

      Therefore when doing the post processing we need to look at the parent bean definition, and if there are any keys of the propertyExpressions Map which match a property configured on the child bean, remove the expression so it does not override the child setting. That is in place and appears to be working.

      But then it gets more complicated, and that is do to nested property configuration. Consider this example:

      <bean id="HisBean" class="HisClass">
      <property name="myBeanRef">
      <bean parent="MyBean"/>
      </property>
      </bean>

      <bean id="HerBean" parent="HisBean">
      <property name="myBeanRef.field1" value="false"/>
      </bean>

      The MyBean is nested in His and Her Beans. The same thing should happen in the nested HerBean object, the expression inherited needs to be cleared. These nested beans though are processed as part of the parent bean, and thus don't have their own standalone bean definition in the container. Furthermore the nested path can be more than two levels, so the beans at each level need to be checked for expressions to clear. This process was started but due to time constraints not finished. (By the way this is why setting fieldInquiry.render to false is not working)

      In UifBeanFactoryPostProcessor there is a method named removeParentExpressionsOnNested whose call is currently commented out. We need to finish the logic on this (if the current logic is doable, needs reviewed) and enable the call.

      I would recommend coming up with many different examples and documenting the post processing. It gets very confusing to keep straight and to make sure we are covering everything.

        Issue Links

          Activity

          Hide
          Jerry Neal (Inactive) added a comment -

          Mostly done, one minor issue with maps

          Show
          Jerry Neal (Inactive) added a comment - Mostly done, one minor issue with maps
          Hide
          Jerry Neal (Inactive) added a comment -

          Work left:

          • spring support of nested map merging
          • expressions in primitive (string) lists not handled correctly
          Show
          Jerry Neal (Inactive) added a comment - Work left: spring support of nested map merging expressions in primitive (string) lists not handled correctly
          Hide
          Jessica Coltrin (Inactive) added a comment -

          moving m4 criticals and blockers to rc1

          Show
          Jessica Coltrin (Inactive) added a comment - moving m4 criticals and blockers to rc1
          Hide
          Jerry Neal (Inactive) added a comment -

          Hey Matt,

          Would you create another issue for the problems we have with the Spring framework and link the spring Jiras. Then we can close this one.

          thanks,
          Jerry

          Show
          Jerry Neal (Inactive) added a comment - Hey Matt, Would you create another issue for the problems we have with the Spring framework and link the spring Jiras. Then we can close this one. thanks, Jerry
          Hide
          Matthew Wuertz (Inactive) added a comment -

          I added a new issue (KULRICE-8425) to address the nesting problems that rely upon Spring fixing their framework.

          Show
          Matthew Wuertz (Inactive) added a comment - I added a new issue ( KULRICE-8425 ) to address the nesting problems that rely upon Spring fixing their framework.

            People

            • Assignee:
              Matthew Wuertz (Inactive)
              Reporter:
              Jerry Neal (Inactive)
            • Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved:

                Structure Helper Panel