You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Rudy De Busscher <rd...@gmail.com> on 2011/11/28 15:06:16 UTC

Question about converter with attribute and keeping 'state' (JSF 2.0)

Hi all,

For my application, I need a converter that can format financial values.
But at some locations, I need 2 digits after the comma and somewhere else I
need 4 digits.

So I created a converter and defined a tag with Facelets so that I can set
the 4 digits when needed.

But the number of digits is only correct when the page is initially
displayed, after a post (full or ajax) I always loose the value of the
attribute of the facelets tag converter.

This is the code
*
@FacesConverter(value = "bigDecimalConverter")
public class BigDecimalValueConverter implements Converter {

    private Integer digitsAfterDecimalSeparator;

    public Object getAsObject(FacesContext context, UIComponent component,
String value) throws ConverterException {
        return BigDecimal.valueOf(Double.valueOf(value));
    }

    public String getAsString(FacesContext context, UIComponent component,
Object value) throws ConverterException {
        String result;
        if (digitsAfterDecimalSeparator == null) {
            // When used as attribute on component or as f:converter, no
parameter specified and thus default.
            result =
ConverterUtil.DefaultBigDecimalValueAsString((BigDecimal) value);
        } else {
            result = ConverterUtil.BigDecimalValueAsString((BigDecimal)
value, digitsAfterDecimalSeparator);
        }
        return result;
    }

    // setter and getter for digitsAfterDecimalSeparator
}*

facelets tag library
*    <tag>
        <tag-name>bigDecimalConverter</tag-name>
        <converter>
            <converter-id>bigDecimalConverter</converter-id>
        </converter>
    </tag*


Looking into the source I found out that
- The attribute on the converter is set during build view by
ConverterTagHandlerDelegate#applyAttachedObject method by statement
_delegate.setAttributes(faceletContext, c)
- This ConverterTagHandlerDelegate isn't called during restore view
- When the state is saved, the converter info isn't stored.  (quite logic
since I didn't implement StateHolder)


Looking at the javax.faces.component.UIComponentBase#saveAttachedState
method, I see that implementing Serializable is enough (and I verified that
it works) and also StateHolder is a solution of course.

So sorry for this large introduction but here are my questions:

- Implementing StateHolder is the best strategy I guess (better then
Serializable)?  Also because the JSF specification states "The StateHolder
interface is implemented by UIComponent, Converter, FacesListener, and
Validator classes that need to save their state between requests." (3.2.4 :
StateHolder)
- Isn't it always required that Converter also implements StateHolder,
based on that line in the JSF Specification? Or how should we interprete
that sentence?
- How can we use EL expressions as attribute on converter tags?  Since that
EL is only once evaluated and thus attribute doesn't reflect the current
value.

I compared with Mojarra, and there the attributes are sets during build
view in the render response but also in restore view phase.  So there the
attribute value isn't lost, without the need of implementing StateHolder.

Hope this is clear to someone. If needed, I have an example web application
that demonstrate the behaviour.

regards
Rudy


-- 
Rudy De Busscher
http://www.c4j.be