java - Wildfly 8 SEAM2 重定向 - javax.faces.context.PartialViewContextFactory

标签 java jsf upgrade wildfly-8 seam2

我正在迁移一个在遗留 AS 上运行的应用程序(里面有很多遗留的东西)。初始状态是 Java 1.7、JBoss 5.1GA、Hibernate 3、SEAM 2.2.2、jBPM 3.9 和一些遗留的 richfaces。

我设法将它部署在 Java 1.8、带有 Hibernate 4.3.7 的 Wildfly 8.2、SEAM 2.3.1 和 RichFaces 4.5.6 上。由于 SEAM 2.3 支持 JSF2,因此我还将 JSF 升级到 2.2(Mojarra 2.2.8 实现,随 Wildfly 一起提供)。由于使用 SEAM,我不得不从应用程序服务器中删除 CDI (WELD)(在 standalone-full.xml 中注释掉 WELD)。还重写了 jBPM 以使其与新的 Hibernate 一起工作。

该应用似乎部署正确,一切正常(无错误)。当我访问网络界面时,登录页面加载得很好。我输入我的登录信息,然后 - 成功登录后 - 出现一个重定向,它通过这样的外观从应用程序的深处调用:

import org.jboss.seam.faces.Redirect;
class C {
    public static void showPage(String page) {
        Redirect redirect = Redirect.instance();
        redirect.setViewId(page);       
        redirect.execute();
    }
}

这样调用,抛出异常,网页处理停止。异常:

SEVERE [javax.faces] (default task-8) Unable to obtain InjectionProvider from init time FacesContext. Does this container implement the Mojarra Injection SPI?
SEVERE [javax.faces] (default task-8) Application was not properly initialized at startup, could not find Factory: javax.faces.context.PartialViewContextFactory. Attempting to find backup.
...
Caused by: org.jboss.seam.faces.RedirectException: Could not find backup for factory javax.faces.context.PartialViewContextFactory. 
    at org.jboss.seam.faces.FacesManager.redirect(FacesManager.java:237) [jboss-seam.jar:2.3.1.Final]
    at org.jboss.seam.faces.FacesManager.redirect(FacesManager.java:190) [jboss-seam.jar:2.3.1.Final]
    at org.jboss.seam.faces.Redirect.execute(Redirect.java:154) [jboss-seam.jar:2.3.1.Final]

但是还有其他重定向 - 所有这些都在 pages.xml 中明确指定 - 工作正常。

没有任何冲突的库(例如广泛存在的 MyFaces 与 Mojarra 问题),只有 Mojarra。还排除了那些错误:

https://issues.jboss.org/browse/WFLY-2594

https://java.net/jira/browse/JAVASERVERFACES-3189

有人知道怎么解决吗?请注意,很遗憾,丢弃 SEAM 不是这里的一个选项。

我会根据要求发布更多详细信息(配置、更多信息...)。

更新: 我调试了更多——将一些日志记录直接添加到 SEAM 的 FacesManager 中。日志记录如下所示:

private void redirect(String viewId, FacesContext context, String url)
   {
      url = Pages.instance().encodeScheme(viewId, context, url);
      if ( log.isDebugEnabled() )
      {
         log.debug("redirecting to: " + url);
      }
      ExternalContext externalContext = context.getExternalContext();
      controllingRedirect = true;
      try
      {  
         log.debug("Trying to get context...");
         log.debug("Contexts.getEventContext(): "+Contexts.getEventContext());
         Contexts.getEventContext().set(REDIRECT_FROM_MANAGER, "");
         log.debug("REDIRECT_FROM_MANAGER set");
         log.debug("externalContext: "+externalContext);
         externalContext.redirect( externalContext.encodeActionURL(url) );
      }
      catch (IOException ioe)
      {
         throw new RedirectException(ioe);
      }
      catch (IllegalStateException ise)
      {
          log.debug("Caught illegal state exception.");
         throw new RedirectException(ise.getMessage());
      }
      finally
      {
         Contexts.getEventContext().remove(REDIRECT_FROM_MANAGER);
         controllingRedirect = false;
      }
      context.responseComplete();
   }

