Jsf 通过@ManagedProperty注入ResourceBundle不会';似乎在@Named内部不起作用

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

如何从java代码中访问消息包以根据当前语言环境获取消息

我尝试使用
@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@Jens
context.addMessage(null,新FacesMessage(FacesMessage.SEVERITY\u ERROR,bundle.getString(“\u login\u ERROR”),null))设置bean请求或应用程序的作用域。资源束不应存储在会话中。否则,您需要手动对其进行EL求值或在其周围创建一个包装器。我无法使其成为应用程序范围,因为它是“UserBean”,因此它必须是唯一的,同时它的某些方面也有问题