Могу ли я получить доступ к FacesContext внутри прослушивателя событий Hibernate? - PullRequest
1 голос
/ 04 ноября 2011

Вот мой сценарий:

У меня развернуты my-jsf-app.war (приложение JSF 1.2) и daos-and-entity.har (Hibernate 3.3.1) на сервере JBOSSAS 5. Я хочу, чтобы в моем приложении был какой-то журнал изменений, содержащий информацию «кто сделал изменения». Таким образом, моя идея заключалась в том, чтобы иметь прослушиватели событий гибернации, которые обращаются к FacesContext (или фактически к HttpSession внутри контекста), чтобы извлечь текущего зарегистрированного пользователя.

Таким образом, я настроил прослушиватели событий и добавил следующий метод для извлечения текущего пользователя, вошедшего в систему.

protected static String tryToFindUserLogin() {

    try {
        Class classFacesContext = Class.forName("javax.faces.context.FacesContext");
        Class classExternalContext = Class.forName("javax.faces.context.ExternalContext");
        Method methodGetCurrentInstance =  classFacesContext.getMethod("getCurrentInstance", (Class[])null);
        Method methodGetExternalContext =  classFacesContext.getMethod("getExternalContext", (Class[])null);
        Method methodGetRemoteUser =  classExternalContext.getMethod("getRemoteUser", (Class[])null);

        // This call always returns null
        Object currentFacesContext = methodGetCurrentInstance.invoke(null, (Object[])null);

        Object currentExternalContext = methodGetExternalContext.invoke(currentFacesContext, (Object[])null);
        String login = (String)  methodGetRemoteUser.invoke(currentExternalContext, (Object[])null);
        logger.debug("Found Weblogin: " + login);
        return login;

    } catch (Exception e) {
        logger.debug(e, e);
    }

    return "anonymous";
    }

Для этого я использую отражение Java, поскольку файл HAR также используется в других не-jsf-проектах.

Проблема в том, что я никогда не получаю currentFacesContext. Я понимаю, что FacesContext.getCurrentInstance () является ThreadLocal. Но если действие гибернации (например, saveOrUpdate ()) напрямую вызывается из метода действия JSF ManagedBean, не должен ли прослушиватель событий выполняться тем же потоком, что и метод действия?

Любая помощь оценивается, возможно, есть и совершенно другой подход к моему сценарию, о котором я не знаю. Я, очевидно, не хочу добавлять параметр userContext ко всем моим вызовам dao, так как это будет огромный объем работы.

Спасибо заранее

1 Ответ

1 голос
/ 15 ноября 2011

Получив ценную подсказку, я нашел решение. WAR содержит JAR-файлы реализации JSF внутри своего WEB-INF \ lib. Поскольку WAR и HAR являются отдельными развертываниями, они используют отдельные загрузчики классов, в результате чего WAR загружает реализацию JSF из своего WEB-INF \ lib, а HAR загружает ее из установки JBOSS.

Мне удалось принудительно использовать правильный загрузчик классов, изменив вышеуказанный код следующим образом:

protected static String tryToFindUserLogin() {

    try {
        /*** Obtain the classLoader from the calling Thread, instead of using the default ***/
        ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
        Class classFacesContext = classLoader.loadClass("javax.faces.context.FacesContext");
        Class classExternalContext = classLoader.loadClass("javax.faces.context.ExternalContext");
        /**************/

        Method methodGetCurrentInstance =  classFacesContext.getMethod("getCurrentInstance", (Class[])null);
        Method methodGetExternalContext =  classFacesContext.getMethod("getExternalContext", (Class[])null);
        Method methodGetRemoteUser =  classExternalContext.getMethod("getRemoteUser", (Class[])null);

        Object currentFacesContext = methodGetCurrentInstance.invoke(null, (Object[])null);

        Object currentExternalContext = methodGetExternalContext.invoke(currentFacesContext, (Object[])null);
        String login = (String)  methodGetRemoteUser.invoke(currentExternalContext, (Object[])null);
        logger.debug("Found Weblogin: " + login);
        return login;

    } catch (Throwable e) {
        logger.debug(e, e);
    }

    return "anonymous";
    }

Кроме того, я изменил блок catch на catch (Throwable), потому что при запуске в среде, отличной от JSF, getMethod () может вызвать исключение RuntimeException, которое не перехватывается catch (Exception)

Это прекрасно работает!

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