Using forms and items

Hey.

I’ve been dabbling with Forms lately, and what I noticed in it was that I always use BeanItems as item datasource for the Forms. That raised me the question: Are everybody doing it in the same way or are there some other nifty things that you can do with forms that I am not aware of. Please share a bit of information on how you use those Forms yourself.

and explain when use what and why? I am really confused with Vaadin data model and forms :frowning:

Hi!

I am totally lost with Vaadin Data bindings and forms, even if I read that part from the Vaadin book. I have a small training software where is one page and there is 4 tabs in the tabsheet. Tabsheet is like a process so after user has filled every tab, the data shoud go to the database and fill the correct tables.

Could someone tell me when to use ObjectProperty, BeanItem, when PropertySetItem, when Containers? What is the wisest and why in my case? I know that I can use form as an item but I have pojos inside pojos and It doesn’t understand nested pojos (I think).

Tab1:

  • I have 8 fields in that page from 3 POJOs (3 tables in database as well)
  • There is nested pojos too, so for instance inside AddressPOJO there is CityPOJO and CountryPOJO etc.

QUESTION1: I am using textfields, so is it wise to take (getValue()) value from those fields one by one and collect them to correct objects (nested pojos) and transfer those to SQLContainer or what?

QUESTION2: Should I use ObjectProperty and collect the data to that and transfer it to SQLContainer?

QUESTION3: Should I bind textfields, comboboxes and checkboxes straight to the SQLContainer? How?

QUESTION4: If I use SQLContainer, how can I bind data from those pojos to different tables (fields, checkboxes etc to fields in different tables in database)?

QUESTION5: Where is the source code of Address book demo (Database version)? I found only in memory version, not database version?

Could you give me simple example how to make a nice form with nested pojos and explain why it is the best way to do it like that :slight_smile:

ARGGGHHH
Sami

+1

Thank you Jens for bringing that up. I personally think this is a very important point which needs clarification.

I am kind of new to Vaadin myself. Currently I am at the state of finding out how to use forms and, much more important, how to communicate with the backend (database) before commit() takes place. In my case commit() should only be fired if database processing was successful.

I was searching the Vaadin forum to find out how to solve this. Turns out that I am not the only one who is having a hard time on this. Unfortunately, as fare as I can see, actually no one has or knows how to deal with it.


http://vaadin.com/forum/-/message_boards/view_message/168437


http://vaadin.com/forum/-/message_boards/view_message/522321


http://vaadin.com/forum/-/message_boards/view_message/255793

Kurt

Hi all!

I can also share some of my experiences with Vaadin forms. I have to admit that Vaadin Forms are bit tricky to get started with. But after I have used them enough I kind of like them (a little). My thoughts are below (but some of those might not be the best practises).

  • I rarely use BeanItems
  • I very often use the CustomField add-on, I think it is quite necessary for constructing good forms.
  • Some times it might be wise to wrap your datasource into custom item class by extending the Vaadin Item.
    (* I implement the FormFieldFactory)
  • If the form is not very simple, extending the Vaadin Form class to some MyForm class (overriding the attachField method) gives you extra flexibility.
  • If you override the attachField method you can also more easily use different layouts (like the AbsoluteLayout) for the Form

Hi!

I am totally lost with Vaadin Data bindings and forms, even if I read that part from the Vaadin book. I have a small training software where is one page and there is 4 tabs in the tabsheet. Tabsheet is like a process so after user has filled every tab, the data shoud go to the database and fill the correct tables.

Could someone tell me when to use ObjectProperty, BeanItem, when PropertySetItem, when Containers? What is the wisest and why in my case? I know that I can use form as an item but I have pojos inside pojos and It doesn’t understand nested pojos (I think).

Tab1:

  • I have 8 fields in that page from 3 POJOs (3 tables in database as well)
  • There is nested pojos too, so for instance inside AddressPOJO there is CityPOJO and CountryPOJO etc.

Hello Sami.

I have a little bit hard grasping on what level you are since you clearly have done a bit with forms already. What I suggest to you is that you create a separate form with an BeanItem on every tab, and use setVisibleItemProperties(Object) to decide which fields should be visible in which form. Let’s leave the use of SQLContainer out so far as this is about forms. Let’s just say that you get beans out of you database which you give into forms, the forms modify them, and then you take care to get the data from the beans back into the database.

