diff --git a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java index 255ac393..a5713e15 100644 --- a/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java +++ b/spring-faces/src/main/java/org/springframework/faces/webflow/JsfView.java @@ -58,19 +58,6 @@ public class JsfView implements View { this.context = context; } - public boolean eventSignaled() { - return context.getExternalContext().getRequestMap().contains(EVENT_KEY); - } - - public Event getEvent() { - String eventId = (String) context.getExternalContext().getRequestMap().get(EVENT_KEY); - return new Event(this, eventId); - } - - public UIViewRoot getViewRoot() { - return this.viewRoot; - } - /** * This implementation performs the standard duties of the JSF RENDER_RESPONSE phase. */ @@ -92,6 +79,23 @@ public class JsfView implements View { } } + public void postback() { + // TODO - implement Postback JSF lifecycle + } + + public boolean eventSignaled() { + return context.getExternalContext().getRequestMap().contains(EVENT_KEY); + } + + public Event getEvent() { + String eventId = (String) context.getExternalContext().getRequestMap().get(EVENT_KEY); + return new Event(this, eventId); + } + + public UIViewRoot getViewRoot() { + return this.viewRoot; + } + public String toString() { return "[JSFView = '" + viewId + "']"; } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java index b09253d1..bcfbd803 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/ViewState.java @@ -175,6 +175,7 @@ public class ViewState extends TransitionableState { public void resume(RequestControlContext context) { restoreVariables(context); View view = viewFactory.getView(context); + view.postback(); if (view.eventSignaled()) { Event event = view.getEvent(); if (logger.isDebugEnabled()) { diff --git a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java index 74feb5bc..46a59e4f 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/engine/builder/support/ActionExecutingViewFactory.java @@ -60,6 +60,16 @@ public class ActionExecutingViewFactory implements ViewFactory { this.context = context; } + public void render() { + if (action != null) { + ActionExecutor.execute(action, context); + } + } + + public void postback() { + + } + public boolean eventSignaled() { return context.getExternalContext().getRequestParameterMap().contains("_eventId"); } @@ -68,11 +78,5 @@ public class ActionExecutingViewFactory implements ViewFactory { return new Event(this, context.getExternalContext().getRequestParameterMap().get("_eventId")); } - public void render() { - if (action != null) { - ActionExecutor.execute(action, context); - } - } - } } \ No newline at end of file diff --git a/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java b/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java index 1b3d43a9..c81117f4 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/execution/View.java @@ -38,14 +38,20 @@ public interface View { public void render() throws IOException; /** - * Was a user event signaled on this view in this request? + * Execute the view postback lifecycle. This typically results in a view model binding and validation. + */ + public void postback(); + + /** + * Returns true if an event occurred the flow system should handle. * @return true if yes, false otherwise */ public boolean eventSignaled(); /** - * Get the user event signaled on this view in this request. - * @return the user event + * Get the user event the flow should handle. Returns an event object when {@link #eventSignaled()} returns true. + * Returns null otherwise + * @return the event, or null if there is no event for the flow system to handle */ public Event getEvent(); diff --git a/spring-webflow/src/main/java/org/springframework/webflow/mvc/MvcViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/mvc/MvcViewFactoryCreator.java index 05835fd3..5a48c174 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/mvc/MvcViewFactoryCreator.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/mvc/MvcViewFactoryCreator.java @@ -24,13 +24,16 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.binding.expression.Expression; +import org.springframework.binding.expression.ExpressionParser; +import org.springframework.binding.format.FormatterRegistry; +import org.springframework.binding.mapping.MappingResults; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextAware; import org.springframework.context.i18n.LocaleContextHolder; import org.springframework.core.io.ContextResource; import org.springframework.core.io.ResourceLoader; -import org.springframework.security.context.SecurityContextHolder; import org.springframework.util.ClassUtils; +import org.springframework.validation.BindingResult; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.view.InternalResourceView; import org.springframework.web.servlet.view.JstlView; @@ -57,8 +60,11 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon private static final boolean jstlPresent = ClassUtils.isPresent("javax.servlet.jsp.jstl.fmt.LocalizationContext"); - private static final boolean springSecurityPresent = ClassUtils - .isPresent("org.springframework.security.context.SecurityContextHolder"); + // TODO + private ExpressionParser expressionParser; + + // TODO + private FormatterRegistry formatterRegistry; private List viewResolvers; @@ -187,6 +193,27 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon this.context = context; } + public void render() { + Map model = new HashMap(); + model.putAll(context.getConversationScope().union(context.getFlowScope()).union(context.getFlashScope()) + .union(context.getRequestScope()).asMap()); + exposeBindingModel(model); + model.put("flowRequestContext", context); + model.put("flowExecutionKey", context.getFlowExecutionContext().getKey().toString()); + model.put("flowExecutionUrl", context.getFlowExecutionUrl()); + model.put("currentUser", context.getExternalContext().getCurrentUser()); + try { + view.render(model, (HttpServletRequest) context.getExternalContext().getNativeRequest(), + (HttpServletResponse) context.getExternalContext().getNativeResponse()); + } catch (Exception e) { + throw new IllegalStateException("Exception rendering view", e); + } + } + + public void postback() { + // TODO implement me with real data binding behavior + } + public boolean eventSignaled() { determineEventId(context); return eventId != null; @@ -196,21 +223,16 @@ public class MvcViewFactoryCreator implements ViewFactoryCreator, ApplicationCon return new Event(this, eventId, context.getRequestParameters().asAttributeMap()); } - public void render() { - Map model = new HashMap(); - model.putAll(context.getConversationScope().union(context.getFlowScope()).union(context.getFlashScope()) - .union(context.getRequestScope()).asMap()); - model.put("flowRequestContext", context); - model.put("flowExecutionKey", context.getFlowExecutionContext().getKey().toString()); - model.put("flowExecutionUrl", context.getFlowExecutionUrl()); - if (springSecurityPresent && !model.containsKey("currentUser")) { - model.put("currentUser", SecurityContextHolder.getContext().getAuthentication()); - } - try { - view.render(model, (HttpServletRequest) context.getExternalContext().getNativeRequest(), - (HttpServletResponse) context.getExternalContext().getNativeResponse()); - } catch (Exception e) { - throw new IllegalStateException("Exception rendering view", e); + private void exposeBindingModel(Map model) { + Expression boundObjectExpr = (Expression) context.getCurrentState().getAttributes().get("model"); + if (boundObjectExpr != null) { + Object boundObject = boundObjectExpr.getValue(context); + // TODO + BindingModel bindingModel = new BindingModel(boundObject, null, null, context.getMessageContext()); + MappingResults bindResults = (MappingResults) context.getRequestScope().get( + boundObjectExpr.getExpressionString() + "MappingResults"); + bindingModel.setMappingResults(bindResults); + model.put(BindingResult.MODEL_KEY_PREFIX + boundObjectExpr.getExpressionString(), model); } } diff --git a/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java b/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java index afd1f0aa..27913f23 100644 --- a/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java +++ b/spring-webflow/src/main/java/org/springframework/webflow/test/MockViewFactoryCreator.java @@ -100,6 +100,10 @@ class MockViewFactoryCreator implements ViewFactoryCreator { return context.getRequestParameters().contains("_eventId"); } + public void postback() { + // TODO - implement me as appropriate for a test environment + } + public Event getEvent() { return new Event(this, context.getRequestParameters().get("_eventId")); } diff --git a/spring-webflow/src/test/java/org/springframework/webflow/engine/StubViewFactory.java b/spring-webflow/src/test/java/org/springframework/webflow/engine/StubViewFactory.java index d22962d1..92cfd813 100644 --- a/spring-webflow/src/test/java/org/springframework/webflow/engine/StubViewFactory.java +++ b/spring-webflow/src/test/java/org/springframework/webflow/engine/StubViewFactory.java @@ -37,6 +37,10 @@ public class StubViewFactory implements ViewFactory { context.getFlowScope().put("renderCalled", Boolean.TRUE); } + public void postback() { + + } + public boolean eventSignaled() { return context.getExternalContext().getRequestParameterMap().contains("_eventId"); }