I want to use a BeanItem with an enum property on a Form with a ComboBox for that enum property. I use setItemDataSource(beanItem) for setting the bean for that form.
For building this Form from the beans properties I extended the DefaultFieldFactory.
My question is, how can bind the selected ComboBox-Value to the BeanItem-Property when the form is committed (form.commit()).
I allways get the error:
Exception
com.vaadin.data.Property$ConversionException: java.lang.NoSuchMethodException: de.saarland.lzd.mis.business.Informationsart.(java.lang.String)
at com.vaadin.data.util.MethodProperty.setValue(MethodProperty.java:716)
at com.vaadin.ui.AbstractField.commit(AbstractField.java:242)
at com.vaadin.ui.Form.commit(Form.java:336)
at de.saarland.lzd.mis.ui.informationsempfaenger.InformationsempfaengerForm$2.buttonClick(InformationsempfaengerForm.java:59)
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:487)
at com.vaadin.event.EventRouter.fireEvent(EventRouter.java:161)
at com.vaadin.ui.AbstractComponent.fireEvent(AbstractComponent.java:1154)
at com.vaadin.ui.Button.fireClick(Button.java:371)
at com.vaadin.ui.Button.changeVariables(Button.java:193)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.handleVariables(AbstractCommunicationManager.java:1094)
at com.vaadin.terminal.gwt.server.AbstractCommunicationManager.doHandleUidlRequest(AbstractCommunicationManager.java:590)
at com.vaadin.terminal.gwt.server.CommunicationManager.handleUidlRequest(CommunicationManager.java:266)
at com.vaadin.terminal.gwt.server.AbstractApplicationServlet.service(AbstractApplicationServlet.java:476)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)
Caused by: java.lang.NoSuchMethodException: de.saarland.lzd.mis.business.Informationsart.(java.lang.String)
at java.lang.Class.getConstructor0(Class.java:2706)
at java.lang.Class.getConstructor(Class.java:1657)
at com.vaadin.data.util.MethodProperty.setValue(MethodProperty.java:709)
... 29 more
I would be glad if someone could help me. Thanks.
Sorry for my english,
Thomas
Here is the class from which I build the BeanItem:
@Entity
@Table(name = "informationsempfaenger")
public class Informationsempfaenger extends DomainObject {
private static final long serialVersionUID = -5838470992191901480L;
@Column(name = "bez", length = 128, nullable = false)
private String bezeichnung;
@Enumerated(EnumType.ORDINAL)
@Column(length = 1)
private Informationsart artDerInformation;
@Column(name = "email", length = 128, nullable = false)
private String email;
@SuppressWarnings("unused")
private Informationsempfaenger() {
super();
}
public Informationsempfaenger(Long id, int version, Date erstellung,
Date aktualisierung, String letzterBearbeiter, boolean geloescht,
String bez, String email, Informationsart artDerInformation) {
super(id, version, erstellung, aktualisierung, letzterBearbeiter,
geloescht);
assert bez != null : "bez darf nicht null sein";
assert bez.length() != 0 : "laenge von bez darf nicht 0 sein";
assert email != null : "email darf nicht null sein";
assert email.length() != 0 : "laenge von email darf nicht 0 sein";
assert artDerInformation != null : "artDerInformation darf nicht null sein";
this.bezeichnung = bez;
this.email = email;
this.artDerInformation = artDerInformation;
}
... setter and getter Methods
@Override
public String toString() {
return getBezeichnung() + "(" + getEmail() + ")";
}
@Override
public boolean equals(Object obj) {
if (!super.equals(obj)) {
return false;
}
final Informationsempfaenger other = (Informationsempfaenger) obj;
if (!bezeichnung.endsWith(other.bezeichnung)) {
return false;
}
if (!email.endsWith(other.email)) {
return false;
}
if (!artDerInformation.equals(other.artDerInformation)) {
return false;
}
return true;
}
@Override
public int hashCode() {
int hash = super.hashCode();
hash = 97 * hash + bezeichnung.hashCode();
hash = 97 * hash + email.hashCode();
hash = 97 * hash + artDerInformation.hashCode();
return hash;
}
}
Here is my enum:
public enum Informationsart {
IT_BESCHAFFUNG(1),
DMS_TEAM(2),
GEHEIMSCHUTZBEAUFTRAGTER_MDF(3),
PERSONALRAT(4);
private int ART;
Informationsart(int art) {
this.ART = art;
}
@Override
public String toString() {
if (ART == 1) {
return "IT-Beschaffung";
}
if (ART == 2) {
return "DMS-Team";
}
if (ART == 3) {
return "Geheimschutzbeauftragter des MdF";
}
if (ART == 4) {
return "Personalrat";
}
return "";
}
}
If I remember correctly, if the actual and wanted value types are not compatible, fields perform a standard “conversion” by calling (via reflection) a constructor of the desired type that takes as a parameter the toString() result of the given value. With enums, as they cannot be created from outside the enum itself, this always causes a problem unless the item ID in the select component is the actual enum value.
The first option (if practical) would be to make the item IDs in the combo box be the enum values themselves e.g. by using a BeanItemContainer for the combo box. This way, no conversions should be required.
Alternatively, to perform your own conversions, take a look at FieldWrapper in the
CustomField add-on.
The first option would be to use a BeanItemContainer in the ComboBox - I think toString() will be used by default if you don’t specify an item caption property, and you could also specify explicit captions for each item in the combo box if you want.
If you need any conversions (the FieldWrapper/PropertyConverter option), I don’t have an example with enums but it should be similar to
this one .
Ok, I solved it by wrapping my enum-property in my own PropertyWrapper that handles conversion from and to String. Works quite nice in the end but I still wonder why enums as options for a select/combobox isn’t provided through the standard APIs?
For this problem. Ive created a simple helper that builds a container with a HashMap of ItemIds(can be a enum), and String descriptions to captions. Whith this, I can even use a Internationalization classes to build the Captions, not using the enum names itself.
No conversion is needed. Setting and getting values is transparent.
I use a code like that:
public class ContainerUtils {
public static String CAPTION_PROPERTY_NAME = "caption";
public static Container createContainerFromMap(Map<?, String> hashMap) {
IndexedContainer container = new IndexedContainer();
container.addContainerProperty(CAPTION_PROPERTY_NAME, String.class, "");
Iterator<?> iter = hashMap.keySet().iterator();
while(iter.hasNext()) {
Object itemId = iter.next();
container.addItem(itemId);
container.getItem(itemId).getItemProperty(CAPTION_PROPERTY_NAME).setValue(hashMap.get(itemId));
}
return container;
}
}
can someone post a complete example, because I couldn’t manage to solve this. I tried everything posted here for the past 2 days but without success.
In my table, there is a 1 char column with values Y and N (Yes and No). I would like to have a combo box in my form which will be populated with YesNoEnum so I can select some value rather than typing Y or N in the TextField.
I did some debugging and noticed that the problem is with comparing String value from combo box with enum from my Entity (“Yes” is comapred with YesNoEnum.Yes)