Hi Boris.

We can't change f:convertNumber's behavior -- it's in the spec that way.

I've developed a convertNumberAsBigDecimal converter class, however.

At some point, it should probably get put into the sandbox, but that
probably won't happen for awhile as I don't have time to personally do
it right -- I'm using facelets and I have no need to add in all of the
JSP support.

You're welcome to open a JIRA issue, clean up the code, provide some
docs and an example, and attach everything to the issue if you want
though.

Note that I'm primarily using this for currency conversion and haven't
really tested much of anything else.

Here's the code:

package converter;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.ConverterException;
import javax.faces.convert.NumberConverter;

public class NumberAsBigDecimalConverter extends NumberConverter
{
   public static final String CONVERTER_ID =
"com.gvea.jsf.converter.NumberAsBigDecimalConverter";

   public Object getAsObject(FacesContext facesContext,
           UIComponent uiComponent, String value)
   {
        
        if (getType().equals("currency")) {
                        // Might need to add the currency symbol into it.

                        NumberFormat numberFormat = 
NumberFormat.getCurrencyInstance(getLocale());

                        if (numberFormat instanceof DecimalFormat) {
                                // determine if symbol is prefix or suffix
                                DecimalFormatSymbols decimalFormatSymbols = 
((DecimalFormat)
numberFormat).getDecimalFormatSymbols();
                                String currencySymbol = 
decimalFormatSymbols.getCurrencySymbol();
                                String localizedPattern = ((DecimalFormat)
numberFormat).toLocalizedPattern();
                                int currencySymbolIndex = 
localizedPattern.indexOf('\u00A4'); //
currency sign

                                boolean isCurrencySignPrefixed;
                                if (currencySymbolIndex > 0) {
                                        isCurrencySignPrefixed = false;
                                } else {
                                        isCurrencySignPrefixed = true;
                                }

                                currencySymbolIndex = 
value.indexOf(currencySymbol);
                                if (currencySymbolIndex == -1) {
                                        if (isCurrencySignPrefixed) {
                                                value = currencySymbol + value;
                                        } else {
                                                value = value + " " + 
currencySymbol;
                                        }
                                }
                        }
                }
        
       Number number = (Number)super.getAsObject(facesContext,
uiComponent, value);
       if (null == number)
       {
           return null;
       }

       if (number instanceof Double)
       {
           return new BigDecimal(number.doubleValue());
       }

       if (number instanceof Long)
       {
           return BigDecimal.valueOf(number.longValue());
       }

//        throw new
ConverterException(_MessageUtils.getErrorMessage(facesContext,
//                CONVERSION_MESSAGE_ID,
//                new Object[]{uiComponent.getId(),value}), e);
       throw new ConverterException("Expected number of type <Double>
or <Long> but received type <" + number.getClass().getName() + ">,
value <" + number.toString() + ">");
   }
}



On 7/24/06, Boris Kovalenko <[EMAIL PROTECTED]> wrote:
Hello!

        Thanks, Bill! You are absolutely right!

P.S. Dear developers, can You look at f:convertNumber for BigDecimal
improvements?

Bill Schneider wrote:
>> Hello!
>>
>> What does this error mean:
>>
>> /pages/admin/references/services/edit.xhtml @72,0
>> value="#{serviceform.periodicService.price}": Exception setting
>> property price of base with class
>> ru.tagnet.beans.references.services.PeriodicService
>>
>> It ocurred what I use
>> <f:convertNumber pattern="#{bundle['formats.currency.2d']}"/>
>> on h:inputText. formats.currency.2d == #,##0.00 and input field is of
>> class java.math.BigDecimal
>
>
> Hi Boris,
> Check your server error logs to see if there is more detail from an
> underlying exception.
>
> My guess is, f:convertNumber isn't playing nicely with the setter for
> BigDecimal, and there is a ClassCastException or NoSuchMethodException
> somewhere.
>
> You could change your getter/setter to take/return a java.lang.Number
> instead, for example
>
> private BigDecimal price;
> public Number getPrice() {
>   return price;
> }
> public void setPrice(Number n) {
>   if (n instanceof BigDecimal)
>     price = (BigDecimal) n;
>   } else {
>     price = new BigDecimal(n.doubleValue());
>   }
> }
>
> that way, if the convert tries to pass in a Double instead, it gets
> converted in your setter.
>
> hope this helps,
>
> -- Bill
With respect,
        Boris

Reply via email to