0

What I'm trying to achieve is UTF-8 encoded JSF validation and converter messages (message-bundle). Also, I would like custom resource bundle for labels, etc (resource-bundle).

I managed to create and use custom resource bundle successfully, but I have problem with defining message-bundle.

I have the following structure under src/ directory:

- com.example.i18n.resources
    - FacesMsgs.properties
    - FacesMsgs_de.properties
    - UTF8FacesMsgs.java
    - Msgs.properties
    - Msgs_de.properties
    - UTF8Msgs.java

Faces-config.xml snippet:

<application>
    <message-bundle>com.example.i18n.resources.UTF8FacesMsgs</message-bundle>
    <resource-bundle>
        <base-name>com.example.i18n.resources.UTF8Msgs</base-name>
        <var>msg</var>
    </resource-bundle>
    <locale-config>
        <default-locale>de</default-locale>
    </locale-config>
</application>

In my implementation I have followed the instructions given here: Internationalization in JSF with UTF-8 encoded properties files

These are resulting classes:

public class ResourceBundleWrapper extends ResourceBundle {

    public ResourceBundleWrapper(ResourceBundle parent) {
        setParent(parent);
    }

    @Override
    protected Object handleGetObject(String key) {
        return parent.getObject(key);
    }

    @Override
    public Enumeration<String> getKeys() {
        return parent.getKeys();
    }
}

EncodingControl.java

public class EncodingControl extends Control {

    private String encoding;

    private String extension;

    public EncodingControl(String encoding, String extension) {
        this.encoding = encoding;
        this.extension = extension;
    }

    @Override
    public ResourceBundle newBundle(String baseName, Locale locale, String format, ClassLoader loader, boolean reload)
            throws IllegalAccessException, InstantiationException, IOException {

        String bundleName = toBundleName(baseName, locale);
        String resourceName = toResourceName(bundleName, extension);
        ResourceBundle bundle = null;
        InputStream stream = null;
        if (reload) {
            URL url = loader.getResource(resourceName);
            if (url != null) {
                URLConnection connection = url.openConnection();
                if (connection != null) {
                    connection.setUseCaches(false);
                    stream = connection.getInputStream();
                }
            }
        } else {
            stream = loader.getResourceAsStream(resourceName);
        }
        if (stream != null) {
            try {
                bundle = new PropertyResourceBundle(new InputStreamReader(stream, encoding));
            } finally {
                stream.close();
            }
        }
        return bundle;
    }
}

UTF8FacesMsgs.java

public class UTF8FacesMsgs extends ResourceBundleWrapper {

    public UTF8FacesMsgs() {
           super(ResourceBundle.getBundle("com.example.i18n.resources.FacesMsgs", 
                        FacesContext.getCurrentInstance().getViewRoot().getLocale(), 
                            new EncodingControl("UTF-8", "properties"));
    }
}

UTF8Msgs.java

public class UTF8Msgs extends ResourceBundleWrapper {

    public UTF8Msgs() {
        super(ResourceBundle.getBundle("com.example.i18n.resources.Msgs", 
                        FacesContext.getCurrentInstance().getViewRoot().getLocale(), 
                            new EncodingControl("UTF-8", "properties"));
    }
}

Resulting behaviour:

resource-bundle configuration seems to be working without issue: default UTF8Msgs.java is used and all labels on the page are rendered successfully. On the other hand, behaviour with message-bundle is quite different although everything is configured likewise: when validation fails (submiting the button triggers validation) I get MissingResourceException - the default UTF8FacesMsgs.java is not used and UTF8FacesMsgs_de.java is expected.

Behaviour with changes introduced:

When I configure faces-config.xml like this (directly using properties file, not java class):

<application>
    <message-bundle>com.example.i18n.resources.FacesMsgs</message-bundle>
    <resource-bundle>
        <base-name>com.example.i18n.resources.UTF8Msgs</base-name>
        <var>msg</var>
    </resource-bundle>
    <locale-config>
        <default-locale>de</default-locale>
    </locale-config>
</application>

and delete FacesMsgs_de.properties everything runs without issue. So - default properties file is used and default java file is not.

Does anybody know what is the problem with message-bundle configuration?

Kukeltje
  • 11,924
  • 4
  • 19
  • 44
user3096746
  • 61
  • 1
  • 10
  • So it works if you don't use any uft8 related characters? – Kukeltje Mar 06 '17 at 11:33
  • I realized that problem is in constructor UTF8FacesMsg because FacesContext.getCurrentInstance().getViewRoot() returns null so NPE is thrown and class fails to initialize which leads to MissingResourceException. I wasn't aware of all the phases faces messages get initialized. I'll have to find some workaround. – user3096746 Mar 15 '17 at 08:51

0 Answers0