jsfserializationjsf-2.2resourcebundletransient

Accessing ResourceBundle as ManagedProperty Serialization Issue


first of all, sorry for my bad english!

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.

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

i have 2 Questions to this issue:

Your help is greatly appreciated.

@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

}

UPDATE:


Solution

  • i think, JSF handles pre-defined(in faces-config.xml) ResourceBundles as ApplicationScoped beans.

    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.

    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; 
    }
    

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

    See also: