Fábio Pires
Fábio Pires

Reputation: 101

Vaadin - Internal error Please notify the administrator. Take note of any unsaved data, and click here or press ESC to continue

I am developing an application in Vaadin where I have a view for Suppliers.

I am getting the error Internal error Please notify the administrator. Take note of any unsaved data, and click here or press ESC to continue. due to the calling of the method categoriesToString in my View.

View

    public SupplierView(CrmService service) {
        this.service = service;
        addClassName("supplier-view");
        setSizeFull();
        configureGrid();

        form = new SupplierForm(service.findAllCategories(null));
        form.setWidth("25em");
        form.addListener(SupplierForm.SaveEvent.class, this::saveSupplier);
        form.addListener(SupplierForm.DeleteEvent.class, this::deleteSupplier);
        form.addListener(SupplierForm.CloseEvent.class, e -> closeEditor());

        FlexLayout content = new FlexLayout(grid, form);
        content.setFlexGrow(2, grid);
        content.setFlexGrow(1, form);
        content.setFlexShrink(0, form);
        content.addClassNames("content", "gap-m");
        content.setSizeFull();

        add(getToolbar(), content);
        updateList();
        closeEditor();
        grid.asSingleSelect()
                .addValueChangeListener(event -> editSupplier(event.getValue()));
    }

    private void configureGrid() {
        grid.addClassNames("supplier-grid");
        grid.setSizeFull();
        grid.setColumns("name", "address");
        grid.addColumn(supplier -> supplier.categoriesToString())
                .setHeader("Categories");
        grid.getColumns().forEach(col -> col.setAutoWidth(true));
    }
}

The said method belongs to the class Supplier that can be seen below. This class has a Set of Category that I am trying to go trough in order to return all categories present in it.

Supplier

@Entity
public class Supplier extends AbstractEntity {
    @NotEmpty
    private String name;
    @NotEmpty
    private String address;

    @OneToMany(mappedBy = "supplier")
    private Set<Category> categories = new LinkedHashSet<>();


    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getAddress() {
        return this.address;
    }

    public void setAddress(String address) {
        this.address = address;
    }


   public Set<Category> getCategories() {
        return categories;
    }

    public void setCategories(Set<Category> categories) {
        this.categories = categories;
    }

    public String categoriesToString(){
        String allCategories = "";
        for (Category c : this.categories) 
        {
            allCategories += c.getDescription();
        }
        
        return allCategories;
    }
} 

In order to do some testing I tried to make the method just return "test" and in that scenario the word was indeed added to "Categories" column and no error was shown.

Category class

@Entity
public class Category extends AbstractEntity{
    @NotBlank
    private String description;

    @ManyToOne
    @JoinColumn(name = "supplier_id")
    @JsonIgnoreProperties({"categories"})
    private Supplier supplier;

    public String getDescription() {
        return this.description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

Why is this happening? Am I iterating through the set in a incorrect way?

Upvotes: 0

Views: 690

Answers (1)

rodolforfq
rodolforfq

Reputation: 51

You have not specified the fetch mode for your Entity, so it is defaulting to Lazy mode. Your current logic will only work with Eager mode (that would fetch the "categories" one-to-many relationship), but this is bound to create performance issues down the road as your data grows.

I wouldn't use logic inside my entities either (your categoriesToString method), but that is a different topic altogether.

You can either specify Eager loading on your entity as:

@OneToMany(fetch = FetchType.EAGER, mappedBy = "supplier")
private Set<Category> categories = new LinkedHashSet<>();

Or perform an additional query to fetch the related categories. Or even better, create a POJO or Spring Data Projection to fetch/map the appropriate data to. You can check this link for more info on that matter.

Upvotes: 1

Related Questions