Fix JSF < 2.1 compatibility issue

Issue: SWF-1622
This commit is contained in:
Rossen Stoyanchev
2014-05-22 16:04:49 -04:00
parent 103829c2ca
commit 3d8330f1cb
3 changed files with 38 additions and 47 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,7 +15,6 @@
*/
package org.springframework.faces.webflow;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.Map;
@@ -27,12 +26,7 @@ import javax.faces.application.Resource;
import javax.faces.application.ResourceHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.Behavior;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
@@ -44,8 +38,6 @@ import javax.faces.event.SystemEventListener;
*/
public class Jsf2FlowApplication extends FlowApplication {
private static String SKIP_ITERATION_HINT = "javax.faces.visit.SKIP_ITERATION";
public Jsf2FlowApplication(Application delegate) {
super(delegate);
}
@@ -124,21 +116,4 @@ public class Jsf2FlowApplication extends FlowApplication {
getDelegate().unsubscribeFromEvent(systemEventClass, listener);
}
// Ideally this method should be in JsfView
// We keep it here to avoid ClassNotFoundExceptions for JSF 1.2 apps
static void publishPostRestoreStateEvent() {
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
try {
facesContext.getAttributes().put(SKIP_ITERATION_HINT, true);
VisitContext visitContext = VisitContext.createVisitContext(facesContext, null, EnumSet.of(VisitHint.SKIP_ITERATION));
facesContext.getViewRoot().visitTree(visitContext,
new PostRestoreStateEventVisitCallback());
} catch (AbortProcessingException e) {
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, facesContext.getCurrentPhaseId()));
} finally {
facesContext.getAttributes().remove(SKIP_ITERATION_HINT);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,15 +15,12 @@
*/
package org.springframework.faces.webflow;
import java.lang.reflect.Method;
import javax.faces.context.FacesContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.lifecycle.Lifecycle;
import org.springframework.util.ReflectionUtils;
import org.springframework.webflow.execution.RequestContextHolder;
/**
@@ -69,18 +66,4 @@ public class JsfUtils {
}
}
// This method is here for JSF 1.2 backwards compatibility
static void publishPostRestoreStateEvent() {
try {
Class<?> clazz = Class.forName("org.springframework.faces.webflow.Jsf2FlowApplication");
Method method = ReflectionUtils.findMethod(clazz, "publishPostRestoreStateEvent");
ReflectionUtils.makeAccessible(method);
ReflectionUtils.invokeMethod(method, null);
} catch (ClassNotFoundException ex) {
throw new IllegalStateException("Expected Jsf2FlowApplication: " + ex);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2008 the original author or authors.
* Copyright 2004-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -19,14 +19,20 @@ import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJ
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf20;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isPortletRequest;
import java.util.EnumSet;
import java.util.Iterator;
import javax.faces.application.ViewHandler;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.UIViewRoot;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitHint;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseId;
import javax.faces.lifecycle.Lifecycle;
import javax.servlet.ServletContext;
@@ -128,8 +134,8 @@ public class JsfViewFactory implements ViewFactory {
view = createJsfView(viewRoot, lifecycle, context);
}
}
if (isAtLeastJsf20()) {
JsfUtils.publishPostRestoreStateEvent();
if (JsfRuntimeInformation.isAtLeastJsf20()) {
new PostRestoreStateEvenHelper().publishPostRestoreStateEvent();
}
if (!facesContext.getRenderResponse()) {
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext);
@@ -186,4 +192,31 @@ public class JsfViewFactory implements ViewFactory {
}
}
private static class PostRestoreStateEvenHelper {
public void publishPostRestoreStateEvent() {
VisitHint visitHint = null;
try {
visitHint = Enum.valueOf(VisitHint.class, "SKIP_ITERATION");
}
catch (IllegalArgumentException ex) {
// JSF < 2.1
}
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
try {
facesContext.getAttributes().put("javax.faces.visit.SKIP_ITERATION", true);
VisitContext visitContext = (visitHint != null ?
VisitContext.createVisitContext(facesContext, null, EnumSet.of(visitHint)) :
VisitContext.createVisitContext(facesContext));
facesContext.getViewRoot().visitTree(visitContext, new PostRestoreStateEventVisitCallback());
} catch (AbortProcessingException e) {
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, facesContext.getCurrentPhaseId()));
} finally {
facesContext.getAttributes().remove("javax.faces.visit.SKIP_ITERATION");
}
}
}
}