jsf - Seam/Spring WebFlow 应用程序中的 StackOverflowError

标签 jsf spring-mvc seam spring-webflow

我们正在逐步用 Spring-MVC 和 Spring-Webflow 替换 Seam 组件。

运行 JMeter 测试日志在几个小时后变得杂乱无章,出现 StackOverFlowErrors:

javax.servlet.ServletException: Servlet execution threw an exception
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:313)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.myfaces.webapp.filter.ExtensionsFilter.doFilter(ExtensionsFilter.java:341)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.ajax4jsf.webapp.BaseFilter.doFilter(BaseFilter.java:530)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
...
Caused by: java.lang.StackOverflowError
    at org.jboss.seam.jsf.SeamApplication.getMessageBundle(SeamApplication.java:264)
    at org.springframework.faces.webflow.FlowApplication.getMessageBundle(FlowApplication.java:214)
    at org.jboss.seam.jsf.SeamApplication.getMessageBundle(SeamApplication.java:264)
    at org.springframework.faces.webflow.FlowApplication.getMessageBundle(FlowApplication.java:214)
    at org.jboss.seam.jsf.SeamApplication.getMessageBundle(SeamApplication.java:264)
    at org.springframework.faces.webflow.FlowApplication.getMessageBundle(FlowApplication.java:214)
    at org.jboss.seam.jsf.SeamApplication.getMessageBundle(SeamApplication.java:264)

所以 getMessageBundle 方法被两个实例调用:SeamApplication 和 FlowApplication。

查看 javax.faces.application.Application 类,它说:

“因为这个实例是共享的,所以必须以线程安全的方式实现。”

也许这两个应用程序实例正在尝试访问导致竞争条件的同一个包?

编辑: 在应用程序不再响应后,我们重新启动了服务器,现在错误出现在另一个地方:

Caused by: java.lang.StackOverflowError
at org.jboss.seam.contexts.BasicContext.get(BasicContext.java:49)
at org.jboss.seam.contexts.BasicContext.get(BasicContext.java:44)
at org.jboss.seam.core.Init.instance(Init.java:117)
at org.jboss.seam.jsf.SeamApplication$ConverterLocator.<init>(SeamApplication.java:140)
at org.jboss.seam.jsf.SeamApplication.createConverter(SeamApplication.java:122)
at org.springframework.faces.webflow.FlowApplication.createConverter(FlowApplication.java:161)
at org.jboss.seam.jsf.SeamApplication.createConverter(SeamApplication.java:126)
at org.springframework.faces.webflow.FlowApplication.createConverter(FlowApplication.java:161)
at org.jboss.seam.jsf.SeamApplication.createConverter(SeamApplication.java:126)

最后两行在日志文件中重复了数千次。

我们正在使用以下组件版本:

JSF-1.2

Seam-2.2.0

Spring WebFlow 2.3.4

Spring MVC 3.0.5

更新任何组件都不是一种选择。

最佳答案

SeamApplication FlowApplication 在正确委派给包装的应用程序方面存在错误。修复它的一种方法是通过 FlowApplicationFactory .

首先捕获它的raw source code并将其放入 webapp 项目的 Java 源文件夹中,保留其原始包。您不一定需要操作 JAR。 /WEB-INF/classes 中的类(class)比 JAR 中的类加载优先级更高。

然后按如下方式操作类(基于 OmniFaces OmniApplicationFactory ):

public class FlowApplicationFactory extends ApplicationFactory {

    private final ApplicationFactory wrapped;
    private volatile Application application;

    public FlowApplicationFactory(ApplicationFactory wrapped) {
        this.wrapped = wrapped;
    }

    @Override
    public Application getApplication() {
        return (application == null) ? createFlowApplication(wrapped.getApplication()) : application;
    }

    @Override
    public synchronized void setApplication(Application application) {
        wrapped.setApplication(createFlowApplication(application));
    }

    private Application createFlowApplication(final Application application) {
        Application newApplication = application;

        while (!(newApplication instanceof FlowApplication) && newApplication instanceof SeamApplication) {
            newApplication = ((SeamApplication) application).getDelegate();
        }

        if (!(newApplication instanceof FlowApplication)) {
            newApplication =  new FlowApplication(application);
        }

        return (this.application = newApplication);
    }

}

因此,在创建 FlowApplication 时,它将首先检查包装的应用程序(如果之前尚未创建),如果已创建,则重新使用它。

请注意 SeamApplication依赖很尴尬,但这只是为了修复它。 JSF2 通过新的 ApplicationWrapper 使它变得更容易您可以使用的类而不是 SeamApplicationcreateFlowApplication() block 。

如果这一切仍然不起作用,那么可能是 SeamApplicationFactoryFlowApplicationFactory 之后 初始化.您可以通过显式重新声明 <application-factory> 来强制排序webapp 自己的条目 faces-config.xml按所需顺序(修复错误的作为最后一个):

<factory>
    <application-factory>org.jboss.seam.jsf.SeamApplicationFactory</application-factory>
    <application-factory>org.springframework.faces.webflow.FlowApplicationFactory</application-factory>
</factory>

否则,您可能希望对 SeamApplicationFactory 执行与上述相同的操作(显然在代码中交换了 FlowApplicationSeamApplication)。

关于jsf - Seam/Spring WebFlow 应用程序中的 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25330662/

相关文章:

jsf - 如何在 Bootsfaces 数据表列中显示图像

java - 如何在没有 setter 的情况下绑定(bind)请求参数?

java - JSF 国际化 f :loadbundle or through faces-config: Performance point

java - JSF 面板定位

java - ConstraintViolationException : Validation failed for classes [. ...entities.WalletInfo] 在坚持期间

java - Spring @Controller 调用 @Async 方法,然后在返回的 Future 上调用 get()...代码味道?

java - Hibernate 原生查询 - char(3) 列

java - Seam 导出 Excel 格式的数据表

jboss - 丰富:fileUpload is not working in jboss-6. 0.0.Final

jsf - 在 JSF 2.0 中动态创建输入字段并将其链接到支持 bean