I would say that it is smarter to have the item of the form directly coupled to the bean. That way, when you call form.commit(), all the values of all fields are moved back to the bean. Just do BeanItem item = new BeanItem(myPojo); to get an item out of your bean.

To handle nested properties, you can use
CustomField
from the directory, or NestedMethodProperty to get the properties of the nested bean like this:

BeanItem<Person> personItem = new BeanItem<Person>(person);
personItem.addItemProperty("Street", new NestedMethodProperty(person, "postalAddress.street"));
personItem.addItemProperty("City", new NestedMethodProperty(person, "postalAddress.city"));
personItem.addItemProperty("Country", new NestedMethodProperty(person, "postalAddress.country"));
form.setVisibleItemProperties(new Object[] { "name", "dateOfBirth", "email", "Street", "City", "Country" });
form.setItemDataSource(personItem);

Person has a field PostalAddress postalAddress; which contains the strings street, city and country.

I haven’t used SQLContainer but it might be a valid case to just use the item you get from there to populate the form. Don’t know if it is enough to call form.commit() to get the data all the way into the database, or if you have to call separately some table.commit() or something like that after it.

Haven’t used ObjectProperty, can’t say.

I’d just use commit() which will put all the values into the bean, and store the bean into the database separately.

Same as earlier, as long as you have the beans, you don’t have to worry about the backend connection.

Don’t know. Maybe someone else can answer this, or you could browse the sources at dev.vaadin.com.

Hope that helps.

Hi Kurt!

Usually you commit() first which moves that data to the item/bean/whatever the form is connected to, and after that take care of the database commiting. If db commit fails, you may have to reload the data, depending on the case.

However, if you really really have to do db commit before form commit, how about overriding the commit method of the form? in your own version of that method, you start by doing your db magic, and as the last row you call super.commit();. That way you can do what ever you want before the real commiting starts when you call form.commit();

Hey Johannes.

I also override attachField quite often because that is the only way to effectively handle layouting of forms.

If you rarely use BeanItems, what implementation of Item do you use and why?

Thank you for you answer, Jens. Overriding commit() is what I am doing since yesterday. Works perfect.

However I hope some people will post some other stuff on how they are using FormS etc. I for myself use BeanItemS as datasource for FormS as you do and override attachField() if needed.

Please do not double post the same message. Replying here as others have, marked the other thread as duplicate.

Normally, you use a Container, ask for an item from the container and set that item as the data source for the form. Depending on the container, in some cases you might need to take additional actions after form commit e.g. to save the item to a database - for this, see the container you are using. Many containers do this automatically as long as you are working with the item instance you got from the container, though.

Some containers do support nested properties directly. If I remember correctly, SQLContainer supports these in the form of SQL joins.

If the container you are using does not support nested properties, you might need to resort to some tricks to get the nested properties to show.

As for the different item and property classes, I avoid creating any instances of them myself if possible. Instead, I get the items from the container (not caring about their type if possible) so the item and the container stay synchronized automatically.

Is
this
what you are looking for? It also contains examples of what you want to do except nesting.

Hi!

I tried that one and still stupid like a donkey :frowning:

I have a companyPOJO:

public class Company implements java.io.Serializable {

private static final long serialVersionUID = 4134898774853905662L;
private short companyId;
private Address address;
private String companyName;
private Set branchs = new HashSet(0);
private Set customers = new HashSet(0);
private Set staffs = new HashSet(0);

I am doing a use case where user is adding a new company to the empty database. I know how to use SQLContainer now and it is working, but I can’t implement working form at all. I tried it like that:

Company company = new Company();

	BeanItem<Company> companyItem = new BeanItem<Company>(company);
	companyItem.addItemProperty("Address1", new NestedMethodProperty(company, "Address.address1"));
	companyItem.addItemProperty("Address2", new NestedMethodProperty(company, "Address.address2"));
	companyItem.addItemProperty("Zip", new NestedMethodProperty(company, "Address.zip"));
	companyItem.addItemProperty("City", new NestedMethodProperty(company, "Address.City.city"));
	
	
	ComboBox combobox = new ComboBox("Select country");
	combobox.setContainerDataSource(dbHelper.getCountryContainer());
	combobox.setItemCaptionPropertyId("country");
	combobox.setNullSelectionAllowed(false);
	combobox.setImmediate(true); 
	
