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

1

7

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>?

Chibouk answered 28/8, 2013 at 18:34 Comment(0)
I
6

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.

Ileanaileane answered 28/8, 2013 at 19:29 Comment(7)
I can't see this method evaluateExpressionGet(String expression). I can see only public <T> T evaluateExpressionGet(FacesContext context, String expression, Class<? extends T> expectedType) throws ELException instead. Is it there?Chibouk
Sorry, I posted an oversimplified example (actually, I was using a static import from org.omnifaces.util.Faces) and incorrectly assumed that you'd understand the hint as to method's job. I updated the answer.Ileanaileane
It seems when the view metadata is processed, the outer f:view tag is not taken into account, but theorically it should not be like that, because f:view is something special. Looks like a bug to me.Himself
@lu4242: thank you for looking. Is there already a MyFaces ticket for this issue?Ileanaileane
@BalusC: I have created this issue MYFACES-3781 f:view tag must be processed when view metadata is created.Himself
@lu4242: thank you for the issue, but how exactly has it relevance for JSF 2.2? Is it stated differently in the spec?Ileanaileane
@BalusC: the new f:view "contracts" has the same considerations than "locale" at the time it is defined. This means basically "contracts" has the same weakness and the fix needs to be done in 2.2.x too. "locale" spec has not changed, but it is clear we are pushing this feature to its limits. In my opinion, if the spec does not explicitly forbids it, we should fix it anyway in MyFaces. Maybe we need a clarification in JSF 2.3Himself

© 2022 - 2024 — McMap. All rights reserved.