2016-02-11 3 views
2

Мне нужно преобразовать null значения свойств типа java.math.BigDecimal в 0.00 везде с указанным числом знаков после запятой (только для отображения (<h:outputText>), таким образом, а не для входных компонентов).JSF конвертер с нулевым значением

Базовый конвертер, ожидаемый для выполнения этой работы, приведен ниже (валюта, процент, язык и т. Д. Полностью исключены для краткости).

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

    private static final int SCALE = 2; 

    @Override 
    public Object getAsObject(FacesContext context, UIComponent component, String submittedValue) { 

     if (submittedValue == null || submittedValue.isEmpty()) { 
      return null; 
     } 

     try { 
      return new BigDecimal(submittedValue).setScale(SCALE, RoundingMode.HALF_UP).stripTrailingZeros(); 
     } catch (NumberFormatException e) { 
      throw new ConverterException(new FacesMessage(FacesMessage.SEVERITY_ERROR, null, "Message"), e); 
     } 
    } 

    @Override 
    public String getAsString(FacesContext context, UIComponent component, Object modelValue) { 

     BigDecimal value; 

     if (modelValue == null) { // This is expected to replace null with 0. 
      value = BigDecimal.ZERO; 
     } else if (modelValue instanceof Long) { 
      value = BigDecimal.valueOf((Long) modelValue); 
     } else if (modelValue instanceof Double) { 
      value = BigDecimal.valueOf((Double) modelValue); 
     } else if (!(modelValue instanceof BigDecimal)) { 
      throw new ConverterException("Message"); 
     } else { 
      value = (BigDecimal) modelValue; 
     } 

     NumberFormat numberFormat = NumberFormat.getNumberInstance(); 
     numberFormat.setGroupingUsed(true); 
     numberFormat.setMinimumFractionDigits(SCALE); 
     numberFormat.setMaximumFractionDigits(SCALE); 
     return numberFormat.format(value); 
    } 
} 

Обращаясь к свойству соответствующей модели или фасоли типа java.math.BigDecimal с использованием выходных компонентов, как в следующем.

<h:outputText value="#{bean.value}"> 
    <f:converter converterId="bigDecimalConverter"/> 
</h:outputText> 

bean.value является тип java.math.BigDecimal в управляемом компоненте. Если bean.value - null, то метод getAsString() не вызывается. Следовательно, пустой вывод выводится там, где ожидается нулевое значение.

Этот value="#{bean.value}" необходимо изменить на value="#{empty bean.value ? 0 : bean.value}", чтобы конвертер выполнил свою согласованную задачу.

Внесение этого условного теста в EL повсюду, однако, довольно не требует обслуживания.

Есть ли способ, чтобы вызвать метод getAsString(), когда цель свойство null, который условно пытался быть установлен 0 в этом методе (BigDecimal.ZERO)?


Обновление:

Метод getAsString() вызывается с <o:param> (OmniFaces).

<h:outputFormat value="Discount ({0}%)"> 
    <o:param value="#{bean.value}"> 
     <f:converter converterId="bigDecimalConverter"/> 
    </o:param> 
</h:outputFormat> 

Это показывает Discount (0.00%) после того, как был преобразован преобразователем, когда #{bean.value} возвращается null.

+0

Было бы полезно предоставить JSF impl-версию. –

+0

Это Моджара 2.2.12. Протестировано на Apache Tomcat 8.0.27.0, GlassFish 4.1 и WildFly 10.0.0 в качестве альтернативы. – Tiny

ответ

0

Это характерно для Мохары. Проблема возникла из-за того, что преобразователь не вызывается, когда значение равно null (см. source here). Я тестировал один и тот же код в реализации MyFaces, и результат заключается в том, что конвертер всегда вызывается, независимо от того, имеет ли значение значение null (как можно видеть here, строка 378).

Так что если изменение реализации JSF не является вариантом, я думаю, что решение через OmniFaces достаточно хорошее. В худшем случае поддерживайте функцию, которая делает преобразование, например #{convert(bean.value)}, может оставить более чистым ваше представление, чем встроенное сравнение.

+0

Какой способ рекомендован OmniFaces для защиты от этой конкретной проблемы? – Tiny

+0

OmniFaces имеет свою собственную [реализацию param] (https://github.com/omnifaces/omnifaces/blob/master/src/main/java/org/omnifaces/component/output/Param.java#L120), [ o: param] (http://showcase.omnifaces.org/components/param), который также вызывает конвертер, независимо от значения null. Таким образом, вы можете использовать этот компонент для преобразования, как показано в обновлении вашего вопроса. Но если вы хотите простое преобразование, чтобы показать значение как есть, я думаю, что функция типа '# {bean.convertNullAsZero (bean.value)} 'сделает работу проще и понятнее. –

Смежные вопросы