在异常发生之前记录输出:

DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) redirecting to: /idm/user/personal/personal.seam?cid=2
DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) Trying to get context...
DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) Contexts.getEventContext(): BasicContext(EVENT)
DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) REDIRECT_FROM_MANAGER set
DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) externalContext: org.richfaces.context.SkinningExternalContextFactory$ExternalContextWrapperImpl@1dcafb6
DEBUG [org.jboss.seam.faces.FacesManager] (default task-5) Caught illegal state exception.

更新 2:

因此,我在 SEAM 中摆弄调试消息并且(到目前为止)发现了这一点:

DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) viewId: /adminOrUser/home.xhtml
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) parameters: {}
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) includeConversationId: true
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) includePageParams: true
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) FacesContext.getCurrentInstance: com.sun.faces.context.FacesContextImpl@67667a
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) context.getApplication: com.sun.faces.application.ApplicationImpl@134d311
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) context.getApplication.getViewHandler: org.jboss.as.jsf.injection.weld.WildFlyConversationAwareViewHandler@151c033
DEBUG [org.jboss.seam.faces.FacesManager] (default task-14) context.getApplication.getViewHandler.getRedirectURL: /idm/adminOrUser/home.seam

有趣的部分是 org.jboss.as.jsf.injection.weld.WildFlyConversationAwareViewHandler,这让我很不爽。为什么有一个类可能属于 WELD,即使我禁用了它?我没有机会进一步调查,但我的理论是我以某种方式间接地将 WELD 引入部署并焊接东西然后导致问题(冲突?),因为应用程序应该依赖于 SEAM。

更新 3:

WELD 相关问题的概念可能是正确的。作为 JSF 实现,Wildfly 使用 Mojarra(2.2.8) 作为 jsf-impl-2.2.8-jbossorg-1.jar 集成到 AS 中。查看 AS 中的 modules/system/layers/base/com/sun/jsf-impl/main/module.xml 有 WELD 依赖项:

<dependencies>
    ...
    <module name="org.jboss.weld.core"/>
    <module name="org.jboss.weld.spi"/>
</dependencies>

因此,要么 WELD 仍然作为依赖进入部署,要么 JSF 实现依赖于当前关闭的某些东西。

当我打开焊缝时,出现以下错误:

ERROR [org.jboss.seam.exception.Exceptions] (default task-4) handled and logged exception: org.jboss.weld.context.NonexistentConversationException: WELD-000321: No conversation found to restore for id 2
    at org.jboss.weld.context.AbstractConversationContext.initialize(AbstractConversationContext.java:260) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.initialize(LazyHttpConversationContextImpl.java:68) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
    at org.jboss.weld.context.http.LazyHttpConversationContextImpl.checkContextInitialized(LazyHttpConversationContextImpl.java:96) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
    at org.jboss.weld.context.AbstractConversationContext.getCurrentConversation(AbstractConversationContext.java:460) [weld-core-impl-2.2.6.Final.jar:2014-10-03 10:05]
    at org.jboss.weld.jsf.ConversationAwareViewHandler.getActionURL(ConversationAwareViewHandler.java:111) [weld-core-jsf-2.2.6.Final.jar:2014-10-03 10:05]
    at javax.faces.application.ViewHandlerWrapper.getActionURL(ViewHandlerWrapper.java:189) [jboss-jsf-api_2.2_spec-2.2.8.jar:2.2.8]
    at com.sun.faces.application.view.MultiViewHandler.getRedirectURL(MultiViewHandler.java:468) [jsf-impl-2.2.8-jbossorg-1.jar:]
    at javax.faces.application.ViewHandlerWrapper.getRedirectURL(ViewHandlerWrapper.java:250) [jboss-jsf-api_2.2_spec-2.2.8.jar:2.2.8]
    at org.jboss.seam.jsf.SeamViewHandler.getRedirectURL(SeamViewHandler.java:133) [jboss-seam.jar:2.3.1.Final]
    at javax.faces.application.ViewHandlerWrapper.getRedirectURL(ViewHandlerWrapper.java:250) [jboss-jsf-api_2.2_spec-2.2.8.jar:2.2.8]
    at javax.faces.application.ViewHandlerWrapper.getRedirectURL(ViewHandlerWrapper.java:250) [jboss-jsf-api_2.2_spec-2.2.8.jar:2.2.8]
    at org.jboss.weld.jsf.ConversationAwareViewHandler.getRedirectURL(ConversationAwareViewHandler.java:142) [weld-core-jsf-2.2.6.Final.jar:2014-10-03 10:05]
    at javax.faces.application.ViewHandlerWrapper.getRedirectURL(ViewHandlerWrapper.java:250) [jboss-jsf-api_2.2_spec-2.2.8.jar:2.2.8]
    at org.jboss.seam.faces.FacesManager.redirect(FacesManager.java:182) [jboss-seam.jar:2.3.1.Final]

