0

I have a requirement to use BigDecimal type in one of my JSF application.
So I'm using the BigDecimal Converter for the conversion as below:

<h:inputText value="#{priceManager.price}">
    <f:converter converterId="javax.faces.BigDecimal"/>
</h:inputText>

This works fine.
Along with this conversion I also want to restrict

  • Value must be between -9999 to 9999. and
  • Only 2 numbers after the decimal point.

Apparently f:converter isn't much flexible as f:convertNumber.
So how to achieve the above things?
If it requires overriding the default Converter, I'll do it, but i never done it before.
Please give me some suggestions.

Mojarra Version - 2.1

4

2 回答 2

3

I do not know if it is good practice, to let a converter do validation, but it is the cleanest way I see. This converter works fine for me:

package teststuff;

import java.math.BigDecimal;
import java.math.RoundingMode;

import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.convert.FacesConverter;

import org.apache.commons.lang3.math.NumberUtils;

@FacesConverter("bigDecimalConverter")
public class BigDecimalConverter implements Converter {

    private static final BigDecimal UPPER_LIMIT = new BigDecimal(9999);
    private static final BigDecimal LOWER_LIMIT = new BigDecimal(-9999);

    @Override
    public Object getAsObject(FacesContext context, UIComponent component,
            String value) {
        if (!NumberUtils.isNumber(value)) {
            throw new ConverterException(new FacesMessage("not a number"));
        }
        if (value.contains(".")) {
            String decimalPlace = value.substring(value.indexOf("."));
        if (decimalPlace.length() > 3) { // 3 as decimal point is included in the String
                throw new ConverterException(new FacesMessage(
                        "too many numbers after decimal point"));
            }
        }
        BigDecimal convertedValue = new BigDecimal(value).setScale(2,
                RoundingMode.HALF_UP);
        if (convertedValue.compareTo(UPPER_LIMIT) > 0) {
            throw new ConverterException(new FacesMessage(
                    "value may not be greater than " + UPPER_LIMIT));
        }
        if (convertedValue.compareTo(LOWER_LIMIT) < 0) {
            throw new ConverterException(new FacesMessage(
                    "value may not be less than " + LOWER_LIMIT));
        }
        return convertedValue;
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component,
            Object value) {
        return ((BigDecimal) value).toString();
    }
}

I just use it like this:

<h:form>
       <h:inputText value="#{priceManager.price}" converter="bigDecimalConverter"/>
       <h:messages/>
       <h:commandButton value="submit"/>
    </h:form>

I appreciate any feedback on this.

于 2013-10-16T19:35:48.907 回答
1
@FacesConverter("bigDecimalConverter")
public class BigDecimalCoverter implements Converter{        

    @Override
     public Object getAsObject(FacesContext context, UIComponent component,
       String value) {
            BigDecimal valueDecimal=(BigDecimal)value;  
            if(valueDecimal.compareTo(valueDecimal)>9999 && valueDecimal.compareTo(valueDecimal)<-9999){
                 valueDecimal.setScale(2, RoundingMode.CEILING)
            }
            else{                       
                FacesMessage msg = new FacesMessage("Number not in range");
                msg.setSeverity(FacesMessage.SEVERITY_ERROR);
                throw new ConverterException(msg);                   
            }       
            return valueDecimal;
       }

        @Override
        public String getAsString(FacesContext context, UIComponent component,
            Object value) {
            return value.toString();

        }   
  }

And place

  <h:inputText value="#{priceManager.price}">
   <f:converter converterId="bigDecimalConverter"/>
 </h:inputText>
于 2013-10-16T10:37:22.423 回答