Hi,
I’m following Vaadin’s tutorial: https://vaadin.com/docs/v8/framework/tutorial.html
In step 6, creating a from using plain Java, I’m having the following problem: Caused by: java.lang.IllegalStateException: Unable to detect value type for the member ‘status’ in the class ‘com.jetbrains.CustomerForm’.
Here, I’m basically trying to create a form, where its form fields will correspond to a Customer instance that is selected (via Binder class)
The issue seems to come from the code binder.bindInstanceFields(this);. Everything seems to work if I comment out this code.
Note: the status field is an enum defined within CustomerStatus (below)
CustomerForm: import com.vaadin.event.ShortcutAction; import com.vaadin.ui.FormLayout; import com.vaadin.ui.NativeSelect; import com.vaadin.ui.*; import com.vaadin.ui.themes.ValoTheme; import com.vaadin.data.Binder;
public class CustomerForm extends FormLayout {
private TextField firstName = new TextField("First Name");
private TextField lastName = new TextField("Last Name");
private DateField birthDate = new DateField("Birthday");
private NativeSelect status = new NativeSelect("Status");
private TextField email = new TextField("Email");
private Button save = new Button("Save");
private Button delete = new Button("Delete");
private Binder<Customer> binder = new Binder<>(Customer.class);
private CustomerService service = CustomerService.getInstance();
private Customer customer;
private MyUI myUI;
public CustomerForm(MyUI myUI) {
this.myUI = myUI;
setSizeUndefined();
HorizontalLayout buttons = new HorizontalLayout(save, delete);
addComponents(firstName, lastName, birthDate, status, email, buttons);
status.setItems(CustomerStatus.values());
save.setStyleName(ValoTheme.BUTTON_PRIMARY);
save.setClickShortcut(ShortcutAction.KeyCode.ENTER);
binder.bindInstanceFields(this);
save.addClickListener(e -> save());
delete.addClickListener(e -> delete());
}
public void setCustomer(Customer customer) {
this.customer = customer;
binder.setBean(customer);
delete.setVisible(customer.isPersisted());
setVisible(true);
firstName.selectAll();
}
private void save() {
service.save(customer);
myUI.updateList();
setVisible(false);
}
private void delete() {
service.delete(customer);
myUI.updateList();
setVisible(false);
}
}
MyUI:
public class MyUI extends UI {
private CustomerService service = CustomerService.getInstance();
private Grid<Customer> grid = new Grid<>(Customer.class);
private TextField filterText = new TextField();
private CustomerForm form = new CustomerForm(this);
@Override
protected void init(VaadinRequest vaadinRequest) {
final VerticalLayout layout = new VerticalLayout();
filterText.setPlaceholder("Filter by name...");
filterText.setValueChangeMode(ValueChangeMode.LAZY);
filterText.addValueChangeListener(e -> updateList());
Button clearFilterTextBtn = new Button(VaadinIcons.CLOSE);
clearFilterTextBtn.addClickListener(e -> filterText.clear());
clearFilterTextBtn.setDescription("Clear filter text");
CssLayout filtering = new CssLayout();
filtering.addComponents(filterText, clearFilterTextBtn);
filtering.setStyleName(ValoTheme.LAYOUT_COMPONENT_GROUP);
grid.setColumns("firstName", "lastName", "email", "status");
HorizontalLayout main = new HorizontalLayout(grid, form);
main.setSizeFull();
grid.setSizeFull();
main.setExpandRatio(grid, 1);
layout.addComponents(filtering, main);
updateList();
setContent(layout);
form.setVisible(false);
grid.asSingleSelect().addValueChangeListener(event -> {
if(event.getValue() == null) {
form.setVisible(false);
} else {
form.setCustomer(event.getValue());
}
});
}
public void updateList() {
List<Customer> customers = service.findAll(filterText.getValue());
grid.setItems(customers);
}
@WebServlet(urlPatterns = "/*", name = "MyUIServlet", asyncSupported = true)
@VaadinServletConfiguration(ui = MyUI.class, productionMode = false)
public static class MyUIServlet extends VaadinServlet {
}
}
Customer:
import java.io.Serializable;
import java.time.LocalDate;
import java.util.Date;
/**
* A entity object, like in any other Java application. In a typical real world
* application this could for example be a JPA entity.
*/
@SuppressWarnings("serial")
public class Customer implements Serializable, Cloneable {
private Long id;
private String firstName = "";
private String lastName = "";
private LocalDate birthDate;
private CustomerStatus status;
private String email = "";
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/**
* Get the value of email
*
* @return the value of email
*/
public String getEmail() {
return email;
}
/**
* Set the value of email
*
* @param email
* new value of email
*/
public void setEmail(String email) {
this.email = email;
}
/**
* Get the value of status
*
* @return the value of status
*/
public CustomerStatus getStatus() {
return status;
}
/**
* Set the value of status
*
* @param status
* new value of status
*/
public void setStatus(CustomerStatus status) {
this.status = status;
}
/**
* Get the value of birthDate
*
* @return the value of birthDate
*/
public LocalDate getBirthDate() {
return birthDate;
}
/**
* Set the value of birthDate
*
* @param birthDate
* new value of birthDate
*/
public void setBirthDate(LocalDate birthDate) {
this.birthDate = birthDate;
}
/**
* Get the value of lastName
*
* @return the value of lastName
*/
public String getLastName() {
return lastName;
}
/**
* Set the value of lastName
*
* @param lastName
* new value of lastName
*/
public void setLastName(String lastName) {
this.lastName = lastName;
}
/**
* Get the value of firstName
*
* @return the value of firstName
*/
public String getFirstName() {
return firstName;
}
/**
* Set the value of firstName
*
* @param firstName
* new value of firstName
*/
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public boolean isPersisted() {
return id != null;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (this.id == null) {
return false;
}
if (obj instanceof Customer && obj.getClass().equals(getClass())) {
return this.id.equals(((Customer) obj).id);
}
return false;
}
@Override
public int hashCode() {
int hash = 5;
hash = 43 * hash + (id == null ? 0 : id.hashCode());
return hash;
}
@Override
public Customer clone() throws CloneNotSupportedException {
return (Customer) super.clone();
}
@Override
public String toString() {
return firstName + " " + lastName;
}
}
CustomerStatus:
public enum CustomerStatus {
ImportedLead, NotContacted, Contacted, Customer, ClosedLost
}