这意味着在 WELD 管理的上下文中找不到 id=2 的对话。这并不奇怪,因为 cid 是由 SEAM 生成的,而 WELD 根本不知道它。

有一个关于使 JSF 与 WELD 一起工作的简短文档: http://docs.jboss.org/weld/reference/latest/en-US/html/ri-spi.html#_jsf

第二种可能性是关闭 WELD 并更改 JSF 实现,这样 jsf-impl-2.2.8-jbossorg-1.jar 将不会被使用: https://developer.jboss.org/wiki/StepsToAddAnyNewJSFImplementationOrVersionToWildFly (更新:这似乎不起作用。)

还可以在此处找到该主题的有趣/相关读物:JSF 1.2 on Wildfly 8 Final - weld-core-jsf is still referencing JSF 2.2 API

最佳答案

@jarda_mlejnek发现发生了什么事。问题出在 jBPM 框架中。

事实是,所有工厂(ContextFactory、ApplicationFactory、PartialViewContextFactory 等)在应用程序部署期间都已正确初始化 - 即使我们在 GUI 中移动时也已就位。当我们访问启动新 jBPM 进程的网页时出现问题(GUI 的某些部分是这样编写的,尤其是多步骤表单)。

为了定位工厂,Mojarra 使用 FactoryFinder 类,它通过搜索以类加载器为键的 HashMap 来跟踪当前工厂。当 jBPM 进程启动时,它将 Faces 看到的类加载器更改为它自己的 (org.jbpm.instantiation.ProcessClassLoader),这反过来又重新初始化了 Mojarra - 对于这个类加载器,没有创建工厂。从 Mojarra 的角度来看,所有工厂都消失了。这可能是 JAVASERVERFACES-3189 的一些奇怪情况但是,由于我们的场景非常不标准,因此我们没有报告此行为。

我们通过修补 Mojarra 来解决这个问题,方法是重新注册从 jBPM 触发的工厂什么都不做,应用程序可以与部署期间创建的工厂一起工作。

关于java - Wildfly 8 SEAM2 重定向 - javax.faces.context.PartialViewContextFactory,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31187989/

相关文章:

java - 使用 Java 解析 CSV 时管理文件列名称和位置

windows - 如何在不丢失模块的情况下在 Windows 上更新 Perl?

visual-studio - 从 Visual Studio 2015 切换/升级到 Visual Studio 2017

mysql - 错误 1146 (42S02) : Table 'mysql.general_log' doesn't exist

java - 根据文件头数据确定文件扩展名的设计

java - 如何使用自定义值初始化jsp标签?

java - 我正在尝试使用按值排序的 HashMap 来构建一棵树。

java - 如何从 JSF 中的自定义类中的自定义类访问属性?

java - 类 'java.util.HashMap$Node' 没有可写属性 'key'

java - JSF EL : Fallback if l18n-Propperty not found