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.
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.
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.
converter="#{someBeanName}"
. The definition for bean "someBeanName" should specify that a non-singleton instance of this class should be created, and the "beanName" constructor parameter should be set to refer to another bean-definition that is the actual converter type to be instantiated. When using Spring, a BeanPostProcessor class could also be defined that intercepts creation of all Converter instances and automatically wraps them in a SerializableConverter.
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.
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.
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.
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.
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.
Hopefully in some later release, the Orchestra-generated proxies will be able to correctly serialize themselves automatically. When that happens, this class will no longer be needed.
|
|
|
|
|
|
|
|