My n-tier webapp uses AppFuse 1.7 as a base for development.
It uses Spring Framework (Spring MVC too) and Hibernate (v 2.1.7c) integrated.
I'm using
OpenSessionInView pattern, and my tiers are:
Model (Pojo's) -> DAOs -> Services/Managers -> Controllers -> Views.
So, in the DAOs layer, I get one list of objects of type Category,
with a generic method:
Code:
public List getObjects(Class clazz) {
return getHibernateTemplate().loadAll(clazz);
}
In the Services layer, I want to filter the list (exclude the childs) to show it in the views.
The controller tells the service layer to get these filtered list:
Code in the controller:
Code:
protected Map referenceData(HttpServletRequest request)
throws Exception {
Categoria categoria = (Categoria) formBackingObject(request);
Map model = new HashMap();
model.put("categorias", mgr.getObjects(Categoria.class, categoria, Boolean.TRUE, "getCategoriasFilhas"));
return model;
}
Code in the manager:
Code:
public List getObjects(Class clazz) {
return dao.getObjects(clazz);
}
public List getObjects(Class clazz, Object excluded, Boolean excludeChilds, String methodToGetChilds) {
List objects = getObjects(clazz);
Set toRemove = new HashSet();
toRemove .add(excluded);
if (excludeChilds == Boolean.TRUE) {
Set childs = getChilds(excluded, methodToGetChilds);
if (!childs.isEmpty()) {
toRemove.addAll(childs);
}
}
objects.removeAll(toRemove);
return objects;
}
private Set getChilds(Object root, String methodToGetChilds) {
Set childs = (Set) callObjectMethod(root, methodToGetChilds);
//Set childs = getChildsCopy(root, methodToGetChilds);
Iterator i = childs.iterator();
while (i.hasNext()) {
Object sub = i.next();
Set subChilds = getChilds(sub, methodToGetChilds);
if (!subChilds.isEmpty()) {
childs.addAll(subChilds);
}
}
return childs;
}
/*
private synchronized Set getChildsCopy(Object root, String methodToGetChilds) {
return new HashSet((Set) callObjectMethod(root, methodToGetChilds));
}
*/
public Object callObjectMethod(Object object, String methodName) {
Object ret = null;
Class clazz = object.getClass();
try {
Method method = clazz.getMethod(methodName, null);
ret = method.invoke(object, null);
} catch (Exception ex) {
return null;
}
return ret;
}
I tried to make a synchronized copy of the list before iterating over it, with is the code commented above.
Copying or not, the code in the
getChilds method causes a
ConcurrentModificationException in the half of the process.
I suspect that this is because I am using lazy loading in the childs. (class Categoria, method getCategoriasFilhas)
An example graph of objects is:
Code:
Root
/ \
2 5
/ \ \
3 4 6
/ \
7 8
When the code finishes the tree above instance "2" and get's the top (root) to iterate over the tree above "5", that exception occurs.
Anyone have any code/sample/ideia to solve this? I could filter this list in the DAO layer using HQL/etc, but i want to filter this here in the service layer, because I desire to improve my OO logic.
Thanks very much
[]'s
Caetano