First, a bit of history on replicating session scoped beans. Using ICEfaces 1.8 and JSF 1.2 (maybe JSF 1.1 as well) session scoped beans were automatically replicated. Depending on the application server being used only the frequency of the replication needed to be adjusted, but no additional code was required in the actual application. However, there was one exception to this, namely WebLogic. WebLogic documentation dictated to use sessionMap.put("beanName", this) inside the session scoped bean in order to enforce the session replication to occur.
On to ICEfaces 2.0 and JSF 2.0/2.1. Using session scoped beans, all aforementioned still applied and things seem to be working well. However adding view scoped beans innitially and window scoped beans as an alternative eventually broke the session replication. Adding the sessionMap.put(...) strategy didn't help either. (I've only been using Tomcat 6 for now.) To keep the story a bit short, there seems to be a difference between sessionMap.put(...) and session.setAttribute(...). This difference seems to be since JSF 2.1.
JSF 2.0:
@Override
public Object put(String key, Object value) {
Util.notNull("key", key);
HttpSession session = getSession(true);
Object result = session.getAttribute(key);
if (value != null && ProjectStage.Development.equals(stage) && !(value instanceof Serializable)) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING,
"jsf.context.extcontext.sessionmap.nonserializable",
new Object[]
{key, value.getClass().getName()});
}
}
//noinspection NonSerializableObjectBoundToHttpSession
session.setAttribute(key, value);
return (result);
}
JSF 2.1:
@Override
public Object put(String key, Object value) {
Util.notNull("key", key);
HttpSession session = getSession(true);
Object result = session.getAttribute(key);
if (value != null && ProjectStage.Development.equals(stage) && !(value instanceof Serializable)) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING,
"jsf.context.extcontext.sessionmap.nonserializable",
new Object[]{key, value.getClass().getName()}
);
}
}
//noinspection NonSerializableObjectBoundToHttpSession
boolean doSet = true;
if (null != value && null != result)
{
doSet = ! result.equals(value);
}
if (doSet)
{
session.setAttribute(key, value);
}
return (result);
}
Basically resetting a value in the sessionMap using the sessionMap.put(...) doesn't suffice anymore to tickle the session. Explaining why I only saw one replication occur.
In order to ensure replication to occur, we can still use the reset strategy, but use session.setAttribute(...) instead of sessionMap.put(...). In order to test this I added the following to my window scoped bean:
((javax.servlet.http.HttpSession)FacesUtils.getExternalContext().getSession(false)).setAttribute(
"org.icefaces.impl.application.WindowScopeManager",
((javax.servlet.http.HttpSession)FacesUtils.getExternalContext().getSession(false)).
getAttribute("org.icefaces.impl.application.WindowScopeManager"));
This "fixed" at least the window scoped bean scenario. I could use this strategy as well for the view scoped beans be resetting the LogicalViewMap, to see if that would help that scenario as well.
Now this should not be the definite solution of course, as this should not have to be done in the application. We should see where we can put this logic in the framework at least for the window scoped beans scenario.
First, a bit of history on replicating session scoped beans. Using ICEfaces 1.8 and JSF 1.2 (maybe JSF 1.1 as well) session scoped beans were automatically replicated. Depending on the application server being used only the frequency of the replication needed to be adjusted, but no additional code was required in the actual application. However, there was one exception to this, namely WebLogic. WebLogic documentation dictated to use sessionMap.put("beanName", this) inside the session scoped bean in order to enforce the session replication to occur.
On to ICEfaces 2.0 and JSF 2.0/2.1. Using session scoped beans, all aforementioned still applied and things seem to be working well. However adding view scoped beans innitially and window scoped beans as an alternative eventually broke the session replication. Adding the sessionMap.put(...) strategy didn't help either. (I've only been using Tomcat 6 for now.) To keep the story a bit short, there seems to be a difference between sessionMap.put(...) and session.setAttribute(...). This difference seems to be since JSF 2.1.
JSF 2.0:
@Override
{key, value.getClass().getName()});public Object put(String key, Object value) {
Util.notNull("key", key);
HttpSession session = getSession(true);
Object result = session.getAttribute(key);
if (value != null && ProjectStage.Development.equals(stage) && !(value instanceof Serializable)) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING,
"jsf.context.extcontext.sessionmap.nonserializable",
new Object[]
}
}
//noinspection NonSerializableObjectBoundToHttpSession
session.setAttribute(key, value);
return (result);
}
JSF 2.1:
@Override
public Object put(String key, Object value) {
Util.notNull("key", key);
HttpSession session = getSession(true);
Object result = session.getAttribute(key);
if (value != null && ProjectStage.Development.equals(stage) && !(value instanceof Serializable)) {
if (LOGGER.isLoggable(Level.WARNING)) {
LOGGER.log(Level.WARNING,
"jsf.context.extcontext.sessionmap.nonserializable",
new Object[]{key, value.getClass().getName()}
);
{ doSet = ! result.equals(value); }}
}
//noinspection NonSerializableObjectBoundToHttpSession
boolean doSet = true;
if (null != value && null != result)
if (doSet)
{ session.setAttribute(key, value); }return (result);
}
Basically resetting a value in the sessionMap using the sessionMap.put(...) doesn't suffice anymore to tickle the session. Explaining why I only saw one replication occur.
In order to ensure replication to occur, we can still use the reset strategy, but use session.setAttribute(...) instead of sessionMap.put(...). In order to test this I added the following to my window scoped bean:
((javax.servlet.http.HttpSession)FacesUtils.getExternalContext().getSession(false)).setAttribute(
"org.icefaces.impl.application.WindowScopeManager",
((javax.servlet.http.HttpSession)FacesUtils.getExternalContext().getSession(false)).
getAttribute("org.icefaces.impl.application.WindowScopeManager"));
This "fixed" at least the window scoped bean scenario. I could use this strategy as well for the view scoped beans be resetting the LogicalViewMap, to see if that would help that scenario as well.
Now this should not be the definite solution of course, as this should not have to be done in the application. We should see where we can put this logic in the framework at least for the window scoped beans scenario.