Topics

#544: Localization & BeanValidation

Pavel Bucek
 

Dear experts,

we are working on improving integration with BeanValidation [1], and seems like if we choose to address this issue, the change will be slightly bigger than I anticipated.

In short, the issue is about providing Locale based on incoming request to the BV runtime, which can then choose it to provide localized error message. Since there is no way how to get a list of supported locales, we'd need to introduce a provider, which would register supported locales:

public interface SupportedLocaleProvider {
    
    List<Locale> getSupportedLocales();
}

If the application contains @Provider annotated subclass of this interface and there is a BV message to be produced, implementation would be required to do something like:

SupportedLocaleProvider supportedLocaleProvider = ...;
javax.ws.rs.Request request = ...;

List<Locale> locales = supportedLocaleProvider.getSupportedLocales();

javax.ws.rs.Variant.VariantListBuilder variantListBuilder = Variant.VariantListBuilder.newInstance();

List<Variant> vs = variantListBuilder.languages(locales.toArray(new Locale[]{})).build();
Variant v = request.selectVariant(vs);

(+ null checks, etc). If selected variant exists, then "v.getLanguage()" would be used as a Locale passed to BV runtime.

Please let us know what do you think about proposed solution of linked issue.

Also, the introduced interface might have more uses that just this (maybe too specific) case - any brainstorming ideas to what it could be used are welcomed.

Thanks and regards, Pavel

[1] https://github.com/jax-rs/api/issues/544

Sergey Beryozkin
 

Hi Pavel

Where would usually the code wishing to pass the Locale get the list of supported locales from, without even getting JAX-RS involved ?

If there was some well-known mechanism then the JAX-RS runtime would just use it as opposed to having to deal with a new provider...

Cheers, Sergey

On 22/05/17 17:46, Pavel Bucek wrote:

Dear experts,

we are working on improving integration with BeanValidation [1], and seems like if we choose to address this issue, the change will be slightly bigger than I anticipated.

In short, the issue is about providing Locale based on incoming request to the BV runtime, which can then choose it to provide localized error message. Since there is no way how to get a list of supported locales, we'd need to introduce a provider, which would register supported locales:

public interface SupportedLocaleProvider {
    
    List<Locale> getSupportedLocales();
}

If the application contains @Provider annotated subclass of this interface and there is a BV message to be produced, implementation would be required to do something like:

SupportedLocaleProvider supportedLocaleProvider = ...;
javax.ws.rs.Request request = ...;

List<Locale> locales = supportedLocaleProvider.getSupportedLocales();

javax.ws.rs.Variant.VariantListBuilder variantListBuilder = Variant.VariantListBuilder.newInstance();

List<Variant> vs = variantListBuilder.languages(locales.toArray(new Locale[]{})).build();
Variant v = request.selectVariant(vs);

(+ null checks, etc). If selected variant exists, then "v.getLanguage()" would be used as a Locale passed to BV runtime.

Please let us know what do you think about proposed solution of linked issue.

Also, the introduced interface might have more uses that just this (maybe too specific) case - any brainstorming ideas to what it could be used are welcomed.

Thanks and regards, Pavel

[1] https://github.com/jax-rs/api/issues/544


 

A JAX-RS application produces machine-readable information (XML, JSON, etc.), hence it does not support ANY human language by definition. BV provides machine-readable ConstraintViolations for this purpose; the message text plays no role in "real" REST, just like any message text of any Exception is of no interest to the end user. In a RESTful scenario, the translation of the BV exception is up to the front end designer, hence the CLIENT programmer (like MVC API, JSF, JavaFX) just as HE has to find nice and translated phrases for ANY OTHER exception already: Exceptions are INTERNAL and not to be forwarded 1:1 to the end user! So it is up to HIM to define the languages, while the text contained in a server's "error page" should stay in the same language always as it is NOT intended for the end user but for the programmer / administrator / devop! Hence how shall the author of a JAX-RS application ever decide which languages to support? JAX-RS does NOTHING with this information as you already said! In addition, what happens if the application programmer declares to define Chinese, but the BV implementation does not support Chinese? That won't work. I would rather say, this is solely a MVC feature and should not be defined by JAX-RS.

