Announcement Announcement Module
Collapse
No announcement yet.
Spring 3.0 Annotated Formatter Not Working Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Spring 3.0 Annotated Formatter Not Working

    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:

    Code:
    <mvc:annotation-driven conversion-service="formattingFactory" /> <bean id="formattingFactory" class="com.rubyrentals.spring.formatters.FormattingFactory" />
    The FormattingFactory class:
    Code:
    public class FormattingFactory extends FormattingConversionServiceFactoryBean {
    
    	@Override
    	protected void installFormatters(FormatterRegistry registry) {		
    		registry.addFormatterForFieldAnnotation(new MonthNameFormatterFactory());
    		registry.addFormatterForFieldAnnotation(new ImpliedCurrencyFormatterFactory());
    		super.installFormatters(registry);		
    	}
    	
    }
    The MonthName formatter:
    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 MonthNameFormat attribute:
    Code:
    @Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    public @interface MonthNameFormat {
    }
    The MonthNameFormatterFactory class:
    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();
    	}
    
    }
    The following unit tests work, but the formatter is not picked up through the JSP page even though I use spring:bind tag.

    MonthNameFormatterTests
    Code:
    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());
    		}
    	}
    	
    }
    MonthNameFormatterFactoryTests
    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());
    		}
    		
    	}
    	
    }

  • #2
    It works with the form tags not with the spring:bind tags...

    Comment


    • #3
      It works with @NumberFormat

      It works with @NumberFormat and I am using same SPI/API.

      Comment


      • #4
        AFAIK it doesn't work with the old tags, but I could be mistaken. If it works then post some more code and configuration....

        Comment


        • #5
          It works in 3.0.6 but not in 3.1.0 M2

          The @NumberFormat will work with the spring:bind JSP tag under the 3.0.6 release. However, it doesn't work under the new 3.1.0 M2 release. Thanks for all the input on this issue.

          Also, in another post it was mentioned that in 3.1 release you will be able to use SPEL expression in JSP page without binding or form tags and the formatting will be applied. Can someone on the Spring core team speak to this? Is it on the road map for RC of 3.1?

          Thanks!

          Comment


          • #6
            @NumberFormat works in 3.1. You just need to use the <spring:eval/> tag. I have documented some enhancements I needed to do for the NumberFormat (rounding for example) in http://thinkinginsoftware.blogspot.c...on-driven.html

            Hopefully it will help others.

            On a side note I would appreciate if the Spring team can respond if it makes sense to incorporate the enhancements in future versions.

            Thanks!
            -Nestor

            Comment

            Working...
            X