	basicInfoForm.setVisibleItemProperties(new Object[] { "Address1", "Address2", "Zip", "City" });
	basicInfoForm.setItemDataSource(companyItem);
	basicInfoForm.addField("combobox", combobox);
	
	
	Button okbutton = new Button("OK", basicInfoForm, "commit");

and I got this (
look at the picture file attached
)


QUESTIONS:

  1. Why there is more fields than just those four (basicInfoForm.setVisibleItemProperties(new Object { “Address1”, “Address2”, “Zip”, “City” });)?
    ----------->I just recognized that order does matter, so I had to set data source first, then set the visible properties.
  2. How can I get the combobox after the city field? ( I am fetching those countries from database)
  3. Why there is errors after all of the nested properties? Error message below.
  4. I have 4 tabs in the tabsheet. I am going to save that companyPOJO through the whole process and after the last 4. tab, I will store it to the database. So what is the mechanism (like httpSession) where can I store objects between pages (tabs in this case)?
  5. How can I change labels/caption of one field like from Address1 to Address line 1 etc when using BeanItem?


Errormessage in nested property:

com.vaadin.data.util.MethodProperty$MethodException
at com.vaadin.data.util.NestedMethodProperty.invokeSetMethod(NestedMethodProperty.java:234)
at com.vaadin.data.util.NestedMethodProperty.setValue(NestedMethodProperty.java:214)
at com.vaadin.ui.AbstractField.commit(AbstractField.java:241)
at com.vaadin.ui.Form.commit(Form.java:339)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.vaadin.event.ListenerMethod.receiveEvent(ListenerMethod.java:500)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:164)
at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1193)
at com.vaadin.ui.Button.fireClick(Button.java:539)
at com.vaadin.ui.Button.changeVariables(Button.java:206)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariableBurst(AbstractCommunicationManager.java:1299)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1219)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:735)
at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:296)
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:501)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:304)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:240)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:164)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:462)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:164)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:100)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:562)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:395)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:250)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:188)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:302)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:680)
Caused by: java.lang.NullPointerException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at com.vaadin.data.util.NestedMethodProperty.invokeSetMethod(NestedMethodProperty.java:230)
… 34 more

Thanks a lot, I am still trying even if I am almost going back to Struts etc, my learning curve is just too gently :frowning:
Sami

11761.png

As you noticed, calling setItemDataSource will iterate the items properties and reset them, so any modfications done, like setVisibleItemProperties, will be reset.

You need to override attachFIeld to be able to layout the field yourselves. This was one the reasons why I started this thread.

My guess without closer look at your project would be that big A you have in “Address.address1” etc.

Call commit after every step so the data will be moved to the company object, or have a reference to all the forms in the last step and call commit on all of them at once when the user presses the finish button.

getField(“property name”).setCaption(“new caption”);

I tried that:

companyItem.addItemProperty("[b]
companyName
[/b]", new ObjectProperty(null, String.class));
basicInfoForm.getField("[b]
companyName
[/b]").setCaption("new companyName");

Nothing really happend!

Thanks a lot for helping me, this is a little bit frustrating (both of us I think) at the moment, but I hope that this will be useful in future :slight_smile: Good nerves to you!

4.7.2011 More than one week and nothing is working so I think that Vaadin is just too complicated to me. I can’t implement even basic form with nested properties (new NestedMethodProperty), couple of combo boxes and 6 textfields. Using for instace Struts this is couple of hours work so this is not for me :frowning: Now I am just starting to wonder why you are using this one, nice UIs or what, because learning curve is flat in my case, no good manuals, no good examples with comments etc. Could you make a demo-software what is using data base, and there is just one form with different fields, nested properties (pojo inside the pojo), dropdowns, selections etc and writing, deleting and updating data. It should be quite small work to you and in many case , helps a lot!