Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/331.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 我可以在Hibernate事件侦听器中访问FacesContext吗?_Java_Hibernate_Jsf - Fatal编程技术网

Java 我可以在Hibernate事件侦听器中访问FacesContext吗?

Java 我可以在Hibernate事件侦听器中访问FacesContext吗?,java,hibernate,jsf,Java,Hibernate,Jsf,以下是我的设想: 我将my-jsf-app.war(JSF1.2应用程序)和daos-and-entities.har(Hibernate 3.3.1)部署到JBOSSAS 5服务器上。我想要的是在我的应用程序中有某种更改日志,其中包含“谁进行了更改”的信息。所以我的想法是让hibernate事件监听器访问FacesContext(实际上是上下文中的HttpSession)来检索当前登录的用户 因此,基本上我配置了事件侦听器,并添加了以下方法来检索当前登录的用户 protected static

以下是我的设想:

我将my-jsf-app.war(JSF1.2应用程序)和daos-and-entities.har(Hibernate 3.3.1)部署到JBOSSAS 5服务器上。我想要的是在我的应用程序中有某种更改日志,其中包含“谁进行了更改”的信息。所以我的想法是让hibernate事件监听器访问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。但是,如果hibernate操作(例如saveOrUpdate())是从JSF ManagedBean actionmethod中直接触发的,那么事件侦听器不应该由与actionmethod相同的线程执行吗

任何帮助都是值得的,也许还有一种完全不同的方法,我不知道。不过,我显然不想在所有dao调用中添加userContext参数,因为这将是一项巨大的工作


Thx预先

在得到一个有价值的提示后,我找到了一个解决方案。WAR在其WEB-INF\lib中有JSF实现JAR。由于WAR和HAR是单独的部署,它们使用单独的类加载器,这导致WAR从其WEB-INF\lib加载JSF实现,而HAR从JBOSS安装加载JSF实现

通过以下方式更改上述代码,我可以强制使用正确的类加载器:

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)不会捕获它


这很好用

在得到一个有价值的提示后,我找到了一个解决方案。WAR在其WEB-INF\lib中有JSF实现JAR。由于WAR和HAR是单独的部署,它们使用单独的类加载器,这导致WAR从其WEB-INF\lib加载JSF实现,而HAR从JBOSS安装加载JSF实现

通过以下方式更改上述代码,我可以强制使用正确的类加载器:

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)不会捕获它


这很好用

我在EclipseLink和JSF中看到过类似的工作,所以看起来应该是可能的。尝试使用调试器单步执行-在事件侦听器上设置断点,然后查看堆栈跟踪的外观。这至少证实了您关于作用域的假设(这似乎是合理的),即事件侦听器将在JSF请求的作用域内运行,从而绑定FacesContext。其他尝试:使用常规方法调用而不进行反射;摆脱“静态”;或者将侦听器放在webapp本身中。也许是一些微妙的类加载器层次结构问题。感谢您对类加载器问题的提示,这让我找到了一个解决方案。我将发布一个答案。我已经看到了EclipseLink和JSF的类似工作,所以这似乎是可能的。尝试使用调试器单步执行-在事件侦听器上设置断点,然后查看堆栈跟踪的外观。这至少证实了您关于作用域的假设(这似乎是合理的),即事件侦听器将在JSF请求的作用域内运行,从而绑定FacesContext。其他尝试:使用常规方法调用而不进行反射;摆脱“静态”;或者将侦听器放在webapp本身中。也许是一些微妙的类加载器层次结构问题。感谢您对类加载器问题的提示,这让我找到了一个解决方案。我会发布答案的。谢谢。澄清异常部分的一点是:exception的Catch子句不捕获RuntimeException。因为它是Exception的子类。。。谢谢你。澄清异常部分的一点是:exception的Catch子句不捕获RuntimeException。因为它是Exception的子类。。。