Как перезагрузить пакет ресурсов в веб-приложении? - PullRequest
10 голосов
/ 01 декабря 2010

У меня есть пакет ресурсов как класс Java, который читает значения из базы данных.Когда я обновляю базу данных, мне нужно перезагрузить пакет, но я не знаю как.Кто-нибудь помогает?

package model.helpers;
public class Messages_en extends ListResourceBundle {
      protected Object[][] getContents() {
            // from DB
            // ...
      }
}

В связи с этим я использую комплект, как показано ниже:

<f:loadBundle basename="model.helpers.Messages" var="m" />

Ответы [ 3 ]

10 голосов
/ 23 января 2011

Это не совсем тривиально.

Если очистить 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 вашим любимым отражающим утилитом, если необходимо, и добавьте обработчики исключений и ноль, где это необходимо)

5 голосов
/ 01 декабря 2010
ResourceBundle.clearCache();     

ИЛИ

Messages_en .clearCache();

Вызов этого метода перезагрузит ресурсы, обновит пакет

1 голос
/ 16 ноября 2016

Вы даже можете избежать импорта классов сварки и jsf-impl в свой модуль с еще несколькими линиями отражения:

Class<?> applicationAssociateClass = Class.forName("com.sun.faces.application.ApplicationAssociate");
Method getCurrentInstance = applicationAssociateClass.getMethod("getCurrentInstance");
Object applicationAssociate = getCurrentInstance.invoke(null);
Method getResourceBundles = applicationAssociate.getClass().getMethod("getResourceBundles");
Map<String, ?> resourceBundles = (Map<String, ?>)getResourceBundles.invoke(applicationAssociate);
Object appBundle = resourceBundles.get(name);
Map<Locale, ResourceBundle> resources = getFieldValue(appBundle, "resources");
resources.clear();

(хорошо работает с Wildfly 10)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...