This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
I have used <form:form> before on an object but never with an object that contains a Set of objects.
For example, I have a Person object with attributes such as id, firstname, lastname, email, and a Set of Programs.
The Program object contains the attributes: id, code, name, date, status
If I have a form that is bound to the Person object with a checkbox of their Program.status how do I set the path of the <form:checkbox> to link with the Program's "status" attribute? Say the "status" contains a Yes/No value... if I want to bind the user's value of checkbox to the Program.status I have no idea how to bind this attribute.
Thanks for your assistance, I think I almost got it but I think I may need a little more clarification.
I think my issue now may be the way that I am using the checkboxes..perhaps my logic is not correct.
So right now I have my form
Here are my objects
My viewController is working fine and takes me to my jsp form but the processing of my form is failing. Once I click on submit I get this error:
org.springframework.orm.hibernate3.HibernateSystemException: IllegalArgumentException occurred while calling setter of com.domain.Person.programs; nested exception is org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.domain.Person.programs
Caused by: org.hibernate.PropertyAccessException: IllegalArgumentException occurred while calling setter of com.domain.Person.programs
Caused by: java.lang.IllegalArgumentException: argument type mismatch
My idea is to populate program.status with a "Yes" when checked. By default, the value of program.status is "No". But it just doesn't make sense to me how that value "Yes/No" is passed through <form:checkboxes>. I have been reading different examples but I can't seem to get it right.
Here is my submitController that is processing the results which I'm sure is incorrect:
My table data looks like this
Spring will only send the ids for the programs that are checked. Also any field not bound to the form (using path) as part of the form or as a hidden field is not sent. You will need to register a custom property editor or use a converter to get the submitted id's to actual role objects. Your error is due to the fact that Spring does not know how to do that conversion without you specifying it.
I have been reading several examples and I think it's almost there. I created my InitBinder and CustomPropertyEditor and I am no longer getting the argument mismatch instead I am getting this error:
Caused by: org.springframework.validation.BindException: org.springframework.validation.BeanPropertyBindingResult: 1 errors
Field error in object 'person' on field 'programs': rejected value ; codes [methodInvocation.person.programs,methodInvocation.programs,methodInvocation.java.util.List,methodInvocation]; arguments [org.springframework.context.support.DefaultMessageSourceResolvable: codes [person.programs,programs]; arguments ; default message [programs]]; default message [Property 'programs' threw exception; nested exception is org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [com.domain.ProgramEditor]: No default constructor found; nested exception is java.lang.NoSuchMethodException: com.domain.ProgramEditor.<init>()]
I'm thinking it's because the form is passing a list of programs from the checkboxes and maybe it doesn't know how to translate it?
This is what I have now:
And here is my PropertyEditor:
Is there something else I need to add that I'm not considering?
Can you show me the code where you create programEditor? It looks like from the stack trace that it is expecting ProgramEditor to have a default constructor for some reason. This should not be necessary unless you are not passing in IPersonStore when you create it.
You might have other issues but lets try to solve this one first. I don't see the need to implement InitializingBean. Lets try this: (note I did not see an @Controller annotation so I added it. Typically you would have a component scanner scanning this package in your context. Not sure why it was not there). The setters are also not necessary so I removed them.
Now, I'm just a little confused now how to use it. After I check one of the boxes and click submit I see my Hibernate query statement which is retrieving the program id correctly. So, is it here in my CustomEditor that I need to set the value of status='Yes' and not in my actionAddProgramForm() method?
Hibernate: select program0_.id as id1_, program0_.name as name1_, program0_.code as code1_, program0_.status as status1_, program0_.endDate as endDate1_, program0_.pid as pid1_ from program program0_ where program0_.id='92'
Here is the new editor that I used that is no longer giving me an error:
I feel so close to having this working...I'm so excited
I guess if the goal is to set the status to "Yes" whenever a checkbox is checked your could set it there.
I assume when you say "Should I use a hibernate method that sets the "status" attribute here? " You mean just call the setter right?
Assuming cascade rules are set up correctly you could just iterate the returned <Set> and add them to your persons program collection and then persist/merge the person which would also update that status at that point. Anyway good luck.
Joined: Feb 10, 2009
Thanks Bill so much for your help and guiding me through this challenge. Last night I finally got everything working...woohoo!