Wildfly 8 SEAM2 redirect - javax.faces.context.PartialViewCo



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

我设法在Java 1.8、Wildfly 8.2、Hibernate 4.3.7、SEAM 2.3.1和RichFaces 4.5.6上部署了它。由于SEAM2.3能够支持JSF2,我还将JSF升级到了2.2(Wildfly附带的Mojarra 2.2.8实现)。由于使用SEAM,我不得不从应用服务器中删除CDI(WELD)(在独立的full.xml中注释了WELD out)。

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

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:

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

<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(更新:这似乎不起作用。)

同样有趣/相关的阅读内容可以在这里找到:Wildfly 8 Final-weld-core-JSF上的JSF1.2仍然引用JSF2.2 API

@jarda_mlejnek发现了问题所在。问题出在jBPM框架中。

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

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

我们通过修补Mojarra解决了这个问题,即重新注册从jBPM启动的工厂没有任何作用,应用程序与部署期间创建的工厂一起工作。

相关内容

  • 没有找到相关文章

最新更新