Gunnar Morling
 

Bean Validation spec lead here, thanks a lot for considering this feature!

> Since there is no way how to get a list of supported locales

Why is it that you need to get the list of locales? The Locale mechanism has fallback implemented which is used by Bean Validation. So e.g. say you have ValidationMessages.properties, ValidationMessages_en.properties and ValidationMessages_de.properties. If you request with "en" or "en_US", it'd take the second. If you request with "de", it'd take the last one. If you request with any other Locale, it'd take the first one. This all happens automatically.

> hence the CLIENT programmer (like MVC API, JSF, JavaFX) just as HE has to find nice and translated phrases for ANY OTHER exception already

I think there are good reasons for doing I18N on the server and on the client, it's not that one is always better than the other. E.g. doing it on the backend (i.e. JAX-RS) allows different clients to benefit from translations (say a JavaFX client as well as a web client using the same REST API). JSF btw. is integrating with Bean Validation already in the suggested way: it takes its current Locale and passes it to BV. I personally think JAX-RS could do it exactly in the same way: set up a Bean Validation message interpolator which takes the Locale from requests and passes this to calls of interpolate().

--Gunnar

Santiago Pericas-Geertsen
 

Hi Gunnar,

 Other than message interpolation, is there any other scenario where locale information is important in BV? What comes to mind is a string that contains a representation of a locale-specific date format, for example. 

 Pavel and I were discussing locale support included but not limited to message interpolation. I think you’re right about the fallback for messages.

— Santiago

On May 24, 2017, at 11:54 AM, Gunnar Morling via Groups.Io <gunnar.morling@...> wrote:

Bean Validation spec lead here, thanks a lot for considering this feature!

> Since there is no way how to get a list of supported locales

Why is it that you need to get the list of locales? The Locale mechanism has fallback implemented which is used by Bean Validation. So e.g. say you have ValidationMessages.properties, ValidationMessages_en.properties and ValidationMessages_de.properties. If you request with "en" or "en_US", it'd take the second. If you request with "de", it'd take the last one. If you request with any other Locale, it'd take the first one. This all happens automatically.

> hence the CLIENT programmer (like MVC API, JSF, JavaFX) just as HE has to find nice and translated phrases for ANY OTHER exception already

I think there are good reasons for doing I18N on the server and on the client, it's not that one is always better than the other. E.g. doing it on the backend (i.e. JAX-RS) allows different clients to benefit from translations (say a JavaFX client as well as a web client using the same REST API). JSF btw. is integrating with Bean Validation already in the suggested way: it takes its current Locale and passes it to BV. I personally think JAX-RS could do it exactly in the same way: set up a Bean Validation message interpolator which takes the Locale from requests and passes this to calls of interpolate().

--Gunnar

 

If we want to support I18N on the JAX-RS server, it only would be straightforward to not only translation BV messages, but we also have to provide similar services to ALL providers, too. For example, why should it be correct that BV is supported, but custom exception providers are not, also custom MBWs (like for PDF) are not? I mean, content is content, and a service should be available to ALL sources of content, not just to BV.

 

From: jaxrs-spec@javaee.groups.io [mailto:jaxrs-spec@javaee.groups.io] On Behalf Of Gunnar Morling via Groups.Io
Sent: Mittwoch, 24. Mai 2017 17:54
To: jaxrs-spec@javaee.groups.io
Subject: Re: [jaxrs] #544: Localization & BeanValidation

 

Bean Validation spec lead here, thanks a lot for considering this feature!

> Since there is no way how to get a list of supported locales

Why is it that you need to get the list of locales? The Locale mechanism has fallback implemented which is used by Bean Validation. So e.g. say you have ValidationMessages.properties, ValidationMessages_en.properties and ValidationMessages_de.properties. If you request with "en" or "en_US", it'd take the second. If you request with "de", it'd take the last one. If you request with any other Locale, it'd take the first one. This all happens automatically.

