Vaadin tree. Lazy loading

I am trying to implement lazy loading of elements on node Expand Events. There is a problem with this. Thus, when extending the event, I create new elements for the extended node using

HierarchicalContainer.addItem() 

But this method calls

 containerItemSetChange() 

class method AbstractSelect. There

 itemIdMapper.removeAll() 

. Thus, the map is cleared, and all elements of the tree receive new identifiers on the map. When the response from the server comes to the client side, it does not know this new identifier, because it has the previous identifier (extended node), so that new elements are not added or displayed on the client side.

I tried https://vaadin.com/forum/-/message_boards/view_message/131802 . But, in fact, the data for the entire tree is sent from the server to the client. And I expect that only the data needed for a particular node will be sent. Therefore, there is no "+" performance for this.

Can someone help me with this problem? Thanks in advance.

Edition

In fact, I also needed to change the field

 partialUpdate 

true, because on the first server it sends all the contents of the tree to the client side.

+4
source share
2 answers

Rephrase your problem; most people will assume that the tree uses your hash codes / equivalent implementations on your objects (that's why they are there!) for comparison. You create your tree, do a bunch of other things, including modifying the elements that you put in the tree, and then trying to modify the tree using these elements as a key.

Here is the problem.

The tree basically takes a snapshot of the hash code for the element when you call addItem() . This hash code is used inside it to map client artifacts to an object on the server. For any subsequent removeItem() , etc. It simply uses this snapshot hash instead of calling the hashcode / equals method of the object, like any other regular container. If you debug it through removeItem() , you will see pretty quickly what the problem is.

  • A simple solution: do not modify your objects as soon as you put them in a tree. But if you need to rebuild the whole tree.
  • Best solution: create a proxy object ( TreeNode or something else) that contains the element, but provides it with its own equals / hashcode methods.
  • Best solution: Vaadin redesigns its tree so that it runs like a standard java container. Currently, this fancy behavior is not mentioned in javadoc about methods that will fail.

Hope this helps someone.

+3
source

Although the Vaadin documentation says that lazy loading for Tree not supported , I managed to implement the following lazy Hierarchical loading .

It is very important to store all the elements in a local structure (in my case in the HashMap hierarchy ), do not read the elements several times, this will not work. I think because Vaadin does not use equals() and hashCode() .

 import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import com.softmodeler.common.CommonPlugin; import com.softmodeler.model.OutputNode; import com.softmodeler.service.IViewService; import com.vaadin.data.Container.Hierarchical; import com.vaadin.data.Item; import com.vaadin.data.Property; import com.vaadin.data.util.BeanItem; /** * @author Flavio DonzΓ© * @version 1.0 */ public class OutputNodeHierachical implements Hierarchical { private static final long serialVersionUID = 8289589835030184018L; /** the view service */ private IViewService service = CommonPlugin.getService(IViewService.class); /** collection of all root nodes */ private List<OutputNode> rootNodes = null; /** parent=>children mapping */ private Map<OutputNode, List<OutputNode>> hierarchy = new HashMap<>(); /** * constructor * * @param rootNodes collection of all root nodes */ public OutputNodeHierachical(List<OutputNode> rootNodes) { this.rootNodes = Collections.unmodifiableList(rootNodes); addToHierarchy(rootNodes); } @Override public Collection<?> getChildren(Object itemId) { try { List<OutputNode> children = hierarchy.get(itemId); if (children == null) { OutputNode node = (OutputNode) itemId; children = service.getChildren(node.getNodeId(), false); hierarchy.put(node, children); // add children to hierarchy, their children will be added on click addToHierarchy(children); } return children; } catch (Exception e) { VaadinUtil.handleException(e); } return null; } /** * add each element to the hierarchy without their children hierarchy(child=>null) * * @param children elements to add */ private void addToHierarchy(List<OutputNode> children) { for (OutputNode child : children) { hierarchy.put(child, null); } } @Override public boolean areChildrenAllowed(Object itemId) { return !((OutputNode) itemId).getChilds().isEmpty(); } @Override public boolean hasChildren(Object itemId) { return !((OutputNode) itemId).getChilds().isEmpty(); } @Override public Object getParent(Object itemId) { String parentId = ((OutputNode) itemId).getParentId(); for (OutputNode node : hierarchy.keySet()) { if (node.getNodeId().equals(parentId)) { return node; } } return null; } @Override public Collection<?> rootItemIds() { return rootNodes; } @Override public boolean isRoot(Object itemId) { return rootNodes.contains(itemId); } @Override public Item getItem(Object itemId) { return new BeanItem<OutputNode>((OutputNode) itemId); } @Override public boolean containsId(Object itemId) { return hierarchy.containsKey(itemId); } @Override public Collection<?> getItemIds() { return hierarchy.keySet(); } @Override public int size() { return hierarchy.size(); } @Override public boolean setParent(Object itemId, Object newParentId) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public boolean setChildrenAllowed(Object itemId, boolean areChildrenAllowed) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public Item addItem(Object itemId) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public Object addItem() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public boolean removeItem(Object itemId) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public boolean removeAllItems() throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public Class<?> getType(Object propertyId) { throw new UnsupportedOperationException(); } @Override public Collection<?> getContainerPropertyIds() { throw new UnsupportedOperationException(); } @Override public Property<?> getContainerProperty(Object itemId, Object propertyId) { throw new UnsupportedOperationException(); } @Override public boolean addContainerProperty(Object propertyId, Class<?> type, Object defaultValue) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } @Override public boolean removeContainerProperty(Object propertyId) throws UnsupportedOperationException { throw new UnsupportedOperationException(); } } 

Adding a container to the Tree as follows:

 OutputNodeHierachical dataSource = new OutputNodeHierachical(rootNodes); Tree mainTree = new Tree(); mainTree.setSizeFull(); mainTree.setContainerDataSource(dataSource); mainTree.addItemClickListener(new ItemClickListener() { private static final long serialVersionUID = -413371711541672605L; @Override public void itemClick(ItemClickEvent event) { OutputNode node = (OutputNode) event.getItemId(); openObject(node.getObjectId()); } }); 


I hope this example helps, as I have not found an example of real life on the Internet.

+1
source

Source: https://habr.com/ru/post/1402252/


All Articles