I am attempting to leverage the new annotated formatter support in Spring 3+. I am using Spring 3.0.6 and my custom formatters are not being appliedin my JSP page even though I register them and use spring:bind tag.
My application context is configured as follows:
The FormattingFactory class:Code:<mvc:annotation-driven conversion-service="formattingFactory" /> <bean id="formattingFactory" class="com.rubyrentals.spring.formatters.FormattingFactory" />
The MonthName formatter:Code:public class FormattingFactory extends FormattingConversionServiceFactoryBean { @Override protected void installFormatters(FormatterRegistry registry) { registry.addFormatterForFieldAnnotation(new MonthNameFormatterFactory()); registry.addFormatterForFieldAnnotation(new ImpliedCurrencyFormatterFactory()); super.installFormatters(registry); } }
The MonthNameFormat attribute:Code:public class MonthNameFormatter implements Formatter<Number> { @Override public String print(Number value, Locale locale) { DateTime date = new DateTime(); return date.withMonthOfYear((Integer) value).monthOfYear().getAsText(); } @Override public Number parse(String value, Locale locale) throws ParseException { return DateTimeFormat .forPattern("MMMM") .withLocale(locale) .parseDateTime(value) .getMonthOfYear(); } }
The MonthNameFormatterFactory class:Code:@Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) @Retention(RetentionPolicy.RUNTIME) public @interface MonthNameFormat { }
The following unit tests work, but the formatter is not picked up through the JSP page even though I use spring:bind tag.Code:/* * Configures MonthNameFormat annotation for use in spring. */ public final class MonthNameFormatterFactory implements AnnotationFormatterFactory<MonthNameFormat> { @Override public Set<Class<?>> getFieldTypes() { HashSet<Class<?>> set = new HashSet<Class<?>>(); set.add(Short.class); set.add(Integer.class); set.add(Long.class); set.add(BigInteger.class); return set; } @Override public Parser<Number> getParser(MonthNameFormat attribute, Class<?> clazz) { return new MonthNameFormatter(); } @Override public Printer<Number> getPrinter(MonthNameFormat arg0, Class<?> arg1) { return new MonthNameFormatter(); } }
MonthNameFormatterTests
MonthNameFormatterFactoryTestsCode:public class MonthNameFormatterTests { @Test public void BasicFormatterTest() { Integer month = 1; String monthName = "January"; try { MonthNameFormatter formatter = new MonthNameFormatter(); Assert.assertEquals(month, formatter.parse(monthName, Locale.getDefault())); Assert.assertEquals(monthName, formatter.print(month, Locale.getDefault())); } catch(Exception e) { Assert.fail("Failed to format value!\n" + e.getMessage()); } } }
Code:public class MonthNameFormatterFactoryTests extends AbstractSpringTest { /* * Sample class for testing */ public class MonthNameData { @MonthNameFormat private Integer month; public Integer getMonth() { return this.month; } public void setMonth(Integer month) { this.month = month; } public MonthNameData(Integer month) { this.setMonth(month); } } @Test public void FactoryCanConvertValueToString() { try { MonthNameData data = new MonthNameData(DateTimeConstants.JANUARY); PropertyDescriptor prop = new PropertyDescriptor("month", MonthNameData.class); MethodParameter param = MethodParameter.forMethodOrConstructor(MonthNameData.class.getMethod("getMonth", null), -1); PropertyTypeDescriptor desc = new PropertyTypeDescriptor(prop, param); FormattingConversionService service = (FormattingConversionService)this.applicationContext.getAutowireCapableBeanFactory().getBean("formattingFactory"); Assert.assertEquals("January", service.convert(data.getMonth(), desc, TypeDescriptor.valueOf(String.class))); } catch(Exception e) { Assert.fail("Error formatting MonthName!\n" + e.getMessage()); } } @Test public void FactoryCanConvertValueFromInt() { try { MonthNameData data = new MonthNameData(DateTimeConstants.JANUARY); PropertyDescriptor prop = new PropertyDescriptor("month", MonthNameData.class); MethodParameter param = MethodParameter.forMethodOrConstructor(MonthNameData.class.getMethod("setMonth", Integer.class), 0); PropertyTypeDescriptor desc = new PropertyTypeDescriptor(prop, param); FormattingConversionService service = (FormattingConversionService)this.applicationContext.getAutowireCapableBeanFactory().getBean("formattingFactory"); Assert.assertEquals(DateTimeConstants.JANUARY, service.convert("January", TypeDescriptor.valueOf(String.class), desc)); } catch(Exception e) { Assert.fail("Error formatting MonthName!\n" + e.getMessage()); } } @Test public void GenericConversionServiceCanConvertValueToString() { try { MonthNameData data = new MonthNameData(DateTimeConstants.JANUARY); PropertyDescriptor prop = new PropertyDescriptor("month", MonthNameData.class); MethodParameter param = MethodParameter.forMethodOrConstructor(MonthNameData.class.getMethod("getMonth", null), -1); PropertyTypeDescriptor desc = new PropertyTypeDescriptor(prop, param); GenericConversionService service = this.applicationContext.getAutowireCapableBeanFactory().getBean(GenericConversionService.class); Assert.assertEquals("January", service.convert(data.getMonth(), desc, TypeDescriptor.valueOf(String.class))); } catch(Exception e) { Assert.fail("Error formatting MonthName!\n" + e.getMessage()); } } @Test public void GenericConversionServiceCanConvertValueFromInt() { try { MonthNameData data = new MonthNameData(DateTimeConstants.JANUARY); PropertyDescriptor prop = new PropertyDescriptor("month", MonthNameData.class); MethodParameter param = MethodParameter.forMethodOrConstructor(MonthNameData.class.getMethod("setMonth", Integer.class), 0); PropertyTypeDescriptor desc = new PropertyTypeDescriptor(prop, param); GenericConversionService service = this.applicationContext.getAutowireCapableBeanFactory().getBean(GenericConversionService.class); Assert.assertEquals(DateTimeConstants.JANUARY, service.convert("January", TypeDescriptor.valueOf(String.class), desc)); } catch(Exception e) { Assert.fail("Error formatting MonthName!\n" + e.getMessage()); } } }


Reply With Quote