> hence the CLIENT programmer (like MVC API, JSF, JavaFX) just as HE has to find nice and translated phrases for ANY OTHER exception already

I think there are good reasons for doing I18N on the server and on the client, it's not that one is always better than the other. E.g. doing it on the backend (i.e. JAX-RS) allows different clients to benefit from translations (say a JavaFX client as well as a web client using the same REST API). JSF btw. is integrating with Bean Validation already in the suggested way: it takes its current Locale and passes it to BV. I personally think JAX-RS could do it exactly in the same way: set up a Bean Validation message interpolator which takes the Locale from requests and passes this to calls of interpolate().

--Gunnar

Pavel Bucek
 

We are still not exactly sure how / whether it should be put into place.

JAX-RS implementation has to have list of supported locales, because there is a defined algorithm, which chooses effective locale for the response. Note that Accept-Language is a list of languages, not a single one. Thus we'd need to somehow get a list of supported languages and invoke algorithm which computes effective language/Locale for the response entity.

If there would be BV API which could do that, it would be great (I mean - if there would be a way how to pass a list of possible locales and let BV runtime to do the rest).

Introducing new interface like SupportedLocaleProvider is viable option, but when I try to get into a "user role", I would expect something more from that - maybe adding Language header to the response. That is certainly possible, but again problematic, since there is no guarantee that the response entity will respect that (and JAX-RS would need to provide a way how to obtain computed Language).

Also, seems like one of the main motivations for doing this is to provide support for MVC - and if there is Provider priority, this could be handled on MVC side (including BV, if MVC chooses to use it)..

Regards,
Pavel


On 25/05/2017 08:56, Markus KARG wrote:

If we want to support I18N on the JAX-RS server, it only would be straightforward to not only translation BV messages, but we also have to provide similar services to ALL providers, too. For example, why should it be correct that BV is supported, but custom exception providers are not, also custom MBWs (like for PDF) are not? I mean, content is content, and a service should be available to ALL sources of content, not just to BV.

 

From: jaxrs-spec@javaee.groups.io [mailto:jaxrs-spec@javaee.groups.io] On Behalf Of Gunnar Morling via Groups.Io
Sent: Mittwoch, 24. Mai 2017 17:54
To: jaxrs-spec@javaee.groups.io
Subject: Re: [jaxrs] #544: Localization & BeanValidation

 

Bean Validation spec lead here, thanks a lot for considering this feature!

> Since there is no way how to get a list of supported locales

Why is it that you need to get the list of locales? The Locale mechanism has fallback implemented which is used by Bean Validation. So e.g. say you have ValidationMessages.properties, ValidationMessages_en.properties and ValidationMessages_de.properties. If you request with "en" or "en_US", it'd take the second. If you request with "de", it'd take the last one. If you request with any other Locale, it'd take the first one. This all happens automatically.

> hence the CLIENT programmer (like MVC API, JSF, JavaFX) just as HE has to find nice and translated phrases for ANY OTHER exception already

I think there are good reasons for doing I18N on the server and on the client, it's not that one is always better than the other. E.g. doing it on the backend (i.e. JAX-RS) allows different clients to benefit from translations (say a JavaFX client as well as a web client using the same REST API). JSF btw. is integrating with Bean Validation already in the suggested way: it takes its current Locale and passes it to BV. I personally think JAX-RS could do it exactly in the same way: set up a Bean Validation message interpolator which takes the Locale from requests and passes this to calls of interpolate().

--Gunnar


Sergey Beryozkin
 

Can those providers which need it, ex, BV exception mappers, depend on the existing injectable Configuration interface to ensure the locales or other info can be accessed in a portable way ?

Cheers, Sergey

Gunnar Morling
 

> Note that Accept-Language is a list of languages, not a single one

Ah, that's a good point, I wasn't aware of that. My feeling is that JAX-RS should select the right Locale (however that would look like), so it can apply it across all sorts of providers/services it interacts with and then pass that one to Bean Validation.

> one of the main motivations for doing this is to provide support for MVC

