myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Leonardo Uribe <lu4...@gmail.com>
Subject Re: JSF 2.1 State saving of UIOutput values
Date Fri, 05 Oct 2012 03:43:19 GMT
Hi

I feel like a 'deja vu' with this problem. In tomahawk 1.1.10, it was
introduced
an interface to deal with a similar problem for t:inputCalendar and t:inputDate
called DateBusinessConverter. The code looks like this:

/**
 * Provide a bridge between the java.util.Date instance used by a component
 * that receive date/time values and the "business" value used to represent
 * the value.
 *
 * @since 1.1.10
 * @author Leonardo Uribe (latest modification by $Author: lu4242 $)
 * @version $Revision: 691856 $ $Date: 2008-09-03 21:40:30 -0500 (mié,
03 sep 2008) $
 */
public interface DateBusinessConverter
{
    /**
     * Convert the java.util.Date instance calculated from submittedValue,
     * so the resulting object will be used later as the converted value
     * and validation.
     *
     * @param context
     * @param component
     * @param value
     * @return
     */
    public Object getBusinessValue(FacesContext context,
                       UIComponent component,
                       java.util.Date value);

    /**
     * Used to retrieve the value stored in the business bean and convert
     * it in a representation that the component (t:inputCalendar and
     * t:inputDate for example)using this class can manipulate.
     *
     * @param context
     * @param component
     * @param value
     * @return
     */
    public java.util.Date getDateValue(FacesContext context,
                       UIComponent component,
                       Object value);
}

In summary, this interface provides a "bridge" between the value to be
stored in the component (java.util.Date) and the value used in the bean.
In this case t:inputCalendar understands only java.util.Date instances
through CalendarDateTimeConverter, but with this we can have any
non serializable and non stateholder instance on the beans.

I know the intention of DateBusinessConverter is different to what
is mentioned here, but the concept behind it is still valid. The idea was
add some application scope object in tomahawk to deal with known
date types (joda Datetime and others), but that would require an
alternate faces-context.xml (tomahawk-context.xml).

Something we can do is use the existing <faces-config-extension> to
do something similar to what is proposed here and update the
standard components to deal with this. Recently, I added a custom
config param there, see:

https://issues.apache.org/jira/browse/MYFACES-3612

Is it worth to do it? maybe. This looks like something that you can't
really fix correctly without put it into myfaces core, but maybe something
like this should be solved in the spec directly, because otherwise,
component libraries outside myfaces cannot use it without break
compatibility with the spec.

regards,

Leonardo Uribe

2012/9/25 Mike Kienenberger <mkienenb@gmail.com>:
> I've never paid a lot of detail to the implementation of state saving
> up to this point as it never concerned me beyond implementing it in my
> own components.
>
> Now that I've upgraded from JSF 1.2 to 2.1, I have hit various state
> saving exceptions.  Some were due to t:saveState, which I have since
> gotten rid of (most of this project is session scoped, and t:saveState
> was a left-over from the original request-scoped project).   Some were
> due to trying to create deferred El evaluation in validators, and that
> code was likewise replaced with more appropriate code.
>
> However, my latest issue is with a UIInput with a Money converter.
> We have a special java class to represent Money amounts.
>
> <h:inputText value="#{page.amount}">
>         <my:convertMoney/>
>         <my:validatePositiveMoney/>
>         <a4j:ajax execute="@this" event="blur"
> listener="#{page.paymentAmountChanged}" render="totalsPanelId"/>
> </h:inputText>
>
> This has worked for the most part, except when validation of an
> unrelated input field on the same page fails.   Then attempting to
> continue after that causes the following exception for clazz =
> Money.class.  Note that Money isn't serializable.
>
>                 throw new RuntimeException("Could not restore
> StateHolder of type " + clazz.getName()
>                         + " (missing no-args constructor?)", e);
>             }
>
> So I traced through the code, and determined that this is because we
> are attempting to restore the "value" of the inputText, which is is of
> type Money.
>
> I read section 7.7 for StateManager in the JSF 2.1 spec.
>
>         Validators, Converters, FacesListeners, and other objects attached to
> a component. The manner in
>         which these attached objects are saved is up to the component
> implementation. For attached objects that may have
>         state, the StateHolder interface (see Section 3.2.4 “StateHolder”) is
> provided to allow these objects to preserve
>         their own attributes and properties. If an attached object does not
> implement StateHolder, but does implement
>         Serializable, it is saved using standard serialization. Attached
> objects that do not implement either
>         StateHolder or Serializable must have a public, zero-arg constructor,
> and will be restored only to their
>         initial, default object state.
>
> Since this is implementation-specific, we have latitude here.  Why do
> we not use the specified converter to create a string if the value
> object implements neither StateHolder nor Serializable?   We know the
> converter is going to produce reversible reference to the value object
> -- it is essentially going to serialize it into a String for us, which
> is likely to be far more useful than the initial, default object
> state.
>
> It seems to me that we should be doing this for all value objects with
> converters.
>
> I know we have to follow the spec otherwise I'd go a step further and
> say we should throw an exception rather than create an initial,
> default object state, since I'd rather know as soon as possible when a
> situation like this turns up rather than trying to debug some
> uniitialized object at some point down the road.  Maybe that's
> something we can add a oam behavior parameter for.

Mime
View raw message