I have a piece of information that is stored in a database table as a string code value. I have defined an enum to make the code human-readable. An entity class defines the field with the enum.
When I display the data in a Vaadin grid, it displays the enumeration value, which is what is needed. However, I am also trying to display the same data in a form text field, and this behaves differently. I had to write a converter for the data binding to avoid a run-time error, but the result is the opposite of what I expect - it shows the code value instead of the enumeration.
Some code to illustrate:
The enumeration type:
public enum TaskType {
TASK_VIEW("00"), INTERACTIVE("01"), BATCH("02"), FOLDER("07"), URL("08"), USER_DEFINED("11");
private String codeValue;
private TaskType(String codeValue) {
this.codeValue = codeValue;
}
public String getCodeValue() {
return codeValue;
}
public static TaskType fromCodeValue(String value) {
switch (value) {
case "00":
return TASK_VIEW;
case "01":
return INTERACTIVE;
case "02":
return BATCH;
case "07":
return FOLDER;
case "08":
return URL;
case "11":
return USER_DEFINED;
default:
return null;
}
}
}
The entity class:
@Entity
public class TaskMaster extends AbstractEntity {
private TaskType type;
// other fields
public TaskType getType() {
return type;
}
public void setType(TaskType type) {
this.type = type;
}
// other methods
}
A converter between database field and enum type:
@Converter(autoApply = true)
public class TaskTypeConverter implements AttributeConverter<TaskType, String> {
@Override
public String convertToDatabaseColumn(TaskType type) {
if (type != null) {
return type.getCodeValue();
} else {
return null;
}
}
@Override
public TaskType convertToEntityAttribute(String dbData) {
if (dbData != null) {
return TaskType.fromCodeValue(dbData);
} else {
return null;
}
}
}
The grid view class:
public class TaskMasterListView extends VerticalLayout {
private Grid<TaskMaster> grid = new Grid<>(TaskMaster.class);
private TaskMasterService taskService;
public TaskMasterListView(TaskMasterService taskService) {
this.taskService = taskService;
...
}
@PostConstruct
public void init() {
List<TaskMaster> items = taskService.findAll();
grid.setItems(items);
}
private void configureGrid() {
grid.addClassName("tasks-grid");
grid.setColumns("internalTaskID", "taskID", "name", "type", "objectName", "version",
"formName");
grid.getColumns().forEach(col -> col.setAutoWidth(true));
}
...
}
The details view (where it displays incorrectly):
public class TaskDetailView extends FormLayout {
private static final Logger logger = LoggerFactory.getLogger(TaskDetailView.class);
private TextField type;
// other GUI objects
private Binder<TaskMaster> binder;
public TaskDetailView() {
configureView();
bindData();
}
public void loadTask(TaskTreeView.TaskSelectionEvent event) {
if (event.getSelected() != null) {
binder.setBean(event.getSelected());
}
}
private void bindData() {
binder = new Binder<>(TaskMaster.class);
binder.setBean(new TaskMaster());
binder.forField(type).withConverter(new TaskTypeConverter()).bind("type");
// other bindings
}
private static class TaskTypeConverter implements Converter<String, TaskType> {
@Override
public Result<TaskType> convertToModel(String value, ValueContext context) {
logger.info("convertToModel: value={}", value);
return Result.ok(TaskType.fromCodeValue(value));
}
@Override
public String convertToPresentation(TaskType value, ValueContext context) {
if (value != null) {
logger.info("convertToPresentation: value={}", value.toString());
return value.getCodeValue();
} else {
logger.info("convertToPresentation: null");
return "";
}
}
}
}
So, as an example, if an entity with type = 07
is displayed in the grid, it shows FOLDER
, which is what I want. But, when I display the same object where the type is shown in a text field, it shows 07
instead of FOLDER
.
Any idea what's going on here? It seems to be doing the opposite of what I need.
question from:
https://stackoverflow.com/questions/65860095/vaadin-14-text-field-not-displaying-enumeration-correctly