首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >StackOverflowError在Seam / Spring WebFlow中的应用

StackOverflowError在Seam / Spring WebFlow中的应用
EN

Stack Overflow用户
提问于 2014-08-15 16:51:58
回答 1查看 650关注 0票数 3

我们正在逐步用Spring和Spring取代Seam组件。

运行JMeter-几个小时后,日志就会被StackOverFlowErrors弄得乱七八糟:

代码语言:javascript
复制
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类,它说:

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

也许这两个应用程序实例试图访问相同的包,这会导致竞争条件?

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

代码语言:javascript
复制
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)

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

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

JSF-1.2

Seam-2.2.0

春季WebFlow 2.3.4

Spring 3.0.5

更新任何组件都不是一个选项。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-08-19 08:29:54

SeamApplicationFlowApplication在正确委托包装的应用程序方面都有错误。修复它的一种方法是通过FlowApplicationFactory

首先获取它的原始源代码并将其放到webapp项目的Java文件夹中,维护它的原始包。你不一定需要操纵罐子。/WEB-INF/classes中的类比JAR中的类具有更高的类加载优先级。

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

代码语言:javascript
复制
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类使它更容易使用,您可以在createFlowApplication()块中使用它而不是SeamApplication

如果这一切仍然不起作用,那么也许SeamApplicationFactory是在 FlowApplicationFactory之后初始化的。您可以强制排序,方法是按照所需的顺序显式地重新声明webapp自己的faces-config.xml中的faces-config.xml条目( by固定为最后一个):

代码语言:javascript
复制
<factory>
    <application-factory>org.jboss.seam.jsf.SeamApplicationFactory</application-factory>
    <application-factory>org.springframework.faces.webflow.FlowApplicationFactory</application-factory>
</factory>

否则,您可能希望对SeamApplicationFactory (显然是使用代码中交换的FlowApplicationSeamApplication )执行上述操作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/25330662

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档