StackOverflowError dans L'Application Seam / Spring WebFlow
nous sommes en train de remplacer progressivement les composants de joint par ressort-MVC et ressort-Webflow.
Running JMeter-tests les journaux sont encombrés de StackOverFlowErrors après une couple d'heures:
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)
ainsi la méthode getMessageBundle est appelée par deux instances: SeamApplication et FlowApplication.
en regardant le javax.face.application.Classe d'Application il est écrit:
" parce que cette instance est partagé, il doit être mis en œuvre d'une manière sûre."
peut-être que les deux instances de l'application essaient d'accéder au même paquet qui cause des conditions de course?
EDIT: Après que l'application n'ait plus répondu, Nous avons redémarré le serveur et maintenant l'erreur apparaît dans un autre endroit:
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)
Les 2 dernières lignes sont répétées des milliers de fois dans le fichier journal.
nous travaillons avec les suivants component-versions:
JSF-1.2
Couture-2.2.0
Spring WebFlow 2.3.4
printemps MVC 3.0.5
mettre à jour l'un des composants n'est pas une option.
1 réponses
les deux SeamApplication
et FlowApplication
présentent des anomalies quant à la délégation appropriée à l'application enveloppée. Une façon de le réparer est par l'intermédiaire de la FlowApplicationFactory
.
prenez D'abord son code source brut et déposez-le dans le dossier Java source de votre projet webapp, en maintenant son paquet original. Vous n'avez pas nécessairement besoin de manipuler des pots. Classes dans /WEB-INF/classes
ont une priorité de chargement supérieure à celles des bocaux.
puis manipuler la classe comme suit (basé sur 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);
}
}
ainsi, lors de la création de FlowApplication
, il inspectera d'abord les applications enveloppées si elle n'est pas déjà créée avant et si oui, puis la réutiliser à la place.
notez que la dépendance SeamApplication
est un peu étrange, mais c'est juste pour correction. JSF2 a rendu plus facile par la nouvelle classe ApplicationWrapper
que vous pourriez utiliser au lieu de SeamApplication
dans le bloc createFlowApplication()
.
si tout cela ne fonctionne toujours pas, alors peut-être que le SeamApplicationFactory
est initialisé après le FlowApplicationFactory
. Vous pouvez forcer l'ordre en sélectionnant explicitement les entrées <application-factory>
dans le propre faces-config.xml
de webapp dans l'ordre désiré (le erreurs un dernier):
<factory>
<application-factory>org.jboss.seam.jsf.SeamApplicationFactory</application-factory>
<application-factory>org.springframework.faces.webflow.FlowApplicationFactory</application-factory>
</factory>
sinon, vous pourriez vouloir faire la même chose que ci-dessus pour SeamApplicationFactory
(évidemment avec FlowApplication
et SeamApplication
échangés dans le code).