How can I access messages bundle from java code to get message according to current locale?
I tried using @ManagedProperty
like below:
@Named
@SessionScoped
public class UserBean implements Serializable {
@ManagedProperty("#{msg}")
private ResourceBundle bundle;
// ...
public void setBundle(ResourceBundle bundle) {
this.bundle = bundle;
}
}
However, it remains null
. It seems that it doesn't work inside a @Named
.
This is how I registered the resource bundle in faces-context.xml
:
<application>
<message-bundle>validator.messages</message-bundle>
<locale-config>
<supported-locale>en_US</supported-locale>
<supported-locale>ua_UA</supported-locale>
</locale-config>
<resource-bundle>
<base-name>lang.messages</base-name>
<var>msg</var>
</resource-bundle>
</application>
updated by author:
I get error
16:29:10,968 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/WEBSearchPrime_JB_lang].[Faces Servlet]] (http-localhost-127.0.0.1-8080-1) Servlet.service() for servlet Faces Servlet threw exception: org.jboss.weld.exceptions.IllegalProductException: WELD-000054 Producers cannot produce non-serializable instances for injection into non-transient fields of passivating beans\\n\\nProducer\: Producer Method [PropertyResourceBundle] with qualifiers [@Any @Default] declared as [[method] @Produces public util.BundleProducer.getBundle()]\\nInjection Point\: [field] @Inject private model.UserBean.bundle
note, that I also put Serializable interface
You can't use @javax.faces.bean.ManagedProperty
in a CDI managed bean as annotated with @Named
. You can only use it in a JSF managed bean as annotated with @ManagedBean
.
You need use @javax.faces.annotation.ManagedProperty
instead, along with an @Inject
. This was introduced in JSF 2.3.
@Inject @javax.faces.annotation.ManagedProperty("#{msg}")
private ResourceBundle bundle;
Noted should be that this gets injected as a @Dependent
. So be aware that when you inject this into a @SessionScoped
bean, then it would basically become @SessionScoped
too and thus stick to the originally injected value forever. So any potential locale changes later on in the session won't be reflected there. If this is a blocker, then you should really inject it into a @RequestScoped
or @ViewScoped
only, or make use of a @Producer
as shown below.
CDI doesn't have native annotations to inject the evaluation result of an EL expression. The CDI approach is using a "CDI producer" with @Produces
wherein you return the concrete type, which is PropertyResourceBundle
in case of .properties
file based resource bundles.
So, if you cannot upgrade to JSF 2.3, then just drop this class somewhere in your WAR:
@RequestScoped
public class BundleProducer {
@Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{msg}", PropertyResourceBundle.class);
}
}
With this, can inject it as below:
@Inject
private PropertyResourceBundle bundle;