3

I am trying to change my JSF application locale in one page and that has to change all my pages locale. I have followed this link, and it works well Localization in JSF, how to remember selected locale per session instead of per request/view

If I run the application I can change the locale in my index.xhtml and that locale is set per session, so if then I go to page index_1.xhtml I will see the locale changed.

My problem is that when I run the application and I write the URL: http://localhost:8080/Myapp-war/faces/index_.xhtml to go to the index_1.xhtml page and I change the locale that locale is not changed in index.xhtml.

This is my code:

Managed Bean

package controllers;

import java.io.Serializable;
import java.util.Locale;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;

    @ManagedBean
    @SessionScoped
    public class LanguageSwitcher implements Serializable{

        private Locale locale; 


        @PostConstruct
        public void init() 
        {
            locale = FacesContext.getCurrentInstance().getViewRoot().getLocale();
        }


       public Locale getLocale() {
            return locale;
        }

        public String getLanguage() {
            return locale.getLanguage();
        }

        //Change locale
        public void changeLanguage(String language) {
            locale = new Locale(language);
            FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
        }   

    }

File index.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html   lang="#{languageSwitcher.language}"
        xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">


    <h:head>
    </h:head>

    <h:body>     
        <h3>Language switcher:</h3>
        <h:form id="language_form">
            <h:commandLink action="#{languageSwitcher.changeLanguage('es')}" value="Español" rendered="#{languageSwitcher.language != 'es'}"/> |
            <h:commandLink action="#{languageSwitcher.changeLanguage('en')}" value="English" rendered="#{languageSwitcher.language != 'en'}"/>
        </h:form>

       <h:outputText value="#{msg['greeting']}" />

    </h:body>
</html>

File index_1.xhtml:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
    "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html   lang="#{languageSwitcher.language}"
        xmlns="http://www.w3.org/1999/xhtml"
    xmlns:h="http://java.sun.com/jsf/html"
    xmlns:f="http://java.sun.com/jsf/core"
    xmlns:ui="http://java.sun.com/jsf/facelets"
    xmlns:p="http://primefaces.org/ui">

    <f:view locale="#{languageSwitcher.locale}">

    <h:head>
    </h:head>

    <h:body>     
        <h3>Language switcher:</h3>
        <h:form id="language_form">
            <h:commandLink action="#{languageSwitcher.changeLanguage('es')}" value="Español" rendered="#{languageSwitcher.language != 'es'}"/> |
            <h:commandLink action="#{languageSwitcher.changeLanguage('en')}" value="English" rendered="#{languageSwitcher.language != 'en'}"/>
        </h:form>

       <h:outputText value="#{msg['greeting']}" />

    </h:body>
  </f:view>
</html>

If I write <f:view locale="#{languageSwitcher.locale}">in my index.xhtml, when I run the app I get an error.

How could I solve it?

UPDATE:

The error I get when running the app is:

java.lang.NullPointerException at controllers.LanguageSwitcher.init(LanguageSwitcher.java:56)

Community
  • 1
  • 1
jose
  • 303
  • 4
  • 17
  • 1
    You must use ``. Which error exactly did you get when trying that? Errors basically represent the whole answer to the problem. You should not ignore them when you're unable to interpret them, but you should instead share them with experts like us, so that we can translate the error in layman's terms for you (and hence make the cause and solution much more obvious). It may possibly be related with the disappearing `` bug you faced in [your previous question](http://stackoverflow.com/questions/30646177/setting-dir-rtl-in-html-tag-doesnt-seem-to-work-works-in-hbody). – BalusC Jun 04 '15 at 21:01
  • I have updated my question telling what the error is. – jose Jun 04 '15 at 21:10
  • 1
    so... you get an error in line 56 of a class that has less than 30 lines? And even though you get the error message you do not tell us, what's in the line? Oh, well... I will shoot in the dark: I think you try to access the locale (perhaps log the langiuage) in your constructor, before it is initialized by the @PostConstruct method? – fdreger Jun 04 '15 at 21:17
  • JSF Implementation: Mojarra 2.2.7 – jose Jun 04 '15 at 21:22
  • At that line there is this code: locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); It is inside the PostConstruct, but I think that that doesn't make sense – jose Jun 04 '15 at 21:28
  • I also get this error: InjectionProviderException: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting invoke lifecycle method public void controllers.LanguageSwitcher.init() – jose Jun 04 '15 at 21:41
  • I reproduced it, the `getViewRoot()` returned `null`. Things have changed in JSF 2.2. That answer was written at time of JSF 2.0/2.1 and works just fine with those JSF versions. I will investigate further. – BalusC Jun 04 '15 at 21:48
  • Thank you so much for your effort. BTW if I catch the locale = FacesContext.getCurrentInstance().getViewRoot().getLocale(); exception, locale.getLanguage(); also gives me a NPE – jose Jun 04 '15 at 21:53
  • No, no, NPEs should never be explicitly caught. Like all other RuntimeExceptions, they indicate developer's mistakes. Those should never be caught, but be avoided by conditionally testing in e.g. `if` statements, or by seeking for the right approach. In any case, I posted an answer. – BalusC Jun 04 '15 at 22:20
  • OK, thank you for the aclaration – jose Jun 04 '15 at 22:36

1 Answers1

8

I reproduced your problem. This is the consequence of issue 3021 which was applied since Mojarra 2.2.5. The locale is now determined during view build time. Previously, at time of writing the answer you found, the locale was determined during view render time which allowed the code to find view's default locale this way. However, during view build time this is not possible as the view doesn't exist yet. You see, the getViewRoot() returned null.

You need to obtain the request locale from the external context instead.

@PostConstruct
public void init() {
    locale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
}

The answer you found has also been altered.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
  • Now the problem is solved because it does not return NPE, but I have a new problem. My browser settings say that I prefere receiving pages In Spanish rather than in English, but when I run the application I get the pages in English (that's my default-locale in the configuration xml file). So could you tell me how to get the pages in Spanish, being the server's default-locale the English? – jose Jun 04 '15 at 22:33
  • Oh, I will answer my question. I should have read more before asking it. Sorry. The answer is locale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale(); – jose Jun 04 '15 at 22:37
  • That's after all indeed better. – BalusC Jun 05 '15 at 06:17