Analog to @Hardy's answer you can also store the Local
in the resource SessionContext
data map for this purpose and retrieve it in your MessageInterpolator
implementation.
In your remote bean methods you can pass the client locale as an argument and set it on method entry. A possible setup could look like this:
Locale retrieval interface
interface ILocale
{
public Locale getLocale();
}
LocaleMessageInterpolator
Extend your default MessageInterpolator. Had to use interface to obtain locale to make it usable outside of EJB application.
public class LocaleMessageInterpolator extends ResourceBundleMessageInterpolator
{
private final ILocale iLocale;
public LocaleMessageInterpolator(final ILocale iLocale)
{
this.iLocale = iLocale;
}
@Override
public String interpolate(final String messageTemplate, final Context context)
{
final Locale locale = this.iLocale == null ? null : this.iLocale.getLocale();
if (locale == null)
return super.interpolate(messageTemplate, context);
else
return this.interpolate(messageTemplate, context, locale);
}
}
Application scoped bean
Register the new MessageInterpolator
in your validator factory. If all other Beans
inject AppBean
the constant could be private and a setClientLocale()
method could be provided.
@Startup
@Singleton
public class AppBean
{
public static final String CONTEXT_CLIENT_LOCALE_KEY = "CLIENT_LOCALE_KEY";
@Resource
private SessionContext ctx;
@PostConstruct
public void init()
{
// retrieve client locale from context using anyonymous implementation
final ILocale ilocale = () -> {
if (AppBean.this.ctx.getContextData().containsKey(AppBean.CONTEXT_CLIENT_LOCALE_KEY))
return (Locale) AppBean.this.ctx.getContextData()
.get(AppBean.CONTEXT_CLIENT_LOCALE_KEY);
return null;
};
// create client locale aware message interpolator
final LocaleMessageInterpolator localeMessageInterpolator= new LocaleMessageInterpolator(ilocale);
// configurate validator factory
ValidatorFactory validatorFactory = Validation.byDefaultProvider().configure().messageInterpolator(localeMessageInterpolator).buildValidatorFactory();
// register validator factory
configuration.getProperties().put("javax.persistence.validation.factory", validatorFactory);
}
Remote Bean
Save current client locale in SessionContext
.
@Stateless(mappedName = "MyBean")
@Remote(MyBeanRemote.class)
public class MyBean
{
@Resource
private SessionContext ctx;
@Override
public void create(Locale locale, Foo foo)
{
this.ctx.getContextData().put(AppBean.CONTEXT_CLIENT_LOCALE_KEY, locale);
// persist new Foo
// thrown validation exceptions are localized
}
}