Joe Almore
Joe Almore

Reputation: 4311

Add Resource Bundles Programmatically

I have a faces-config.xml file with some resource bundles declared, like this:

<faces-config 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"
              version="2.0">
    <application>
        <locale-config>
            <default-locale>en</default-locale>
            <supported-locale>de</supported-locale>
            <supported-locale>es</supported-locale>
            <supported-locale>pt</supported-locale>
            <supported-locale>zh</supported-locale>
        </locale-config>
        <resource-bundle>
            <base-name>messages.Messages</base-name>
            <var>bundle</var>
        </resource-bundle>
        <resource-bundle>
            <base-name>countries.Countries</base-name>
            <var>countryBundle</var>
        </resource-bundle>
    </application>
</faces-config>

These resource bundles are registered and can be used in any .xhtml file, but is there any way to register these resource bundles programmatically? I mean by the use of dynamic code instead of a xml declaration.

Upvotes: 2

Views: 2203

Answers (2)

mabi
mabi

Reputation: 5307

Here's a simplified version of what I'm doing using CDI:

@ApplicationScoped
public class BundleProducer {
    @Produce @RequestScoped @Named
    public ResourceBundle getMsgBundle() {
        Locale userLocale = Faces.getLocale();
        return ResourceBundle.getBundle("messages", userLocale);
    }
}

Note the use of omnifaces' getLocale() to avoid a ton of boilerplace code (for a less sane version, you can substitute FacesContext.getCurrentInstance().getViewRoot().getLocale() like in the tutorial you linked to).

This will cause the CDI framework to call getMsgBundle once each request if it needs to access to msgBundle thanks to the @Named annotation. In this simple case, I'm relying on the ResourceBundle internal caching and lookup mechanisms to produce my bundle efficiently. You can execute any logic you like here (eg, load stuff from the enclosing BundleProducer) as long as you return a ResourceBundle from the method (you're not allowed to return null).

Repeat as you like with more methods producing different bundles.

Not sure if I got what you were after, so just comment if you need more clarification.


For easier handling of FacesMessage stuff, I'd recommend having a look at omnifaces' Messages utility class. I use something like this to be able to optionally give bundle keys as message strings:

@Singleton
@Startup
public class MessageResolverInit {
    @PostConstruct
    public void initMessageResolver() {
        Messages.setResolver(new Messages.Resolver() {
            @Override
            public String getMessage(String message, Object... params) {
                Locale userLocale = Faces.getLocale();
                ResourceBundle b = ResourceBundle.getBundle("msgs", userLocale);
                if (b.containsKey(message)) {
                    return MessageFormat.format(b.getString(message), params);
                }
                return message;
            }
        });
    }

Note that I use b as a variable name only for demo purposes. Usage goes like this:

Messages.addGlobalError("my_msg_key", param1);
Messages.addGlobalInfo("I'm a standalone message");

Upvotes: 2

Joe Almore
Joe Almore

Reputation: 4311

Here is the answer from Oracle documentation: Using FacesMessage to Create a Message

Upvotes: 0

Related Questions