I'm not so sure about that, I think JAX-RS itself would benefit from it, too.

--Gunnar

Pavel Bucek
 

On 26/05/2017 10:14, Gunnar Morling via Groups.Io wrote:
> Note that Accept-Language is a list of languages, not a single one

Ah, that's a good point, I wasn't aware of that. My feeling is that JAX-RS should select the right Locale (however that would look like), so it can apply it across all sorts of providers/services it interacts with and then pass that one to Bean Validation.

selecting a right locale might be problematic. Imagine you have two resource method, one serving orders and the other one items. Items can be returned in different set of languages than orders.

Then, if we delegate this selection to JAX-RS, we need to support it per resource method? How would SupportedLanguageProvider do that?

Also, it could be that this information is stored in a database and is even item specific. How would be that provider written then? I'm not saying it is not possible, it would bring additional complexity to something, which can be already handled (in application specific way) without providing any real benefit.

The struggle here is with the SupportedLanguagesProvider - it feels like it should be used for something more than BV - I think it's fair to say that if localizaiton of BV error messages is the sole purpose of such provider, it shouldn't be introduced. And I can't think of any other sensible use right now.

Regards,
Pavel



> one of the main motivations for doing this is to provide support for MVC

I'm not so sure about that, I think JAX-RS itself would benefit from it, too.

--Gunnar

 

Hey Pavel,

The struggle here is with the SupportedLanguagesProvider - it feels like it should be used for something more than BV - I think it's fair to say that if localizaiton of BV error messages is the sole purpose of such provider, it shouldn't be introduced. And I can't think of any other sensible use right now.

I would like to take the opportunity to describe what MVC did to support internationalization which relates to the issue we are discussing here. As MVC builds on top of JAX-RS, this may (or may not) be interesting for you.

For MVC we identified a few locale-dependent aspects which we had to support:
  1. Data type conversion as part of the data binding mechanism needs to be locale aware. So something like @FormParam("price") BigDecimal price needs to be parsed according to the number formatting rules of the specific locale.
  2. Formatting data according to locale dependent rules when rending the view (date format / number format). This certainly isn't something relevant for JAX-RS.
  3. Generating binding and validation errors message in the specific language. This is basically what we are talking about here.
To support these scenarios we defined the term "request locale" as the locale which is used for any locale-dependent operation within the lifecycle of a request. The request locale is resolved for each request using the following SPI:

  public interface LocaleResolver {
    Locale resolveLocale(LocaleResolverContext context);
  }

The default implementation basically resolves the locale by parsing the Accept-Locale request header and resolving the locale with the highest priority. 

But developers can customize this by providing their own resolver. So if the developer wants to support only a specific subset of locales, he could simply create a custom resolver and match the supported locales against the Accept-Locale header as described in Pavel's previous mail.

You can see the full SPI here:


All the details are described in the MVC spec document (pages 37-38):


I'm not sure if anything described here could be useful for JAX-RS. Of cause we (the MVC EG) would be happy to see any of our APIs to be integrated into JAX-RS.

Christian


--

Gunnar Morling
 

Hi Christian,

The default implementation basically resolves the locale by parsing the
Accept-Locale request header and resolving the locale with the highest
priority.
This seems very useful, pretty much like what could be useful within
JAX-RS itself. That selected Locale could then be used with a
specifically set up message interpolator, just as JSF defines this
integration with Bean Validation.

Out of curiosity, how is that priority be defined?

--Gunnar



2017-05-28 16:00 GMT+02:00 Christian Kaltepoth <@chkal>:
Hey Pavel,

The struggle here is with the SupportedLanguagesProvider - it feels like
it should be used for something more than BV - I think it's fair to say that
if localizaiton of BV error messages is the sole purpose of such provider,
it shouldn't be introduced. And I can't think of any other sensible use
right now.

I would like to take the opportunity to describe what MVC did to support
internationalization which relates to the issue we are discussing here. As
MVC builds on top of JAX-RS, this may (or may not) be interesting for you.

For MVC we identified a few locale-dependent aspects which we had to
support:

