Jsf 通过@ManagedProperty注入ResourceBundle不会';似乎在@Named内部不起作用
如何从java代码中访问消息包以根据当前语言环境获取消息 我尝试使用Jsf 通过@ManagedProperty注入ResourceBundle不会';似乎在@Named内部不起作用,jsf,cdi,resourcebundle,Jsf,Cdi,Resourcebundle,如何从java代码中访问消息包以根据当前语言环境获取消息 我尝试使用@ManagedProperty如下: @Named @SessionScoped public class UserBean implements Serializable { @ManagedProperty("#{msg}") private ResourceBundle bundle; // ... public void setBundle(ResourceBundle bun
@ManagedProperty
如下:
@Named
@SessionScoped
public class UserBean implements Serializable {
@ManagedProperty("#{msg}")
private ResourceBundle bundle;
// ...
public void setBundle(ResourceBundle bundle) {
this.bundle = bundle;
}
}
但是,它仍然是null
。它似乎在名为的@中不起作用
这就是我在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>
验证程序消息
恩努斯
乌瓦
lang.messages
味精
作者所述:
@巴卢斯我得到错误
16:29:10968错误[org.apache.catalina.core.ContainerBase.[jboss.web].[default host].[WEBSearchPrime\u JB\u lang].[Faces Servlet]](http-localhost-127.0.0.1-8080-1)Servlet.service()对于servlet Faces,servlet抛出异常:org.jboss.weld.exceptions.IllegalProductException:weld-000054生产者无法生成非序列化实例以注入钝化bean的非瞬态字段\\n\\n生产者\:生产者方法[PropertyResourceBundle],其限定符[@Any@Default]声明为[[Method]@products public util.BundleProducer.getBundle()]\\n注入点\:[field]@Inject private model.UserBean.bundle
请注意,我还将可序列化接口放在CDI管理bean中,不能用@Named
注释。您只能在JSF托管bean中使用它,并用@ManagedBean
注释
您需要与@Inject
一起使用。这是在JSF2.3中引入的
@Inject @javax.faces.annotation.ManagedProperty("#{msg}")
private ResourceBundle bundle;
应该注意的是,这是作为@依赖项注入的。所以请注意,当您将其注入到@SessionScoped
bean中时,它基本上也会变成@SessionScoped
,从而永远保持最初注入的值。因此,会话中以后可能发生的任何区域设置更改都不会反映在那里。如果这是一个拦截器,那么您应该将它真正注入到@RequestScoped
或@viewscope
中,或者使用@Producer
,如下所示
CDI没有本机注释来注入EL表达式的计算结果。CDI方法使用带有@products
的“CDI生产者”,其中返回具体类型,如果是.properties
基于文件的资源束,则返回具体类型PropertyResourceBundle
因此,如果您无法升级到JSF 2.3,那么只需在WAR中的某个地方删除该类:
@RequestScoped
public class BundleProducer {
@Produces
public PropertyResourceBundle getBundle() {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().evaluateExpressionGet(context, "#{msg}", PropertyResourceBundle.class);
}
}
有了这个,可以按如下方式注入它:
@Inject
private PropertyResourceBundle bundle;
除了BalusC的回答之外:
由于JSF2.3,也可以注入在faces-config.xml中定义的资源包,而无需使用生产者方法。有一个新的注解javax.faces.annotation.ManagedProperty
(注意它在..annotation
包中,而不是..bean
包中)与@Inject
一起工作:
/。。。
导入javax.faces.annotation.ManagedProperty;
// ...
@命名
@会议范围
公共类UserBean实现了可序列化{
// ...
@注入
@ManagedProperty(“msg”)
私有资源包;
// ...
}
也许我弄错了什么,但实际上提供的两种解决方案都不适用于我的用例。所以我提供了另一个对我有用的答案
根据BalusC提供的答案,我遇到了以下问题:
- 当我使用基于ajax的验证时,我的bean是
@ViewScoped
,并且
必须是可序列化的。既不是ResourceBundle
也不是
PropertyResourceBundle
是可序列化的,无法注入
@相关
范围
- 如果我尝试将生产者更改为使用
@RequestScoped
,它也会失败
因为ResourceBundle
不可代理,因为它定义了final
方法
当我使用JSF2.3(JBoss7.2EAP)时,我使用了Jören Haag提供的解决方案,最初它似乎是有效的。与原始问题一样,我也有多个受支持的区域设置,用户可以在区域设置之间进行更改(在我的例子中是ca
和es
)
我面临的问题是Jören的答案是
- 创建bean时,将评估返回的
ResourceBundle
。在他的例子中,他使用了一个@SessionScoped
bean。创建会话时,ResourceBundle
将使用当前区域设置进行解析。如果用户以后更改了区域设置,ResourceBundle
将不会得到更新。如果用户可以在不更改视图的情况下更改语言,则@ViewScoped
bean也会发生这种情况
- 我还遇到了另一个需要使用
预加载数据的bean问题。在本例中,bean在前面被实例化,因此ResourceBundle
在用户区域设置设置为
之前被注入。因此,如果用户浏览器使用的是es
,但用户将区域设置更改为ca
,则捆绑包将加载es
,因为在渲染阶段之前,视图区域设置不会使用sessionBean.locale
设置为ca
为了克服这个问题,对于我来说,使用注入的问题用例的解决方案是:
@SessionScoped
public class UserBean implements Serializable {
@Inject
@ManagedProperty("#{msg}")
private Instance<ResourceBundle> bundle;
// ....
public void someAction() {
String message = bundle.get().getString("someLabel");
// ...
}
}
@SessionScoped
public class UserBean implements Serializable {
@Inject
private FacesContext context;
// ...
public void someAction() {
ResourceBundle bundle = context.getApplication().getResourceBundle(context, "msg");
String message = bundle.getString("someLabel");
// ...
}
}
@Jens我尝试了由您的链接提供的解决方案,但ManagedProperty在命名bean中不起作用。。。我在bundle.getString(“\u login\u error”)中得到错误NullPointerException@Jenscontext.addMessage(null,新FacesMessage(FacesMessage.SEVERITY\u ERROR,bundle.getString(“\u login\u ERROR”),null))代码>设置bean请求或应用程序的作用域。资源束不应存储在会话中。否则,您需要手动对其进行EL求值或在其周围创建一个包装器。我无法使其成为应用程序范围,因为它是“UserBean”,因此它必须是唯一的,同时它的某些方面也有问题