当前位置: 首页 > 知识库问答 >
问题:

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

花健
2023-03-14

我正在迁移一个在legacy AS上运行的应用程序(其中包含大量的legacy内容)。开始状态是Java 1.7、JBoss 5.1GA、Hibernate3、SEAM 2.2.2、JBPM3.9和一些遗留的RichFaces。

我设法在Java1.8、WildFly8.2和Hibernate 4.3.7、SEAM 2.3.1和RichFaces 4.5.6上部署了它。由于Seam2.3支持JSF2,我还将JSF升级到2.2(Mojarra2.2.8实现,该实现与Wildfly一起提供)。由于使用SEAM,我不得不从应用程序服务器中删除CDI(WELD)(在standalone-full.xml中注释为WELD out)。还对jBPM进行了重写,使其与新的Hibernate一起工作。

该应用程序似乎部署正确,一切都赶上了良好(没有错误)。当我访问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 vs.Mojarra问题),只有Mojarra。也排除了那些bug:

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

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

有人知道怎么解决这个吗?请注意,不幸的是,这里不是一个选择。

我会发布更多的细节(配置,更多的信息,...)应要求。

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的事情引发了问题(冲突?)因为app要靠Seam。

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

关于这个主题的有趣的/相关的阅读可以在这里找到:Wildfly 8 final-weld-core-jsf上的JSF 1.2仍然引用了JSF 2.2 API

共有1个答案

万俟沛
2023-03-14

@jarda_mlejnek一探究竟。问题出在jBPM框架中。

实际上,所有工厂(ContextFactory,ApplicationFactory,PartialViewContextFactory,...)在应用程序部署期间都已正确初始化--甚至当我们在GUI中移动时也已到位。当我们访问开始新的jBPM流程的网页时出现了问题(GUI的某些部分是这样编写的,特别是多步表单)。

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

我们通过修补Mojarra来解决这一问题,即从jBPM激发的工厂的重新注册不执行任何操作,而应用程序与部署期间创建的工厂一起工作。

 类似资料:
  • 我想知道301和307重定向之间的区别。 我希望通过自制url重定向器生成反向链接,我希望任何“链接果汁”或“页面排名果汁”都能直接从原始主页流向最终url,但如果其中一个原始主页出现问题,我希望能够通过删除该特定页面的重定向链接来关闭该链接。有道理? 我的理解是,301是永久性的,这意味着谷歌将看到301并更新其缓存的URL作为最终目的地,而不管我以后是否取消重定向。 如果我使用307,它将不会

  • Django 原生自带一个可选的重定向应用。它将简单的重定向保存到数据库中并处理重定向。它默认使用HTTP 响应状态码301 Moved Permanently。 安装 请依照下面的步骤安装重定向应用: 确保django.contrib.sites 框架已经安装。 添加'django.contrib.redirects' 到 INSTALLED_APPS 设置中。 添加'django.contri

  • 重定向 可以使用redirect助手函数进行重定向 <?php namespace app\index\controller; class Index { public function hello() { return redirect('http://www.thinkphp.cn'); } } redirect函数和控制器的redirect方法的参数

  • 问题内容: 我有一个网页。该网页将用户重定向到另一个网页,或多或少通过以下方式: 好吧,您知道,我要做的是将GET参数转换为POST参数。不要告诉我这很不好,我知道我自己,这也不是我真正要做的,重要的是我从数组中收集数据并尝试通过POST将其提交到另一个页面。但是,如果用户关闭了JavaScript,它将无法正常工作。我需要知道的是:有没有一种方法可以通过PHP传递POST参数,以便重定向也可以通

  • 问题内容: 我正在Tomcat环境中学习Java servlet。我正在学习如何使用j_security_check使用基于表单的登录身份验证。因此,在我的servlet中,我有一个具有j_username和j_password的登录页面。在该servlet的web.xml文件中,我有一个欢迎页面列表,指示我的登录页面“ landing.html”。因此,理想情况下,成功登录后,我希望用户重定向到

  • 问题内容: 我的应用程序有许多System.out.println()语句。 我想从println捕获消息并将其发送到标准记录器(Log4j,JUL等)。 怎么做 ? 问题答案: System类具有,可以用于将输出流更改为例如具有支持的新File流,在这种情况下,可能是另一个使用你选择的日志记录子系统的流。 请记住,如果你将日志记录库配置为输出到标准输出或错误(可能是无限递归类型),则很可能会遇到

  • 主要内容:重定向的工作流程,转发和重定向的区别,response.sendRedirect(),示例重定向属于客户端行为。服务器在收到客户端请求后,会通知客户端浏览器重新向另外一个 URL 发送请求,这称为请求重定向。它本质上是两次 HTTP 请求,对应两个 request 对象和两个 response 对象。 重定向的工作流程 重定向的工作流程如下: 用户在浏览器中输入 URL,请求访问服务器端的 Web 资源。 服务器端的 Web 资源返回一个状态码为 302 的响应信息,该响应的含义为:通

  • 创建网站时,重定向非常重要。 如果请求格式错误的URL或服务器上存在某些错误,则应将其重定向到相应的错误页面。 重定向还可用于阻止人们进入您网站的受限区域。 让我们创建一个错误页面,并在有人请求格式错误的URL时重定向到该页面。 var koa = require('koa'); var router = require('koa-router'); var app = koa(); var _