Here is a new Spring scope for JSF. It is just a prototype but it works. It will get added to Crank unless/until they add it to Spring.
Spring allows you to create a custom scope (scope as in singleton, prototype, session, etc).
And
(See section 3.4.5.1 in the Spring reference for more detail)
http://static.springframework.org/spring/docs/2.5.x/reference/beans.html#beans-factory-scopes
Along those lines, I have been meaning to create a JSF View scope for a while. I thought it would be pretty easy and it was. I had a working version in about 15 to 20 minutes. One wonders why they don't ship with such a beast (I will include it in Crank for now).
package org.crank.config.spring.support;
import java.util.HashMap;
import java.util.Map;
import javax.faces.context.FacesContext;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.beans.factory.config.Scope;
public class ViewScope implements Scope
{
public final String VIEW_SCOPE_KEY = "CRANK_VIEW_SCOPE";
public Object get(String name, ObjectFactory objectFactory)
{
if (FacesContext.getCurrentInstance().getViewRoot() != null)
{
Map<String, Object> viewScope = extractViewScope();
if (viewScope.get(name) == null)
{
Object object = objectFactory.getObject();
viewScope.put(name, object);
return object;
} else
{
return viewScope.get(name);
}
} else
{
System.out.println("################ : GET VIEW ROOT NOT FOUND");
return null;
}
}
@SuppressWarnings("unchecked")
private Map<String, Object> extractViewScope()
{
Map<String, Object> attributes = FacesContext.getCurrentInstance().getViewRoot().getAttributes();
Map<String, Object> viewScope = null;
if (attributes.get(VIEW_SCOPE_KEY)==null)
{
viewScope = new HashMap<String, Object>();
attributes.put(VIEW_SCOPE_KEY, viewScope);
} else
{
viewScope = (Map<String, Object>) attributes.get(VIEW_SCOPE_KEY);
}
return viewScope;
}
public String getConversationId()
{
return null;
}
public void registerDestructionCallback(String name, Runnable callback)
{
System.out.println("#####################: We don't support destruction callbacks at this time");
}
public Object remove(String name)
{
if (FacesContext.getCurrentInstance().getViewRoot() != null)
{
Map<String, Object> viewScope = extractViewScope();
return viewScope.remove(name);
} else
{
System.out.println("################ : REMOVE VIEW ROOT NOT FOUND");
return null;
}
}
}
With the above (which will be cleaned up) supports a view scope so now I can associate objects with the current view root, and when the view root changes, the objects go away.
@Bean(scope = DefaultScopes.SESSION) public JsfCrudAdapter empRecordCrud() {
So now instead of the above... which stays around for the whole session, I can use:
@Bean(scope = "view") public JsfCrudAdapter empRecordCrud() {