how to delete node children? - aem

before I write may sitemap.xml in some jcr folder /var/myProject/sitemap, I would like to delete the old sitemap.xml
Resource resource = resourceResolver.getResource("/var/myProject/sitemap");
sitemapNode = resource.adaptTo(Node.class);
sitemapNode.getNodes().remove();
sitemapNode.getNodes().remove(); deliver the following exception:
*ERROR* [CM Event Dispatcher (Fire ConfigurationEvent: pid=MyClass] The start method has thrown an exception (java.lang.UnsupportedOperationException)
How to remove all children of the sitemapNode ?

The sitemapNode.getNodes(); returns a NodeIterator. The remove() method available in that is the one inherited from Iterator.
Quoting the docs remove()
Removes from the underlying collection the last element returned by
this iterator (optional operation)
When you try to remove from an unmodifiable collection, it gives the UnsupportedOperationException.
Either remove the sitemapNode using sitemapNode.remove() and recreate it (this would remove all its children along with the node), or iterate through each child and then call the remove() method individually. This would invoke the Node's remove() method inherited from javax.jcr.Item.

Related

Why does calling TreeViewer.refresh() not call the contentProvider's getChildren(Object) method?

Amongst other places, I've looked here and here, but I've not found an answer to my question.
A little background:
I'm implementing a view that represents a subset of the resources in an eclipse project.
The project nodes in the tree will check whether the project is open to see if they should contain children. Effectively, the Project node's hasChildren() method returns IProject.isOpen().
The eclipse view subscribes to resourceChangeEvents, and in the case that any change occurs, it calls refresh() on the TreeViewer.
Based on information from this question:
If you have added or removed objects in the tree use
TreeViewer.refresh();
refresh() (with no arguments) should then go through and update the entire tree with fresh information from the model.
By setting breakpoints in the code, I've discovered that during the refresh process, the framework calls hasChildren() several times on a node, but never calls getChildren().
Let us say that Project is currently open, and the node representing it in the tree is expanded with some children. I close the project and resource change event is fired. This causes a refresh(). When asked, the project now returns false from hasChildren(), and yet the children are still present in the tree.
Conversely, if the project is closed and the node has no children (there is no expansion arrow), opening the project will fire a resource change event, which refresh()es the tree, the project node returns true from hasChildren() and yet getChildren() is never called to find out what these children are. The node still has no children and no expansion arrow.
Currently the model fires events when new nodes are added and old ones removed, and the tree listens for these and calls add(Object, Object) and remove(Object) on the TreeViewer as appropriate, but the model only checks to see whether its children need to be changed when it is asked for them via the content provider's getChildren() method.
The problem can be partially alleviated by calling getChildren() from hasChildren(), but this seems messy, and from my understanding of how refresh() works, shouldn't be necessary.
Why does the TreeViewer's refresh() method not re-query a node to see what its children are? Given that is doesn't do this, how is it meant to handle adding and removing objects?
It turns out the problem was that the Implementation of the IElementComparer passed to TreeViewer.setComparer looked like this:
#Override
public boolean equals( final Object one, final Object two ) {
if (one.getClass().equals( two.getClass() ) ) { <-- This is not always true...
if ( one instanceof MyCustomNodeBaseClass) {
return ((MyCustomNodeBaseClass) one).isEquivalentTo( (MyCustomNodeBaseClass) two);
}
}
return false; <-- ...therefore this is the problem, as it wasn't expected to be reached
}
The IElementComparer.equals(Object, Object) method can be called with arguments of class org.eclipse.ui.internal.ViewSite, and should handle those too.
It was a questionable move to quietly return false in cases where the class of the parameters was unrecognised, and the problematic line could be replaced with:
return ( one.equals( two ) ); <-- this will quietly handle unexpected classes better.
I eventually found this by following the debugger into the updatePlus() method of the AbstractTreeViewer

Extending CQ5 List component

I'm looking into extending the cq5 list component to create custom list displays (obviously). The constructor takes a SlingHttpServletRequest and the minimal java doc says "creates a list from the specified request".
Can someone explain how those request settings are used to build the list? what things in the request should I change to alter the list? Is there better documentation somewhere?
The component uses the request to retrieve the resource object.
In the init method it retrieves a the resource node's properties.
The "listFrom" property should matter for you the most as it controls how the list is created. Either by querybuilder, search, retrieving the children ("children") or tags.
The List component does a simple string equals to find out which option is set and executes the associated logic.
At the end a PageIterator is returned, which is processed by the jsp.

Delete a list of entity with RequestFactory (GWT)

How can I delete a list of entity with RequestFactory?
InstanceRequest<List<XProxy>, Void> remove();
Of course, this is not working, because the first parameter has to be like this: P extends BaseProxy; but is there a similar way?
I want to delete the selected entities of my CellTable from the database. And I am using MultiSelectionModel, and CheckboxCell.
An InstanceRequest means that the method is an instance method on the domain method for the first type argument (similar to looking for a remove() on a List in what you tried).
You have to use a Request and pass the List as an argument to the method. The presence of a #ServiceLocator on the RequestContext will tell RequestFactory whether to look for a static or an instance method.
Request<Void> remove(List<XProxy> list);

Business Logic when Saving in Entity Framework

If I want to perform some action when an entity is saved, I can do something as described here.
However, suppose I retrieve an object from the database. This object has a list of items within it. If I instantiate a new item and add it to this list and then save all changes, the item in the list is not part of the "GetObjectStateEntries".
The problem for my situation, I believe, has been resolved. There appears to be a bug, in my opinion, in the ObjectContext.SaveChanges(SaveOptions) method. Even though this method will call DetectChanges (depending on the saveOptions), the OnSavingChanges method is called FIRST. This, I think, is a problem.
The solution to this is to call ObjectContext.DetectChanges() prior to calling SaveChanges().

GWT app getting java.util.ConcurrentModificationException from MVC pattern

I am getting this error everytime my Observers are traversed.
#Override
public void notifyObservers(ModelViewInterface model) {
for(Observer<ModelViewInterface> o : this.observers)
o.notify(model);
}
GWT does not have threads, so it is not a synchronization issue.
It seems to happen after I press a button, any ideas of how to avoid this error?
From the javadoc of ConcurrentModificationException:
Note that this exception does not always indicate that an object has been concurrently modified by a different thread. If a single thread issues a sequence of method invocations that violates the contract of an object, the object may throw this exception. For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
So in your case, it seems that o.notify(model) modifies this.observers - directly or indirectly. This is a common phenomenon when modifying the collection you're iterating over.
To avoid concurrent modification, you can operate on a copy of the collection like this:
for(Observer<ModelViewInterface> o :
new ArrayList<ModelViewInterface>(this.observers)) {
o.notify(model);
}
However, sometimes this is not what you want - the current behaviour of o.notify could also indicate a bug.