0

Firstly, I am newbie in Vaadin 7. I was just trying out some vaadin demo when I discovered the BeanFieldGroup.class. As I saw ,this class bound a field to a bean property. In the bean the properties are annotated with validation constraints annotations ( JSR 303 ). In this case my pom.xml include hibernate validator dependency:

<dependency>
        <groupId>org.hibernate</groupId>
        <artifactId>hibernate-validator</artifactId>
        <version>5.1.0.CR1</version>
</dependency>

I made ValidationMessage.properties file and put there some messages, ( with Hungarian characters ) and it has been saved UTF-8 format,for example :

validation.NotBlank=Árvíztűrő tükörfúrgép

And here is the annotated bean property:

@NotNull(message = "{validation.NotBlank}")
private String name = null;

I can see, when I change the field value to null, Vaadin show me my previous constraint error message, but with wrong character coding.

In other hand - without Vaadin, but Spring,I can use the next simple formula where the character coding is appropriate me ( as you can see I use Spring ReloadableResourceBundleMessageSource) :

private MessageSource MessageSource(){
    ReloadableResourceBundleMessageSource reloadableResourceBundleMessageSource = new ReloadableResourceBundleMessageSource();
    reloadableResourceBundleMessageSource.setCacheSeconds(5000);
    reloadableResourceBundleMessageSource.setFallbackToSystemLocale(false);
    reloadableResourceBundleMessageSource.setDefaultEncoding("UTF-8");
    Properties properties = new Properties();
    properties.setProperty("fileEncodings", "UTF-8");
    reloadableResourceBundleMessageSource.setFileEncodings(properties);
    reloadableResourceBundleMessageSource.setBasename("classpath:/locales/messages");

    return reloadableResourceBundleMessageSource;
}

@Bean
public LocalValidatorFactoryBean validator(){

    LocalValidatorFactoryBean factory = new LocalValidatorFactoryBean();
    factory.setValidationMessageSource(MessageSource());

    return factory;
}

My question is: Can Somebody tell me the right solution how do I configure hibernate validator or Vaadin to read property files with UTF-8 encoding ?

Viktor Gintner
  • 135
  • 2
  • 13

2 Answers2

2

By default, ISO-8859-1 encoding is used when reading properties files. Characters not available in that encoding must be converted using Unicode escapes ("\u1234"), e.g. using the native2ascii tool. See this answer to a related question for some more details.

Alternatively, you could plug in a custom ResourceBundleLocator which reads properties using UTF-8 encoding. The Hibernate Validator reference guide describes how to do this. As a starting point, you could take PlatformResourceBundleLocator and adapt it as per your requirements.

Community
  • 1
  • 1
Gunnar
  • 18,095
  • 1
  • 53
  • 73
1

Vaadin's BeanFieldGroup uses another Vaadin class BeanValidator for JSR-303 validation. If you take a look at it's source code at BeanValidator.getJavaxBeanValidator() and getJavaxBeanValidatorFactory() methods, wou will see that it's building it's own Validator and ValidatorFactory instances. You'll need to subclass it and override the getJavaxBeanValidatorFactory() method with one that uses a ValidatorFactory obtained from your Spring context, which is properly set up to use Spring's own UTF-8 encoded MessageSource as you already configured it in your example. It will also help you with debugging as Spring's MessageSource can be reloadable, which is a huge saver.

EDIT: following a question in comments on how to override with subclassing I realized that with the current state of this part of the Vaadin API as of version 7.5.9, I can't do it elegantly. Since we can't do it elegantly we could do it the quick and dirty way by reflection with this hack implemented as a spring component:

@Component
public class VaadinValidationHack implements InitializingBean {

    @Autowired
    private ValidatorFactory validatorFactory;

    protected void hack() throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
        Field field = BeanValidator.class.getDeclaredField("factory");
        if (!field.isAccessible()) {
            field.setAccessible(true);
        }
        field.set(null, validatorFactory);
    }

    @Override
    public void afterPropertiesSet() throws Exception {
        hack();
    }

}
Nándor Előd Fekete
  • 6,988
  • 1
  • 22
  • 47
  • Hi! Thanks your answer. I get you, but I don't exactly now, how do I obtain my BeanFieldGroup's ValidatorFactory instance. Could you show a short example? – Viktor Gintner Jan 19 '16 at 07:36
  • I'd rather do the configuration via Bean Validation's validation.xml descriptor instead of reflection hacks. This configures the default validator factory which also should be the one picked up by Vaadin. – Gunnar Jan 21 '16 at 11:27
  • I evaluated your suggestion. Configuring a custom `ValidationProvider` in `validation.xml` could be a way to do it, delegating to `HibernateValidator` until it is set up by Spring, and delegating to the Spring configured stuff from the point it gets configured by Spring. But it still won't be a clean solution as it will admittedly violate the `ValidationProvider` contract at some point, at least when it would override API based configuration with configuration coming from Spring. And this violation of the contract would affect all the application, while the reflection hack only affects Vaadin. – Nándor Előd Fekete Jan 21 '16 at 12:27
  • Hi there! I have just tried your solution. It is working properly ! But there is an another interesting think. I tried use this local : new Local("hu") with xxx_hu.properties file, but this pair didn't work, in other hand if I use new Local("hu","HU") with xxx_hu_HU.properties file, this pair is working properly. Thanks for your help !!! – Viktor Gintner Jan 24 '16 at 14:27