Hi Alejandro,
I am currently looking at whether I could use your addon for my project. I find your addon super useful, thanks for sharing. However, I still have a few questions. Maybe you can give me your opinion on this.
Understanding error handling using the ADD operation as an example
Scenario is that the bean validation was successful, but there is an error in the backend when saving the data. I will describe my understanding so you can point out where I am wrong.
The click on update leads to execution
public abstract class AbstractAutoGeneratedCrudFormFactory<T> extends AbstractCrudFormFactory<T> {
...
protected Button buildOperationButton(CrudOperation operation, T domainObject, ComponentEventListener<ClickEvent<Button>> clickListener) {
...
button.addClickListener(event -> {
if (binder.writeBeanIfValid(domainObject)) {
try {
clickListener.onComponentEvent(event);
} catch (Exception e) {
showError(operation, e);
}
} else {
Notification.show(validationErrorMessage);
}
Next, the operationPerformedClickEvent of the GridCrud Impl comes into play, which requires that an exception is thrown, which is caught by the AbstractAutoGeneratedCrudFormFactory and thus it doesn’t get to the success message
public class GridCrud<T> extends AbstractCrud<T> {
...
protected void showForm(CrudOperation operation, T domainObject, boolean readOnly, String successMessage, ComponentEventListener<ClickEvent<Button>> buttonClickListener) {
...
}, operationPerformedClickEvent -> {
buttonClickListener.onComponentEvent(operationPerformedClickEvent);
if (!clickRowToUpdate) {
crudLayout.hideForm();
}
showNotification(successMessage);
});
Here is the implementation of the updateButton in this example in the GridCrud and my first questions
public class GridCrud<T> extends AbstractCrud<T> {
...
protected void updateButtonClicked() {
T domainObject = grid.asSingleSelect().getValue();
showForm(CrudOperation.UPDATE, domainObject, false, savedMessage, event -> {
try {
T updatedObject = updateOperation.perform(domainObject);
grid.asSingleSelect().clear();
refreshGrid();
grid.asSingleSelect().setValue(updatedObject);
// TODO: grid.scrollTo(updatedObject);
} catch (IllegalArgumentException ignore) {
} catch (CrudOperationException e1) {
refreshGrid();
} catch (Exception e2) {
refreshGrid();
throw e2;
}
});
}
- Question 1: Why is no exception thrown in case of an IllegalArgumentException or CrudOperationException? In my opinion this wrongly leads to a success message.
Let’s follow the path that it was not one of the mentioned exceptions and an exception is thrown. If the showError implementation of the AbstractAutoGeneratedCrudFormFactory comes on the scene again
public abstract class AbstractAutoGeneratedCrudFormFactory<T> extends AbstractCrudFormFactory<T> {
...
@Override
public void showError(CrudOperation operation, Exception e) {
if (errorListener != null) {
errorListener.accept(e);
} else {
if (CrudOperationException.class.isAssignableFrom(e.getClass())) {
// FIXME no Notification.Type
Notification.show(e.getMessage());
} else {
Notification.show(e.getMessage());
throw new RuntimeException("Error executing " + operation.name() + " operation", e);
}
}
}
How is error handling thought of here?
- Question 2: CrudOperationException only notification to the user? But currently can’t “arrive” here at all, because it is currently caught before.
- Question 3: Rest of exceptions notification and global error handling to ensure logging?
- Question 4: errorListener to hook its own error handling?
I would be grateful for any feedback.
Greetings
Knut