Announcement Announcement Module
Collapse
No announcement yet.
'Rebind' form bean values in webflow after submit. What's wrong? Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • 'Rebind' form bean values in webflow after submit. What's wrong?

    Hi guys.
    I'm using spring-framework-3.2.0.RELEASE, spring-webflow-2.3.1.RELEASE with Spring Security, Thymleaf template engine + Tiles2 support.

    I have sub-flow inside a 'main execution flow' and I'm trying to create 'view/add/edit' functionality in sub-flow for form bean and entity behind it.

    The problem I'm facing is following.
    I can render entity from formBean on page, I modify DOM tree by JS code and then changed data is posted to webflow. When I try to save that 'updated' formBean after 'POST' made from page, I'm getting 'previous' data rather then data 'POSTED' by browser.

    I have following sub-flow definition:
    Code:
        <input name="venueForm" required="false" type="com.web.form.venue.FormBeanVenueField" />
    
        <on-start>
            <evaluate expression="venuePlaceController.initializeForm()" result="flowScope.venueForm"/>
        </on-start>
    
        <view-state id="showMap" view="event/registerEvent/selectVenue/showMap" model="venueForm">
            <on-render>
                <evaluate expression=............... />
            </on-render>
            <transition on="create" to="createVenue"/>
            <transition on="select" to="endVenueFieldOk"/>
            <transition on="edit" to="editVenue"/>
        </view-state>
    
        <view-state id="createVenue" view="event/registerEvent/selectVenue/addVenue" model="venueForm">
            <on-render>
            </on-render>
            <transition on="cancel" to="showMap" validate="false"/>
            <transition on="save" to="showMap">
                <evaluate expression="venuePlaceController.saveVenuePlace(
                                externalContext, flowScope.venueForm, messageContext)"/>
            </transition>
        </view-state>
    
        <view-state id="editVenue" view="event/registerEvent/selectVenue/addVenue" model="venueForm">
            <on-entry>
                <evaluate expression="venuePlaceController.initializeFormByVenueId(flowScope.venueForm)"
                       result="flowScope.venueForm"/>
            </on-entry>
            <on-render>
                 ............
            </on-render>
            <transition on="save" to="showMap">
                <evaluate expression="venuePlaceController.saveVenuePlace(
                     externalContext, venueForm, messageContext)"/>
            </transition>
        </view-state>
    ..............
    Here is a simplified code for clarity.
    Code:
    public class FormBeanVenueField implements Serializable {
        private String venueId; // selected venue Id
        private List<String> venueFieldNames = new ArrayList<>(0);
    ............ // the rest is skipped
    }
    
    @Controller
    public class VenuePlaceController {
        public FormBeanVenueField initializeForm() {
               FormBeanVenueField  venueForm = new FormBeanVenueField();
        }
    
        public FormBeanVenueField initializeFormByVenueId(FormBeanVenueField venueForm) {
            if (venueForm != null && venueForm.getVenueId() != null && !venueForm.getVenueId().isEmpty()) {
                // get Entity by Id from database and create form bean
                venueForm = new FormBeanVenueField(entity);
            }
            return venueForm;
        }
    
        public org.springframework.webflow.execution.Event saveVenuePlace(
                ExternalContext externalContext,
                @Valid FormBeanVenueField formBean, MessageContext messageContext) {
    
              // make form bean validations and return result
    
            if (formBean.venueFieldNames.size() <= 0) { // break point HERE to view received data 
               ....... // generate error 
                MessageBuilder errorMessageBuilder = new MessageBuilder().error();
                messageContext.addMessage(errorMessageBuilder.build());
                return new EventFactorySupport().error(this);
            }
            ........
            // when all is ok, create Entity from 'form bean' data and save entity to database
            return new EventFactorySupport().success(this);
        }
    }
    HTML code is written by thymeleaf library syntax. Here is simplified: event/registerEvent/selectVenue/addVenue.html
    I use that page for 'create' and 'edit' cases.
    Code:
            <form method="post" th:action="${flowExecutionUrl}" action='' th:object="${venueForm}" id="form">
    ............
               <input type="text" name="venueFieldNames[0]" value="0" />
               <input type="text" name="venueFieldNames[1]" value="1" />
               <input type="text" name="venueFieldNames[2]" value="2" />
    
               <button id="cancelBtn" type="submit" name="_eventId_cancel" >Cancel</button>
               <button id="saveBtn" type="submit" name="_eventId_save" >Save</button>
            </form>

    1. The state <view-state id="createVenue".. works fine. I can render a 'empty' page. Add several 'input controls' to DOM model by JS code and then submit all data by 'onclick' handler on 'Save'. The data comes to saveVenuePlace(.......) method and save to DB.


    2. When I try <view-state id="editVenue" .... state I don't get correct data which actually submitted by page AFTER data editing and DOM model modifications.

    Say, I have several 'input' controls rendered by <view-state id="editVenue" .... state on page initially.
    Then I modify DOM model by JS code and POST changed data, say only ONE input value, to state. I can see only ONE input data (venueFieldNames[1]=1) posted to my 'editVenue' state.


    The problem I have... I see ALL three input data values (instead on one) on break point inside method :

    public org.springframework.webflow.execution.Event saveVenuePlace(.......) {
    if (formBean.venueFieldNames.size() <= 0) {
    .......
    }

    So it looks like... 1) data posted by page is not bind to form bean, 2) binded form bean values are overwritten by webflow and I get 'initial data' instead of 'updated data' from page.


    Most probably, there is something I don't know about webflow. Is it possible to make such functionality ? How better to solve that issue?
    Last edited by blandger; Mar 1st, 2013, 08:49 AM.

  • #2
    When I'm stopping at break point specified in code above in previous post (red line), I can see correct parameters submitted from page to webflow controller code inside variable:
    Code:
    public org.springframework.webflow.execution.Event saveVenuePlace(
                ExternalContext externalContext,
                @Valid FormBeanVenueField formBean, MessageContext messageContext) {
    ..
           externalContext.getRequestParameterMap();
    Map externalContext.getRequestParameterMap() definitely contains all changed data submitted from page.
    But those values are NOT 'rebound' to @Valid FormBeanVenueField formBean instance.

    I'd like to understand that and know how make it work?

    Comment


    • #3
      Up
      Can someone suggest something ? What Am I do wrong?

      Comment


      • #4
        Could anybody say, how do you process/bind INDEXED property values in your webflow apps?
        Especially I'm interested how to work with 'indexed properties' when you have 'unknown quantity' of possible UI elements ? How properly map those elements to form bean indexed property ?

        Code:
        <form:form modelAttribute="orderForm" action="${flowExecutionUrl}">
            <input type='text' name='myItem[0]' value='0'/>
        ......
            <input type='submit'..../>
        </form:form>
        Here is a form bean:
        Code:
        public class OrderForm implements Serializable {
           private List<Integer> myItem = new ArrayList<Integer>();
        }
        I would like to add more <input ...> elements dynamically, so they would be properly bound to 'orderForm.myItem' list.
        Say I'm add more elements by JS code:
        Code:
          <form.......
            <input type=''text' name='myItem[1]' value='1'/>
            <input type=''text' name='myItem[2]' value='2'/>
            <input type=''text' name='myItem[4]' value='4'/>
          ......
          </form>
        As you can see there is 'myItem[3]' is missing. That is because it could be added by JS code and then removed by JS code BEFORE form is being submitted to server.

        If I try to submit that indexed data I'm getting 'index out of bound' exception.
        As variant I can get error: evaluationException on myItems[0].propertyName If I use more complex object on: List<MyClass> myItem with some properties.

        How properly do or configure such type of binding ?

        spring-framework-3.2.0.RELEASE, spring-webflow-2.3.1.RELEASE, spring-webmvc-3.2.0-RELEASE

        I found threads about similar issue but they are old (2004, 2005 year).
        http://forum.springsource.org/showth...rties-checkbox
        http://forum.springsource.org/showth...-checkbox-list

        I found one more thread with similar question, but I'm not quite happy with solution there:
        http://forum.springsource.org/showth...on-form-submit

        Can someone suggest good solution?
        Looks like nobody use indexed properties with beans
        Nobody knows, ha-ha
        Last edited by blandger; Mar 12th, 2013, 04:59 PM. Reason: added one more possible error, added one more thread

        Comment


        • #5
          How properly do 'Binding parameterized / indexed property'

          Ok, I'm continue...Dancing with myself (song by Billy Idol, 1981)
          http://4.bp.blogspot.com/_rJBmix_SFs...ence-poesy.jpg


          OMG
          Just in 2006 year people could help to each other. How fast time is passing...

          Spring become more complex and there are almost few people who can give advice, but despite of that they are moving to Spring v.4 !!!

          But those topics are not quite helpful now

          Creating complex Domain Objects from Web MVC
          http://forum.springsource.org/showth...-Web-MVC/page2

          Binding Custom Object to Collection
          http://forum.springsource.org/showth...dexed+property

          Binding checkboxes to Enums and possible bug in Booking demo
          http://forum.springsource.org/showth...dexed+property
          This is a known limitation with today's EL-based binding systems.
          The Spring BeanWrapper can do this type of conversion when binding to parameterized lists; however it's only enableable in Spring MVC view environments. To turn it on, configure the "useSpringBeanBinding" flag on a custom MvcViewFactoryCreator instance.

          Spring EL will generally solve this problem in the Spring Framework 3.0 timeframe.

          Keith
          (Looks like it's still limitation......)


          I'm still curious if I should go with:
          PropertyEditor
          http://static.springsource.org/sprin...ty-editors-tbl
          or
          should I go with
          Spring 3 Type Conversion
          http://static.springsource.org/sprin...l#core-convert
          or with
          Customizing WebDataBinder initialization
          http://static.springsource.org/sprin...-webdatabinder

          or may be kick off Spring approach and make custom code like:
          Complex forms & Springs’ ServletRequestDataBinde
          http://log4p.com/2006/05/31/complex-...estdatabinder/

          Comment


          • #6
            indexed data, indexed property, parameterized properties, parameterized property

            WOW, YAHOOOOO
            I've found freaky good and simple solution for 'indexed data' and 'parameterized properties' used in form bean class.
            It's easy to avoid 'index out of bound' exception after dynamic adding form elements by JS code.

            Thank you very much all who viewed that thread hundred times and couldn't give any advice.

            Comment


            • #7
              Whats "good and simple solution for 'indexed data' and 'parameterized properties' " that you have discovered? I had the same issues for addition of dynamic input element using JS with Web Flow....Please suggest any workaround that you can help with?

              Comment


              • #8
                I've already explained solution in following thread:
                http://forum.springsource.org/showth...-dynamic-sizes
                That is really common problem and nobody want's to share experience on that.

                Comment

                Working...
                X