Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to read messages and pass parameters to message.properties file in JSF 2.0

Tags:

jsf-2

Suppose i have a messages.properties file like

windowTitle=Accessing Form Elements with JavaScript
namePrompt=Name:
passwordPrompt=Password:
confirmPasswordPrompt=Confirm Password:

I have a entry for this in my faces-config.xml like this

<faces-config version="2.0"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd">

    <application>
        <resource-bundle>
            <base-name>pk.mazars.basitMahmood.messages</base-name>
            <var>msgs</var>
        </resource-bundle>
    </application>

</faces-config>

On my xhtml page i can access it like this

<h:panelGrid columns="2" columnClasses="evenColumns, oddColumns">
    #{msgs.namePrompt}
    <h:inputText/>
    #{msgs.passwordPrompt}
    <h:inputSecret id="password"/>
    #{msgs.confirmPasswordPrompt}
    <h:inputSecret id="passwordConfirm"/>
</h:panelGrid>

But how can i read this file from Java. Like, suppose i have to print a message like this, or prompt the user like Name must be entered

System.out.println(msgs.namePrompt + "must be entered")

How can i read the msgs.namePrompt value from my java code.

Also suppose i have a entry in my message file like this

sure=Are you sure, you want to delete the <Field>?
remove=Are you sure you want to remove the<Field> and <Field>?
close=Are you sure you want to mark the <Field> as Closed?
created=<Field> is successfully created
updated=<Field> is successfully updated

Is there any technique that i can pass parameter to my messages.properties file. Like i want to do something like this in my java code

System.out.println(msgs.sure("Name"));   //<Field> is replace with Name
System.out.println(msgs.remove("Age", "Gender"));  //  First Field replace by Age, and second is replace by Gender

Thank you.

like image 875
Basit Avatar asked Feb 22 '12 07:02

Basit


2 Answers

Parameterized resource strings in facelets:

As described in this tutorial, you can use h:outputFormat and f:param to replace your paramters in a resource bundle string:

<h:outputFormat value="#{msg['message.param1']}">
   <f:param value="param0" />
</h:outputFormat>
<h:outputFormat value="#{msg['message.param2']}">
   <f:param value="param0" />
   <f:param value="param1" />
</h:outputFormat>

//properties file
message.param1 = This is "message.param1" - {0}
message.param2 = This is "message.param2" - {0} and {1}

In Java you can access a property file like this:

import java.util.ResourceBundle;
...
ResourceBundle rb = ResourceBundle.getBundle("pk.mazars.basitMahmood.messages");

Parameterized properties can be processed with the javax.text.MessageFormat class:

MessageFormat.format(rb.getString(key), params);

If you are working with different locales and parameterized and non-parameterized properties, you can use a short helper method like this:

public static String getMessageResourceString(String bundleName, String key, Object params[], Locale locale) {

        String text;
        ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale);

        try {
            text = bundle.getString(key);
        } catch (MissingResourceException e) {
            text = "?? key " + key + " not found ??";
        }

        if (params != null) {
            MessageFormat mf = new MessageFormat(text, locale);
            text = mf.format(params, new StringBuffer(), null).toString();
        }

        return text;
    }
like image 164
Matt Handy Avatar answered Oct 21 '22 00:10

Matt Handy


Thanks Matt Handy:). Here i am posting my answer. I also used a method which is same as yours but with description(comment) added. Here is my code that i am using. This is complete example that anyone can use :)

messages.properties file

windowTitle=Accessing Form Elements with JavaScript
namePrompt=Name:
passwordPrompt=Password:
confirmPasswordPrompt=Confirm Password:
message.param1 = This is "message.param1" - {0}
message.param2 = This is "message.param2" - {0} and {1}

faces-config.xml file

<application>
    <resource-bundle>
        <base-name>pk.mazars.basitMahmood.messages</base-name>
        <var>msgs</var>
    </resource-bundle>
</application>

index.xhtml file

