You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by sk...@apache.org on 2008/02/22 10:49:13 UTC

svn commit: r630132 - /myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java

Author: skitching
Date: Fri Feb 22 01:49:10 2008
New Revision: 630132

URL: http://svn.apache.org/viewvc?rev=630132&view=rev
Log:
Update documentation only.

Modified:
    myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java

Modified: myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java
URL: http://svn.apache.org/viewvc/myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java?rev=630132&r1=630131&r2=630132&view=diff
==============================================================================
--- myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java (original)
+++ myfaces/orchestra/trunk/core/src/main/java/org/apache/myfaces/orchestra/lib/jsf/SerializableConverter.java Fri Feb 22 01:49:10 2008
@@ -26,35 +26,30 @@
 import javax.faces.convert.ConverterException;
 
 /**
- * Wraps a converter so that when the parent component is serialized,
- * just the beanName of the component is saved.
+ * Manually implement a proxy for Converter objects which can correctly
+ * serialize a Converter instance that has been wrapped in an Orchestra proxy.
  * <p>
- * When the parent component is recreated, this wrapper will then
- * refetch the converter using the saved beanName. This will discard
- * all state that the converter instance has, but for most converters
- * that doesn't matter.
- * <p>
- * If the converter does implement the JSF StateHolder interface, then
- * that will be called on serialize and deserialize to explicitly save
- * and restore the state on the object. However implementing the
- * standard java.io.Serializable interfaces on Converter objects is
- * not currently supported.
- * <p>
- * This class is primarily intended to wrap Converter beans which are
- * associated with Orchestra conversations. Objects in conversation scopes
- * are wrapped in proxy objects that are unfortunately not serializable;
- * this is not a problem for backing beans in orchestra scopes as they are
- * not serialized along with the view tree but it is a problem for Converter
- * objects as they are part of the view tree and get serialized at the end
- * of each request (and deserialized at the start of each postback). Using
- * the SerializableConverter as a wrapper solves this issue by simply storing
- * the beanName of the converter when serialization occurs, and reloading
- * the bean by name on deserialize.
- * <p>
- * If the converter has no internal state (other than that defined in the
- * bean definition) then nothing more needs to be done. However when the
- * converter does have state, it should implement the JSF StateHolder
- * interface; the SerializableConverter wrapper will invoke that 
+ * A custom converter may need access to orchestra scopes or Orchestra
+ * persistence contexts. In these cases, it must be wrapped in the appropriate
+ * Orchestra proxies. Unfortunately these proxies are not serializable;
+ * they implement neither java.io.Serializable nor the JSF StateHolder interface.
+ * Therefore when a view tree containing components that have such a converter
+ * attached, a serialization failure will occur.
+ * <p>
+ * This class can be used to "wrap" such converter instances, making 
+ * serialization work again. This class implements the JSF StateHolder
+ * interface, and implements this by saving both its own state AND the
+ * state of the Converter it proxies. In addition, the beanName used to
+ * create the original converter instance is kept. When the view tree
+ * is restored, JSF will automatically recreate an instance of this type
+ * and restore its state; this then retrieves a new (proxied) instance of
+ * the converter using the beanName, then invokes the restoreState method
+ * on it passing the saved state data.
+ * <p>
+ * Note that if the converter has no internal state (other than that defined
+ * in the bean definition) then it does not need to implement the StateHolder
+ * interface; when the view tree is restored a new instance will be created
+ * using the beanName. 
  * 
  * <h2>Using from an orchestra:converter tag</h2>
  * 
@@ -73,22 +68,47 @@
  * intercepts creation of all Converter instances and automatically wraps
  * them in a SerializableConverter.
  * 
- * <h2>Outstanding Issues</h2>
+ * <h2>Further details on serialization</h2>
  *
- * We do want to serialize conversation-scoped managed beans when a session
- * is transferred to another machine, or is passivated. Therefore we need to
- * solve the serializing of proxied objects in a general way eventually. And
- * that will then make this workaround irrelevant.
- * <p>
- * If we can drill down from the proxy to the underlying bean, then we could
- * use standard java.io.Serialization on it if that is supported. This
- * "drilling down" functionality is very useful in other cases too.
- * <p>
- * We already have a method ConversationUtils.getCurrentBean which has a comment
- * that a generic "proxy this object" mechanism would be useful. If that existed,
- * then deserializing could use the same approach: drill down and serialize the
- * underlying bean, then later unserialize the underlying bean and generate new
- * proxies for it.
+ * When using client-side state saving, the view tree is serialized <i>by JSF</i>
+ * at the end of each request, and sent to the user along with the generated output.
+ * <p>
+ * When using server-side state, the JSF implementation might use JSF serialization
+ * to generate data to cache in the session, or might just store a reference to 
+ * the unserialized component tree. The latter is not generally wise as switching
+ * to client-side state saving later will suddenly change the way that the tree
+ * is handled on save and postback and may expose bugs in component serialization
+ * (particularly for custom components), so JSF implementations either default to
+ * JSF-serialization even on server-side state, or do not even offer the option
+ * to save an unserialized tree. 
+ * <p>
+ * If a servlet engine is configured for distributed sessions, then when a request
+ * is handled by a different server than handled the last request, the session is
+ * serialized on the host that handled the old request and deserialized on the host
+ * handling the new request. 
+ * <p>
+ * Even without distributed sessions, a servlet engine will serialize sessions when
+ * short of memory ("session passivation") and cache them on disk. Session serialization
+ * also happens when a servlet engine is reconfigured for "hot restart", ie where the
+ * server can be rebooted without losing user sessions.
+ * <p>
+ * With both the client-side or server-side with "normal" JSF serialization, JSF
+ * will first try to serialize converters using the StateHolder methods, and only use
+ * java.io.Serializable when that is not supported. Therefore having this class implement
+ * StateHolder, and then requiring all converters used with this wrapper to implement
+ * StateHolder solves the serialization issues. This class does not need to implement
+ * java.io.Serializable because serialization is always done via the StateHolder methods
+ * instead.
+ * <p>
+ * For applications where a raw JSF tree is stored in the session, then an attempt by
+ * the server to serialize the session might trigger an attempt to use java.io.Serializable
+ * apis on this object. As this does not implement the java.io.Serializable, an exception
+ * will occur. This class cannot simply implement java.io.Serializable because the object
+ * it references is usually proxied, and the proxies are not generally serialiuable. It
+ * *might* be possible for this code to implement normal serialization by "unproxying"
+ * the bean, invoking serialization on the real object, then on deserialize re-wrapping
+ * the bean in proxies. However as this code is unlikely to ever be used, this has not
+ * been implemented.
  */
 public class SerializableConverter implements Converter, StateHolder
 {