作为ManagedProperty序列化问题访问ResourceBundle [英] Accessing ResourceBundle as ManagedProperty Serialization Issue

查看:87
本文介绍了作为ManagedProperty序列化问题访问ResourceBundle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

首先,对不起我的英语不好!

first of all, sorry for my bad english!

我以@ManagedProperty的身份访问ResourceBundle(.properties).ResourceBundle对象不可序列化,因此我在Eclipse/Tomcat控制台中收到一条错误消息,指出该对象无法序列化/反序列化.等等.

in the following managed Bean (ApplicationScoped), i access a ResourceBundle(.properties) as a @ManagedProperty. a ResourceBundle Object is not serializable, so i get in the Eclipse/Tomcat Console an Error saying that this object cannot be serialized/de-serialized.. etc.

从持久性存储中异常加载会话java.io.WriteAbortedException:编写中止;java.io.NotSerializableException:java.util.PropertyResourceBundle

Exception loading sessions from persistent storage java.io.WriteAbortedException: writing aborted; java.io.NotSerializableException: java.util.PropertyResourceBundle

我对此问题有2个问题:

i have 2 Questions to this issue:

  • 我认为,JSF将预定义(在faces-config.xml中)的 ResourceBundles 处理为 ApplicationScoped Bean.这意味着(如果我正确理解的话),该对象/Bean(ResourceBundle)以某种方式存储在文件中的某个位置(永久存储).现在,由于 ResourceBundle 无法序列化,那么它以哪种格式存储?以及JSF如何为此类"Bean"提供服务?序列化的对象以字节形式存储在文件中,那么如何不存储可序列化的对象呢?
  • 在以下示例中,我将我的 @ManagedProperty ResourceBundle 声明为 transient (由于序列化问题),但是瞬态对象不会存储在持久性存储中(是无状态的),这是否意味着每次调用方法 getConfigurationAttribute (我在其中使用此resourceBundle的方法)都将重新创建/重新加载ManagedPropery ResourceBundle,因为它被标记为瞬态的?
  • i think, JSF handles pre-defined(in faces-config.xml) ResourceBundles as ApplicationScoped beans. this means(if i understanding this correctly), this Object/Bean (ResourceBundle) is been stored somewhere somehow in a file (persistent storage). Now and since ResourceBundle is not serializable, then in which format is it been stored? and how JSF serves such "Beans"? serialized Objects are stored in files as Bytes, so how not serializable Objects are stored?
  • in the following example, i would declare my @ManagedProperty ResourceBundle as transient (due to serialization problem), but transient objects won't be stored in persistent storage (stateless), does this mean that with every call of the method getConfigurationAttribute(where i use this resourceBundle) will recreate/reload the ManagedPropery ResourceBundle since it is marked as transient?

非常感谢您的帮助.

@ManagedBean(name="facesResource",eager=true)
@ApplicationScoped
public class FacesResource implements Serializable{
    private static final long serialVersionUID = 2454454363100273885L;
    @ManagedProperty("#{FACES_CONFIG}")
    private ResourceBundle facesConfig;
    //private transient ResourceBundle facesConfig;

    ....
    private Map<String,Language> languagesMap;  
    private Map<String,Theme> themesMap;
    ....

    public FacesResource(){

    }
    @PostConstruct
    public void init(){
        System.out.println("*** FacesResource init ....");
        try{
            ....
            this.initLanguages();
            this.initThemes();
            ....
        }catch(Exception ex){
            ex.printStackTrace();
        }
    }       

    public String getConfigurationAttribute(String attributeKey){
        return this.facesConfig.getString(attributeKey);
    }
    // ... other methods & getter/setter ...etc

}

更新:

  • FacesResource Bean中的ResourceBundle与请求 Locale 无关,因此将其加载到ApplicationScoped Bean BUT中不是问题

  • the ResourceBundle in the FacesResource Bean is independent of the Request Locale, so its not a problem to load it in an ApplicationScoped Bean, BUT

因为我在其他SessionScoped Bean中访问/注入(如@ManagedProperty)此ApplicationScoped Bean,因此应对其进行序列化,这意味着所有属性(包括resourceBundle)也应进行序列化,这就是问题所在序列化/反序列化

since i access/inject(as @ManagedProperty) this ApplicationScoped Bean in other SessionScoped Beans, which should be serialized, which means, that all attributes (resourceBundle included) should be serialized too, and here i got the Problem with Serialization/Deserializazion

@BalusC:如果我确实喜欢您在答案中提出的建议: ResourceBundle.getBundle("com.example.text"),我必须提供捆绑包的baseName.但是,这正是我要避免的事情.我不想在Java源代码中对静态路径进行硬编码),以便在路径更改时(最不可能的,但是对于Case),我不希望在Java源代码中更改路径,而仅在faces-config中更改.xml.

@BalusC: if i do like you suggest in your answer: ResourceBundle.getBundle("com.example.text"), i have to provide the baseName of the Bundle. BUT this is exactly what i want to avoid. i don't want to hardcode static Paths in java Source Codes), so that when the path changes(most unlikely, but for the Case), i don't like to change paths in Java Source Codes but only in faces-config.xml.

,而且我无法使用 FacesContext.getCurrentInstance().getApplication().getResourceBundle(facesContext,"bundleVarName"); ,因为我的Bean标记为eager = true,这意味着此时 facesContext NULL

and i cannot use FacesContext.getCurrentInstance().getApplication().getResourceBundle(facesContext, "bundleVarName"); because my Bean is marked with eager=true, which means, the facesContext is NULL at this moment!

推荐答案

我认为,JSF将预定义(在faces-config.xml中)的ResourceBundle作为ApplicationScoped Bean处理.

不.它们由 ResourceBundle API本身进行管理.JSF只是根据请求的语言环境在每个请求的基础上解决它们(否则,它将影响任何访问Web应用程序的用户的语言!).因此,它们本质上是请求范围的.但这一切与序列化无关. ResourceBundle 类根本不会被设计成可序列化的.它只是将捆绑包懒惰地加载到Java的内存中.

Nope. They are managed by ResourceBundle API itself. JSF just resolves them on a per-request basis based on the requested locale (otherwise it would affect the language of any user visiting the web application!). So, they are essentially request scoped. But this all has further nothing to do with serialization. The ResourceBundle class is simply never intented to be serializable. It just lazily loads the bundles in Java's memory.

您最好也这样做.反序列化后,如果它变为 null ,则延迟加载它.您仅不应评估#{FACES_CONFIG} ,因为它取决于请求的语言环境.前提是您只能使用JSF < resource-bundle>< var> ,那么最好通过 Application#getResourceBundle()加载它们.提供了一个资源束var名称为 FACES_CONFIG ,下面是一个示例:

You'd best just do the same. Lazy loading it if it becomes null after deserialization. You only shouldn't evaluate #{FACES_CONFIG}, because it would be dependent on request locale. Provided that you can only use JSF <resource-bundle><var>, then you'd best load them via Application#getResourceBundle(). Provided a resource bundle var name of FACES_CONFIG, here's an example:

private transient ResourceBundle facesConfig;

public ResourceBundle getFacesConfig() {
    if (facesConfig == null) {
        FacesContext context = FacesContext.getCurrentInstance();
        facesConfig = context.getApplication().getResourceBundle(context, "FACES_CONFIG");
    }

    return facesConfig; 
}

顺便说一句,变量名称 facesConfig 非常混乱.即表示它表示 faces-config.xml 的内容.

By the way, the variable name facesConfig is very confusing. It namely suggests that it represents the contents of faces-config.xml.

这篇关于作为ManagedProperty序列化问题访问ResourceBundle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