<h:body>

    <h:form>

        <h:panelGrid columns="2" columnClasses="evenColumns, oddColumns">
            #{msgs.namePrompt}
            <h:inputText id="name" value="#{readMessages.name}" />
            #{msgs.passwordPrompt}
            <h:inputSecret id="password" value="#{readMessages.password}"/>
            #{msgs.confirmPasswordPrompt}
            <h:inputSecret id="passwordConfirm"/>

        </h:panelGrid>

        <!--A normal way to access the message.

                <h:outputText value="{msg.message}" />

                //properties file
                message = This is "message"

            For a key that has a dot “.” as name, you can’t use the normal way {msg.message.test1}, it
            will not work. Instead, you should use bracket like {msg['message.test1']}.

                <h:outputText value="{msg['message.test1']}" />

                //properties file
                message.test1 = This is "message.test1"

            To display HTML tag in the message, just add the “escape” attribute and set it to false.

                <h:outputText value="{msg['message.test2']}" />
                <h:outputText value="{msg['message.test2']}" escape="false" />
                <h:outputText value="{msg['message.test3']}" />
                <h:outputText value="{msg['message.test3']}" escape="false" />

                //properties file
                message.test2 = This is "<h2>message.test3</h2>"
                message.test3 = This is "&lt;h2&gt;message.test4&lt;/h2&gt;"

        -->
        <h:outputFormat value="#{msgs['message.param1']}">
            <f:param value="param0" />
        </h:outputFormat>

        <h:outputFormat value="#{msgs['message.param2']}">
            <f:param value="param0" />
            <f:param value="param1" />
        </h:outputFormat>

        <h:commandButton  type="button" value="Submit Form" 
                          onclick="checkPassword(this.form)"/>

    </h:form>

</h:body>

java file

@Named(value="readMessages")
@RequestScoped
public class ReadMessages {

    private String name;
    private String password;

    /** Creates a new instance of ReadMessages */
    public ReadMessages() {

        String[] message1 = {"Basit", "Masood"};

        //FacesMessage message = getMessage(
               // "pk.mazars.basitMahmood.messages", "message.param2", new Object[]{new String("arg1")});

        String message = getMessage(
                "pk.mazars.basitMahmood.messages", "message.param2", message1);

        System.out.println();

    } // end of constructor

    public String getName() {
        return name;
    }

    public String getPassword() {
        return password;
    }

    /**
     * For proper localization, you will want to retrieve error messages from a message bundle.
     * Doing that involves some busywork with locales and class Loader.
     *
     * @param bundleName
     * @param resourceId
     * @param params
     * @return
     */
    public static String getMessage(String bundleName, String resourceId, Object[] params) {

        /**
         * Get the current locale.
         *     FacesContext context = FacesContext.getCurrentInstance();
         *     UIViewRoot viewRoot = context.getViewRoot();
         *     Locale locale = viewRoot.getLocale();
         *
         */
        FacesContext context = FacesContext.getCurrentInstance();

        /**
         * Recall that an application can supply a bundle name in a configuration file,
         * such as
         *
         *     <faces-config>
         *         <application>
         *             <message-bundle>pk.mazars.basitMahmood.messages</message-bundle>
         *         </application>
         *         ...
         *     </faces-config>
         *
         * The following code snippet retrieves that bundle name:
         *
         *     Application app = context.getApplication();
         *     String appBundleName = app.getResourceBundle();
         */
        Application app = context.getApplication();
        String appBundle = app.getMessageBundle();

        //get Locale
        Locale locale = getLocale(context);

        /**
         * Get the current class loader.  You need it to locate the resource bundle
         *
         *     ClassLoader loader = Thread.currentThread().getContextClassLoader();
         *
         */
        ClassLoader loader = getClassLoader();

        /**
         * Get the resource bundle with the given name, locale and class loader
         *
         *     ResourceBundle bundle = ResourceBundle.getBundle(bundleName, locale, loader);
         *
         */
        String summary = getString(appBundle, bundleName, resourceId, locale, loader, params);

        if (summary != null) {

            //summary = "????" + resourceId + "????";
            return summary ;

        }

        String detail = getString(appBundle, bundleName, resourceId + "detail", locale, loader, params);
        return detail;
        //return new FacesMessage(summary, detail);

    } //end of getMessage()

