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

Tiny
  • 27,221
  • 105
  • 339
  • 599

1 Answers1

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • I can't see this method `evaluateExpressionGet(String expression)`. I can see only `public T evaluateExpressionGet(FacesContext context, String expression, Class extends T> expectedType) throws ELException` instead. Is it there? – Tiny Aug 28 '13 at 20:02
  • 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. – BalusC Aug 28 '13 at 20:04
  • 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. – lu4242 Sep 16 '13 at 20:56
  • @lu4242: thank you for looking. Is there already a MyFaces ticket for this issue? – BalusC Sep 18 '13 at 11:54
  • 1
    @BalusC: I have created this issue [MYFACES-3781 f:view tag must be processed when view metadata is created](https://issues.apache.org/jira/browse/MYFACES-3781). – lu4242 Sep 23 '13 at 10:48
  • @lu4242: thank you for the issue, but how exactly has it relevance for JSF 2.2? Is it stated differently in the spec? – BalusC Sep 23 '13 at 10:57
  • @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.3 – lu4242 Sep 23 '13 at 15:19