Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

## org.apache.myfaces.orchestra.lib.jsf
Class SerializableConverter

    java.lang.Object
      org.apache.myfaces.orchestra.lib.jsf.SerializableConverter

All Implemented Interfaces:
  javax.faces.component.StateHolder, javax.faces.convert.Converter

    public class SerializableConverter

extends Object
implements javax.faces.convert.Converter, javax.faces.component.StateHolder

Manually implement a proxy for Converter objects which can correctly serialize a Converter instance that has been wrapped in an Orchestra proxy.

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.

## Using from an orchestra:converter tag

When the orchestra:converter tag is used, the fetched object is wrapped in an instance of this type by default.

## Using from a converter attribute

A component in a page can specify `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.

## Further details on serialization

When using client-side state saving, the view tree is serialized by JSF at the end of each request, and sent to the user along with the generated output.

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.

Constructor Summary
`SerializableConverter()`
`SerializableConverter(String beanName)`
`SerializableConverter(String beanName, javax.faces.convert.Converter instance)`

Method Summary
`Object` | `getAsObject(javax.faces.context.FacesContext context, javax.faces.component.UIComponent component, String value)`
`String` | `getAsString(javax.faces.context.FacesContext context, javax.faces.component.UIComponent component, Object value)`
`protected javax.faces.convert.Converter` | `getConverter(javax.faces.context.FacesContext context)`
`boolean` | `isTransient()`
`void` | `restoreState(javax.faces.context.FacesContext context, Object savedState)`
`Object` | `saveState(javax.faces.context.FacesContext context)`
`void` | `setBeanName(String beanName)`
`void` | `setTransient(boolean newTransientValue)`

Methods inherited from class java.lang.Object
`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

Constructor Detail

### SerializableConverter

    public SerializableConverter()

### SerializableConverter

    public SerializableConverter(String beanName)

### SerializableConverter

    public SerializableConverter(String beanName,
                                 javax.faces.convert.Converter instance)

Method Detail

### setBeanName

    public void setBeanName(String beanName)

### getConverter

    protected javax.faces.convert.Converter getConverter(javax.faces.context.FacesContext context)

### getAsObject

    public Object getAsObject(javax.faces.context.FacesContext context,
                              javax.faces.component.UIComponent component,
                              String value)
                       throws javax.faces.convert.ConverterException

  Specified by:
    `getAsObject` in interface `javax.faces.convert.Converter`
  Throws:
    `javax.faces.convert.ConverterException`

### getAsString

    public String getAsString(javax.faces.context.FacesContext context,
                              javax.faces.component.UIComponent component,
                              Object value)
                       throws javax.faces.convert.ConverterException

  Specified by:
    `getAsString` in interface `javax.faces.convert.Converter`
  Throws:
    `javax.faces.convert.ConverterException`

### isTransient

    public boolean isTransient()

  Specified by:
    `isTransient` in interface `javax.faces.component.StateHolder`

### restoreState

    public void restoreState(javax.faces.context.FacesContext context,
                             Object savedState)

  Specified by:
    `restoreState` in interface `javax.faces.component.StateHolder`

### saveState

    public Object saveState(javax.faces.context.FacesContext context)

  Specified by:
    `saveState` in interface `javax.faces.component.StateHolder`

### setTransient

    public void setTransient(boolean newTransientValue)

  Specified by:
    `setTransient` in interface `javax.faces.component.StateHolder`

Overview | Package | Class | Use | Tree | Deprecated | Index | Help
PREV CLASS NEXT CLASS | FRAMES NO FRAMES
SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD

Copyright © 2012 The Apache Software Foundation. All Rights Reserved.