Announcement Announcement Module
Collapse
No announcement yet.
Dynamic list binding Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Dynamic list binding

    I have a table of data that I let the user edit. New rows can be added to the form via javascript. When the form is submitted after a new row has been added I get the following error.

    Code:
    org.springframework.beans.InvalidPropertyException: Invalid property 'issues[6]' of bean class [tracker.domain.Volume]: Index of out of bounds in property path 'issues[6]'; nested exception is java.lang.IndexOutOfBoundsException: Index: 6, Size: 6
    	org.springframework.beans.BeanWrapperImpl.getPropertyValue(BeanWrapperImpl.java:697)
    	org.springframework.beans.BeanWrapperImpl.getNestedBeanWrapper(BeanWrapperImpl.java:535)
    	org.springframework.beans.BeanWrapperImpl.getBeanWrapperForPropertyPath(BeanWrapperImpl.java:513)
    	org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:709)
    	org.springframework.beans.BeanWrapperImpl.setPropertyValue(BeanWrapperImpl.java:844)
    	org.springframework.beans.BeanWrapperImpl.setPropertyValues(BeanWrapperImpl.java:871)
    	org.springframework.validation.DataBinder.applyPropertyValues(DataBinder.java:413)
    	org.springframework.validation.DataBinder.doBind(DataBinder.java:320)
    	org.springframework.web.bind.WebDataBinder.doBind(WebDataBinder.java:111)
    	org.springframework.web.bind.ServletRequestDataBinder.bind(ServletRequestDataBinder.java:108)
    	org.springframework.web.servlet.mvc.BaseCommandController.bindAndValidate(BaseCommandController.java:298)
    	org.springframework.web.servlet.mvc.AbstractFormController.handleInvalidSubmit(AbstractFormController.java:578)
    	org.springframework.web.servlet.mvc.AbstractFormController.handleRequestInternal(AbstractFormController.java:235)
    	org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:128)
    	org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:44)
    	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:684)
    	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:625)
    	org.springframework.web.servlet.FrameworkServlet.serviceWrapper(FrameworkServlet.java:386)
    	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:355)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:709)
    	javax.servlet.http.HttpServlet.service(HttpServlet.java:802)
    	org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:172)
    	org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
    I realize I need to increase the size of the list, but I'm not sure where I should be doing it. Has anyone found a solution to adding rows dynamically to a form with javascript, then being able to bind the form?

    I'm using a SimpleFormController if this helps.

  • #2
    You are out of bound of your array. Size is of it 6 and you are indexing issues[6] (allowed 0..5)

    Regards.
    radone

    Comment


    • #3
      Originally posted by radone
      You are out of bound of your array. Size is of it 6 and you are indexing issues[6] (allowed 0..5)
      I understand that. I am adding new items on the jsp page via javascript. so the user can be editing issues[0] - issues[5], and they can also add new ones, issues[6] - issues[n]. My problem is I don't know how to bind these new issues.

      Comment


      • #4
        a "wrong" but easy solution: in the formBackingObject() method pre-pad your array, then trim it down in onSubmit

        a "correct" solution i think would be to use custom property editors. (maybe)

        http://forum.springframework.org/showthread.php?t=9845
        Last edited by robyn; May 16th, 2006, 04:23 AM.

        Comment


        • #5
          Right now, I'm adding new objects as necessary in createBinder, though I'm not really happy with this solution.

          Can anyone post an example of using custom property editors to solve this problem? Any direction would be helpful.

          Comment


          • #6
            how about overriding processFormSubmission()?

            Hi,

            Just ran across the same problem, and I thought of a work around, although it's not ideal.

            But you can also override processFormSubmission() in the controller. Then you can process the request submission and fill out your collection in your bean. After you're done with everything, call super.processFormSubmission() to fill out the rest of the form.

            -Regards

            Comment


            • #7
              Anyone got a custom property editor solution for this? I need help on this too. thanks.
              Last edited by chunhui; Feb 14th, 2006, 01:46 AM.

              Comment


              • #8
                Chunhui,

                Did you by any chance find a custom editor ?

                folks,
                I have a similar problem myself, and I had to resort to getParamValues from the request object in my controllers onSubmit.

                Any better way ?

                Thanks.

                Comment


                • #9
                  Almost elegant solution found.

                  No need in special editor.

                  the solution is easy as 1-2-3.

                  1. Override createBinder in SimpleFormController.
                  Code:
                  ...
                  	protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object command) throws Exception {
                  		ServletRequestDataBinder binder = super.createBinder(request, command);
                  		Voting v = (Voting) command;
                  		BindingList<VotingCode> bl = new BindingList<VotingCode>(VotingCode.class);
                  		bl.addAll(v.getVotingCodes());
                  		v.setVotingCodes(bl);
                  		return binder;
                  	}
                  ...

                  2. After binding is finished remove deleted records, and probably gaps.
                  Code:
                  	protected void doSubmitAction(Object command) throws Exception {
                  		Voting e = (Voting) command;
                  		BindingList<VotingCode> bl = (BindingList<VotingCode>) e.getVotingCodes();
                  		bl.trimToSize();
                  ...........................
                  ...........................
                  	 }
                  3. The classes that do the magic.
                  Code:
                  public class BindingList<E extends Markable> extends ArrayList<E> {
                  	Class cls;
                  	public BindingList(Class operatingClass) {
                  		cls = operatingClass;
                  	}
                  
                  	public boolean addAll(Collection<? extends E> c) {
                  		boolean res = super.addAll(c);
                  		for (E e : this) {
                  			e.setMarked(false);
                  		}
                  		return res;
                  	}
                  
                  	public E get(int index) {
                  		try {
                  			E e = super.get(index);
                  			e.setMarked(true);
                  			return e;
                  		} catch (IndexOutOfBoundsException e) {
                  			try {
                  				while (index >= size()) {
                  					E o = (E) cls.newInstance();
                  					o.setMarked(false);
                  					add(o);
                  				}
                  				return super.get(index);
                  			} catch (InstantiationException e1) {
                  				e1.printStackTrace(); 
                  			} catch (IllegalAccessException e1) {
                  				e1.printStackTrace();
                  			}
                  		}
                  		throw new RuntimeException("Shit happens.");
                  	}
                  
                  	public void trimToSize() {
                  		for (int i = size() - 1; i >= 0; i--) {
                  			  E e = super.get(i);
                  			if (!e.isMarked()) remove(i);
                  		}
                  		super.trimToSize();
                  
                  	}
                  }
                  Code:
                  public interface Markable {
                  	public boolean isMarked();
                  	public void setMarked(boolean marked);
                  }
                  A bit detailed explanation (on russian): http://diesel.elcat.kg/index.php?aut...&showentry=986

                  Comment


                  • #10
                    a hack-around

                    I had similar issue. I solved with code in formBackingObject. See: http://forum.springframework.org/showthread.php?t=22974

                    Comment


                    • #11
                      The real hack
                      Looks like deletion of rows in dynamic table is not handled at all?

                      Comment


                      • #12
                        use commons-collections!

                        Using the lazy types of supplied by commons-collections:

                        List myList = ListUtils.lazyList(relations,FactoryUtils.instanti ateFactory(FormGraph.class));

                        the list will automatically be extended when non-existing entries are referenced.

                        There are all sorts of lazy types:

                        http://jakarta.apache.org/commons/co...ase/index.html

                        Comment


                        • #13
                          Originally posted by abstraction
                          I understand that. I am adding new items on the jsp page via javascript. so the user can be editing issues[0] - issues[5], and they can also add new ones, issues[6] - issues[n]. My problem is I don't know how to bind these new issues.
                          With Spring 2.0-M5, I believe that the binding will happen automatically if you use an ArrayList, instead of an array, in your bean class. You also won't have to worry about an index out of bounds exception. (I am assuming that you are using an array, as opposed to an ArrayList, already.)

                          Comment


                          • #14
                            Originally posted by sergey_wba
                            The real hack
                            Looks like deletion of rows in dynamic table is not handled at all?
                            I wrote my own function to trim out rows that were deleted using JavaScript:

                            public class InsertPurchaseSaleController extends SimpleFormController {
                            protected ModelAndView onSubmit(Object command, BindException errors)
                            throws Exception {
                            PurchaseSale purchaseSale = (PurchaseSale) command;
                            // Since JavaScript could have deleted some values, we need
                            // to clean any null values out of the list.
                            trimList(purchaseSale.getImages());
                            // ...
                            return new ModelAndView(getSuccessView(), "purchaseSale", purchaseSale);
                            } // end onSubmit()

                            public void trimList(List images) {
                            for (Iterator it = images.iterator(); it.hasNext(); ) {
                            Object element = it.next();
                            if(element == null)
                            it.remove();
                            } // end for loop
                            } // end trimList()
                            } // end class

                            Comment


                            • #15
                              Aha good to know! haven't used spring2 yet... looking forward!

                              Comment

                              Working...
                              X