Это не совсем тривиально.
Если очистить ResourceBundle
с помощью clearCache()
, не всегда можно получить желаемые результаты. Часто нужно хотя бы попытаться очистить с помощью загрузчика класса контекста:
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
Однако это все равно не будет перезагружать пакет ресурсов, определенный в файлеface-config.xml. По крайней мере, реализация Mojarra JSF 1.2 в частном порядке кэширует пакет ресурсов внутри. Это происходит в:
FacesContext -> Application -> associate (ApplicationAssociate) -> resourceBundles (Map<String, ApplicationResourceBundle>()) -> resources (Map<Locale, ResourceBundle>)
Можно очистить этот кэш с помощью отражения (в конце концов, это просто запись на карте), или вы можете заменить приложение. И то, и другое обычно не бывает легкомысленно.
Чисто для разработки вы могли бы использовать JRebel, который, вероятно, уже знает Мохарру и, скорее всего, выполняет трюк отражения, упомянутый выше.
После некоторых экспериментов я пришел к следующему коду, который работает на JBoss AS 5 / JSF 1.2. Он привязывает ваш код к Mojarra (импортирует пакеты Sun) и может сломаться при любом обновлении из-за использования отражающих трюков. Но в любом случае, это код:
public static void reloadBundle() {
ResourceBundle.clearCache(Thread.currentThread().getContextClassLoader());
ApplicationResourceBundle appBundle = ApplicationAssociate.getCurrentInstance().getResourceBundles().get("your_bundle_name");
Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources");
resources.clear();
}
@SuppressWarnings("unchecked")
private static <T> T getFieldValue(Object object, String fieldName) {
try {
Field field = object.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
return (T) field.get(object);
} catch (Exception e) {
return null;
}
}
(замените вспомогательный метод getFieldValue вашим любимым отражающим утилитом, если необходимо, и добавьте обработчики исключений и ноль, где это необходимо)