Data type conversion as part of the data binding mechanism needs to be
locale aware. So something like @FormParam("price") BigDecimal price needs
to be parsed according to the number formatting rules of the specific
locale.
Formatting data according to locale dependent rules when rending the view
(date format / number format). This certainly isn't something relevant for
JAX-RS.
Generating binding and validation errors message in the specific language.
This is basically what we are talking about here.

To support these scenarios we defined the term "request locale" as the
locale which is used for any locale-dependent operation within the lifecycle
of a request. The request locale is resolved for each request using the
following SPI:

public interface LocaleResolver {
Locale resolveLocale(LocaleResolverContext context);
}

The default implementation basically resolves the locale by parsing the
Accept-Locale request header and resolving the locale with the highest
priority.

But developers can customize this by providing their own resolver. So if the
developer wants to support only a specific subset of locales, he could
simply create a custom resolver and match the supported locales against the
Accept-Locale header as described in Pavel's previous mail.

You can see the full SPI here:

https://github.com/mvc-spec/mvc-spec/tree/master/api/src/main/java/javax/mvc/locale

All the details are described in the MVC spec document (pages 37-38):

https://github.com/mvc-spec/mvc-spec/raw/master/spec/spec.pdf

I'm not sure if anything described here could be useful for JAX-RS. Of cause
we (the MVC EG) would be happy to see any of our APIs to be integrated into
JAX-RS.

Christian


--
Christian Kaltepoth
Blog: http://blog.kaltepoth.de/
Twitter: http://twitter.com/chkal
GitHub: https://github.com/chkal

 

Hi Gunnar,

sorry, the term "priority" was a bit misleading in this context. Actually it uses the "quality value" from the "Accept-Language" header. 


Christian

2017-05-29 14:26 GMT+02:00 Gunnar Morling via Groups.Io <gunnar.morling@...>:

Hi Christian,

> The default implementation basically resolves the locale by parsing the
> Accept-Locale request header and resolving the locale with the highest
> priority.

This seems very useful, pretty much like what could be useful within
JAX-RS itself. That selected Locale could then be used with a
specifically set up message interpolator, just as JSF defines this
integration with Bean Validation.

Out of curiosity, how is that priority be defined?

--Gunnar



2017-05-28 16:00 GMT+02:00 Christian Kaltepoth <christian@...>:
> Hey Pavel,
>
>> The struggle here is with the SupportedLanguagesProvider - it feels like
>> it should be used for something more than BV - I think it's fair to say that
>> if localizaiton of BV error messages is the sole purpose of such provider,
>> it shouldn't be introduced. And I can't think of any other sensible use
>> right now.
>
>
> I would like to take the opportunity to describe what MVC did to support
> internationalization which relates to the issue we are discussing here. As
> MVC builds on top of JAX-RS, this may (or may not) be interesting for you.
>
> For MVC we identified a few locale-dependent aspects which we had to
> support:
>
> Data type conversion as part of the data binding mechanism needs to be
> locale aware. So something like @FormParam("price") BigDecimal price needs
> to be parsed according to the number formatting rules of the specific
> locale.
> Formatting data according to locale dependent rules when rending the view
> (date format / number format). This certainly isn't something relevant for
> JAX-RS.
> Generating binding and validation errors message in the specific language.
> This is basically what we are talking about here.
>
> To support these scenarios we defined the term "request locale" as the
> locale which is used for any locale-dependent operation within the lifecycle
> of a request. The request locale is resolved for each request using the
> following SPI:
>
>   public interface LocaleResolver {
>     Locale resolveLocale(LocaleResolverContext context);
>   }
>
> The default implementation basically resolves the locale by parsing the
> Accept-Locale request header and resolving the locale with the highest
> priority.
>
> But developers can customize this by providing their own resolver. So if the
> developer wants to support only a specific subset of locales, he could
> simply create a custom resolver and match the supported locales against the
> Accept-Locale header as described in Pavel's previous mail.
>
> You can see the full SPI here:
>
> https://github.com/mvc-spec/mvc-spec/tree/master/api/src/main/java/javax/mvc/locale
>
> All the details are described in the MVC spec document (pages 37-38):
>
> https://github.com/mvc-spec/mvc-spec/raw/master/spec/spec.pdf
>
> I'm not sure if anything described here could be useful for JAX-RS. Of cause
> we (the MVC EG) would be happy to see any of our APIs to be integrated into
> JAX-RS.
>
> Christian
>
>
> --
> Christian Kaltepoth
> Blog: http://blog.kaltepoth.de/
> Twitter: http://twitter.com/chkal
> GitHub: https://github.com/chkal
>
>