    public static String getString(String bundle, String resourceId, Object[] params) {

        FacesContext context = FacesContext.getCurrentInstance();
        Application app = context.getApplication();
        String appBundle = app.getMessageBundle();
        Locale locale = getLocale(context);
        ClassLoader loader = getClassLoader();
        return getString(appBundle, bundle, resourceId, locale, loader, params);

    } //end of getString()

    public static Locale getLocale(FacesContext context) {

        Locale locale = null;
        UIViewRoot viewRoot = context.getViewRoot();

        if (viewRoot != null) {

            locale = viewRoot.getLocale();

        } //end of if (viewRoot != null)

        if (locale == null) {

            locale = Locale.getDefault();

        } //end of if (locale == null)

        return locale;

    } //end of getLocale()

    public static ClassLoader getClassLoader() {

        /**
         * The Java ClassLoader is a crucial, but often overlooked, component of the Java run-time system.
         * It is the class responsible for finding and loading class files at run time.
         *
         * Among commercially popular programming languages, the Java language distinguishes itself by
         * running on a Java virtual machine (JVM). This means that compiled programs are expressed in
         * a special, platform-independent format, rather than in the format of the machine they are
         * running on. This format differs from traditional executable program formats in a number of
         * important ways.
         *
         * In particular, a Java program, unlike one written in C or C++, isn't a single executable file,
         * but instead is composed of many individual class files, each of which corresponds to a single
         * Java class.
         *
         * Additionally, these class files are not loaded into memory all at once, but rather are loaded
         * on demand, as needed by the program. The ClassLoader is the part of the JVM that loads
         * classes into memory.
         */
        ClassLoader loader = Thread.currentThread().getContextClassLoader();

        if (loader == null) {

            /**
             * Whether you override findClass or loadClass, getSystemClassLoader gives you direct
             * access to the system ClassLoader in the form of an actual ClassLoader object (instead
             * of accessing it implicitly through the findSystemClass call).
             */
            loader = ClassLoader.getSystemClassLoader();

        } //end of if (loader == null)

        return loader;

    } //end of getClassLoader()

    public static String getString(String bundle1, String bundle2, String resourceId,
        Locale locale, ClassLoader loader, Object[] params) {

        String resource = null;
        ResourceBundle bundle;

        if (bundle1 != null) {

            bundle = ResourceBundle.getBundle(bundle1, locale, loader);

            if (bundle != null) {

                try {

                    /**
                     * Get the resource string with the given ID from the bundle.
                     *
                     *     String resource = bundle.getString(resourceId);
                     *
                     */
                    resource = bundle.getString(resourceId);

                } catch (MissingResourceException e) {
                }

            } //end of if (bundle != null)

        } //end of if (bundle1 != null)

        if (resource == null) {

            bundle = ResourceBundle.getBundle(bundle2, locale, loader);

            if (bundle != null) {

                try {

                    /**
                     * Get the resource string with the given ID from the bundle.
                     *
                     *     String resource = bundle.getString(resourceId);
                     *
                     */
                    resource = bundle.getString(resourceId);

                } catch (MissingResourceException e) {
                }

            } //end of if (bundle != null)

        } //end of if (resource == null)

        if (resource == null) {

            return null;  // no match

        }

        if (params == null) {

            return resource;

        }

        /**
         * Finally, you may want some messages to provide detailed information about the
         * nature of the error. For example, you want to tell the user which character
         * in the credit card number was objectionable. Message strings can contain
         * place-holders {0}, {1} and so on - for exanple
         *
         *     The card number contains the invalid character {0}.
         *
         * The java.text.MessageFormat class can substitute values for the placeholders:
         *
         *     Object[] params = ...;
         *     MessageFormat formatter = new MessageFormat(resource, locale);
         *     String message = formatter.format(params);
         *
         * Here, the params array contains the values that should be substituted.
         */
        MessageFormat formatter = new MessageFormat(resource, locale);
        return formatter.format(params);

    } //end of getString()

} //end of class ReadMessages
like image 32
Basit Avatar answered Oct 20 '22 23:10

Basit