When I add components to Vaadin's component (such as TabSheet
or Tree
) , the added components are cached. When user clicks the tab (or tree nodes) , if it contains db data , it shows stale data , not reflecting the latest db state.
I wonder if there is any way to ensure loading latest data ?
I solve the problem by defining my custom interface :
public interface Reloadable {
void reload();
}
And each component implements this Reloadable interface , such as :
@SpringComponent
public class TeachersView extends VerticalLayout implements Reloadable, Serializable {
@Inject
private TeacherDao teacherDao;
private final static int PAGESIZE = 10;
private MTable<Teacher> mTable = new MTable<>(Teacher.class);
@PostConstruct
public void init() {
// mTable settings skip here
reload();
addComponent(mTable);
}
@Override
public void reload() {
mTable.setBeans(new SortableLazyList<>(
sortablePagingProvider ,
() -> (int) teacherDao.count() ,
PAGESIZE
));
}
private SortableLazyList.SortablePagingProvider<Teacher> sortablePagingProvider =
(firstRow, asc, sortProperty) -> {
return teacherDao.findAll(
new PageRequest(
firstRow / PAGESIZE, PAGESIZE,
asc ? Sort.Direction.ASC : Sort.Direction.DESC,
sortProperty == null ? "id" : sortProperty
)
).getContent();
};
}
And this view is injected to UI
class :
@SpringUI(path = "/ui")
@Theme("valo")
public class VaadinUI extends UI {
@Inject
private TeacherDao teacherDao;
@Inject
private TeachersView teachersView;
@Override
protected void init(VaadinRequest vaadinRequest) {
Panel panel = new Panel("Admin Panel");
HorizontalSplitPanel splitPanel = new HorizontalSplitPanel();
splitPanel.setSplitPosition(15, Unit.PERCENTAGE);
panel.setContent(splitPanel);
Tree tree = new Tree("Menu");
splitPanel.setFirstComponent(tree);
Label home = new Label("Home");
Map<String, Component> map = new HashMap<>();
map.put("Teachers", teachersView);
map.put("Home", home);
map.forEach((k, v) -> tree.addItem(k));
tree.addItemClickListener(event -> {
Component view = map.get(event.getItemId());
if (view instanceof Reloadable) {
((Reloadable) view).reload();
}
splitPanel.setSecondComponent(view);
});
splitPanel.setSecondComponent(home);
setContent(panel);
} // init()
}
Notice the tree.addItemClickListener
, I have to check each component if it implements Reloadable
, if true , invoke it.
It works . But I don't know if it the standard way achieving this ? I think it should be a common scenario , there should be something like built-in interface for Components to implement , such as onRender
like that (but I cannot find one) . Did I miss anything ?
Thanks.