Gunnar Morling
 

I see, thanks for clarifying the details, Christian!

To me it seems that'd be a very reasonable default behaviour for
JAX-RS; people still could plug in a custom LocaleResolver based on
their custom requirements and context, e.g. preferring a Locale for
which they provide a resource bundle with validation messages.

2017-05-29 15:36 GMT+02:00 Christian Kaltepoth <@chkal>:

Hi Gunnar,

sorry, the term "priority" was a bit misleading in this context. Actually it
uses the "quality value" from the "Accept-Language" header.

See:
https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language

Christian

2017-05-29 14:26 GMT+02:00 Gunnar Morling via Groups.Io
<gunnar.morling=googlemail.com@groups.io>:

Hi Christian,

The default implementation basically resolves the locale by parsing the
Accept-Locale request header and resolving the locale with the highest
priority.
This seems very useful, pretty much like what could be useful within
JAX-RS itself. That selected Locale could then be used with a
specifically set up message interpolator, just as JSF defines this
integration with Bean Validation.

Out of curiosity, how is that priority be defined?

--Gunnar



2017-05-28 16:00 GMT+02:00 Christian Kaltepoth <@chkal>:
Hey Pavel,

The struggle here is with the SupportedLanguagesProvider - it feels
like
it should be used for something more than BV - I think it's fair to say
that
if localizaiton of BV error messages is the sole purpose of such
provider,
it shouldn't be introduced. And I can't think of any other sensible use
right now.

I would like to take the opportunity to describe what MVC did to support
internationalization which relates to the issue we are discussing here.
As
MVC builds on top of JAX-RS, this may (or may not) be interesting for
you.

For MVC we identified a few locale-dependent aspects which we had to
support:

Data type conversion as part of the data binding mechanism needs to be
locale aware. So something like @FormParam("price") BigDecimal price
needs
to be parsed according to the number formatting rules of the specific
locale.
Formatting data according to locale dependent rules when rending the
view
(date format / number format). This certainly isn't something relevant
for
JAX-RS.
Generating binding and validation errors message in the specific
language.
This is basically what we are talking about here.

To support these scenarios we defined the term "request locale" as the
locale which is used for any locale-dependent operation within the
lifecycle
of a request. The request locale is resolved for each request using the
following SPI:

public interface LocaleResolver {
Locale resolveLocale(LocaleResolverContext context);
}

The default implementation basically resolves the locale by parsing the
Accept-Locale request header and resolving the locale with the highest
priority.

But developers can customize this by providing their own resolver. So if
the
developer wants to support only a specific subset of locales, he could
simply create a custom resolver and match the supported locales against
the
Accept-Locale header as described in Pavel's previous mail.

You can see the full SPI here:


https://github.com/mvc-spec/mvc-spec/tree/master/api/src/main/java/javax/mvc/locale

All the details are described in the MVC spec document (pages 37-38):

https://github.com/mvc-spec/mvc-spec/raw/master/spec/spec.pdf

I'm not sure if anything described here could be useful for JAX-RS. Of
cause
we (the MVC EG) would be happy to see any of our APIs to be integrated
into
JAX-RS.

Christian


--
Christian Kaltepoth
Blog: http://blog.kaltepoth.de/
Twitter: http://twitter.com/chkal
GitHub: https://github.com/chkal



--
Christian Kaltepoth
Blog: http://blog.kaltepoth.de/
Twitter: http://twitter.com/chkal
GitHub: https://github.com/chkal