views:

711

answers:

2

I have an exsisting Java/JSF website all the text on the screen is coming from property files via <f:loadBundle basename="org.example.applicaltion" var="applicaltion" /> which pulls the text from applicaltion.properties.

For a runtime configurable subset of these I am wanting to pull the string from else where (CMS via web services). Looking at the ResourceBundle class it appares to have an infrastructer for something close to this with delegation to a parent ResourceBundle.

I am wanting somethis like this

public class Applicaltion extends ResourceBundle{
    @Override
protected Object handleGetObject(String key) {
 if(overridenKey(key)){
  return overridedValue(key);
 }
 return null; // ResourceBundle.getObject will delegate to parent 
       // if we return null
}
}

I have tried this and parent is null, I assume this is more used for the case of default -> en -> en_GB.

I am considering the not very appealing option of have the property file a different name from the custom resourceBundle and then delegating through the full stack of ResourceBundle.getBundle(PROPERTY_FILE_NAME).getString(key) from within CustomResourceBundle.handleGetObject(key).

Any better ideas?

A: 

You could write a custom PropertyResolver, and then have that perform the logic of where to pull the property values from.

For example, you could define a bean called messageSource and have that load up application.properties, plus your CMS properties or whatever you have.

Then write a custom PropertyResolver (there's an example of how to do this with Spring's MessageSource here) and link it in to your faces-config.xml using something like this:

<application>  
<property-resolver>  
      com.package.MessageSourcePropertyResolver  
   </property-resolver>  
</application>
Phill Sacre
Thanks for the idea but I would far perfer to modify the existing resource loading provided via f:loadBundle then to modify property resolution. I can already gain programatic control via extending the ResrouceBundle as in the question.
David Waters
A: 

I ended up solving this by checking if we had an override value, if we did returning that, else delegating to the standard resource bundle

public class UILabels extends ResourceBundle {


private ResourceBundle getFileResources(){
 return ResourceBundle.getBundle("com.example.web.UILabelsFile", this.getLocale());
}

public Enumeration<String> getKeys() {
 return getFileResources().getKeys();
}

protected Object handleGetObject(String key) {
 if(overrideValue(key)){
  return getOverridenValue(key);
 }
 return getFileResources().getObject(key);
}

}

Note the slight difference in name class is UILabels which is what all clients will use the file is UILabelsFile so the ResourceBundle loader does not go recursive.

David Waters