Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validation/conversion errors of <f:viewParam> do not localize to <f:view locale>, but to default locale

I have an <f:viewParam> tag on JSF pages that sets GET parameters to the corresponding managed bean after conversion and validation.

If either conversion or validation errors occur, then an appropriate error message is fetched from a resource bundle and displayed on <p:messages> (may also be <p:growl> or <h:messages>).

The application is multilingual. Therefore when a different language is selected, a message should be displayed in that language but it always displays the message according to the default locale en (for English).

Test.xhtml:

<!DOCTYPE html>
<html lang="#{localeBean.language}"
    xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core">

    <f:view locale="#{localeBean.locale}">
        <f:metadata>
            <f:viewParam name="id" converter="#{myConverter}" />
        </f:metadata>
        <h:head>
            <title>Test</title>
        </h:head>
        <h:body>
            <h:messages />
        </h:body>
    </f:view>
</html>

The converter:

@FacesConverter("myConverter")
public final class MyConverter implements Converter
{
    @Override
    public Object getAsObject(FacesContext context, UIComponent component, String value)
    {
        ResourceBundle bundle = context.getApplication()
            .evaluateExpressionGet(context, "#{messages}", ResourceBundle.class);
        String message = bundle.getString("id.conversion.error");
        throw new ConverterException(
            new FacesMessage(FacesMessage.SEVERITY_ERROR, message, null));
    }

    @Override
    public String getAsString(FacesContext context, UIComponent component, Object value)
    {
        throw new UnsupportedOperationException(); // Not relevant in this problem.
    }
}

Except for the messages from <f:viewParam>, there is no problem. All other kind of messages are displayed in the language selected by the user.

Is there anything special with <f:viewParam>?

like image 777
Tiny Avatar asked Aug 28 '13 18:08

Tiny


1 Answers

I can reproduce your problem. Both Mojarra 2.1.25 and MyFaces 2.1.12 expose the same problem. I'm therefore not sure if this is a bug in the JSF impl or an oversight in the JSF spec. So far, it turns out that the viewroot locale is not been set for a GET request before the render response phase is entered. The converter runs during validations phase, far before render response, that explains why it got the default locale instead. I have to investigate it later on and if necessary report an issue to Mojarra.

In the meanwhile, your best bet to solve this problem is to obtain the bundle as follows instead of EL-evaluating the <resource-bundle><var>:

String basename = "com.example.i18n.message"; // Exactly the same as <resource-bundle><base-name>
Locale locale = context.getApplication().evaluateExpressionGet(context, "#{localeBean.locale}", Locale.class);
ResourceBundle bundle = ResourceBundle.getBundle(basename, locale);
// ...

Update: I've reported issue 3021 as per this problem. I still can't wrap my head around what the spec is saying at this point, but I find the implementation's behavior unintuitive.


Update 2: the Mojarra and MyFaces guys agreed on this. For Mojarra, it's been fixed as per 2.2.5 (no 2.1.x backport yet?) and for MyFaces it's been fixed as per 2.0.19, 2.1.13 and 2.2.0.

like image 114
BalusC Avatar answered Nov 02 '22 03:11

BalusC