Merge branch '2.3.x'

This commit is contained in:
Rossen Stoyanchev
2012-03-27 18:01:31 -04:00
89 changed files with 821 additions and 1013 deletions

View File

@@ -8,8 +8,8 @@
<classpathentry combineaccessrules="false" kind="src" path="/spring-js"/>
<classpathentry combineaccessrules="false" kind="src" path="/spring-webflow"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="var" path="IVY_CACHE/com.sun.faces/jsf-impl/2.0.3/jsf-impl-2.0.3.jar" sourcepath="/IVY_CACHE/com.sun.faces/jsf-impl/2.0.3/jsf-impl-2.0.3-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.sun.faces/jsf-api/2.0.3/jsf-api-2.0.3.jar" sourcepath="/IVY_CACHE/com.sun.faces/jsf-api/2.0.3/jsf-api-2.0.3-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.sun.faces/jsf-impl/2.1.7/jsf-impl-2.1.7.jar" sourcepath="/IVY_CACHE/com.sun.faces/jsf-impl/2.1.7/jsf-impl-2.1.7-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.sun.faces/jsf-api/2.1.7/jsf-api-2.1.7.jar" sourcepath="/IVY_CACHE/com.sun.faces/jsf-api/2.1.7/jsf-api-2.1.7-sources.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-1.0.0.jar" sourcepath="IVY_CACHE/javax.el/com.springsource.javax.el/1.0.0/com.springsource.javax.el-sources-1.0.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.4.0/com.springsource.javax.servlet-2.4.0.jar" sourcepath="/IVY_CACHE/javax.servlet/com.springsource.javax.servlet/2.4.0/com.springsource.javax.servlet-sources-2.4.0.jar"/>
<classpathentry kind="var" path="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-2.0.0.jar" sourcepath="IVY_CACHE/javax.portlet/com.springsource.javax.portlet/2.0.0/com.springsource.javax.portlet-sources-2.0.0.jar"/>
@@ -23,13 +23,13 @@
<classpathentry kind="var" path="IVY_CACHE/org.jboss.el/com.springsource.org.jboss.el/2.0.0.GA/com.springsource.org.jboss.el-2.0.0.GA.jar" sourcepath="IVY_CACHE/org.jboss.el/com.springsource.org.jboss.el/2.0.0.GA/com.springsource.org.jboss.el-sources-2.0.0.GA.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-3.8.2.jar" sourcepath="IVY_CACHE/org.junit/com.springsource.junit/3.8.2/com.springsource.junit-sources-3.8.2.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.richfaces/com.springsource.org.richfaces/3.1.4.GA/com.springsource.org.richfaces-3.1.4.GA.jar" sourcepath="/IVY_CACHE/org.richfaces/com.springsource.org.richfaces/3.1.4.GA/com.springsource.org.richfaces-sources-3.1.4.GA.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.beans/3.0.5.RELEASE/org.springframework.beans-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.beans/3.0.5.RELEASE/org.springframework.beans-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.context/3.0.5.RELEASE/org.springframework.context-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.context/3.0.5.RELEASE/org.springframework.context-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.core/3.0.5.RELEASE/org.springframework.core-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.core/3.0.5.RELEASE/org.springframework.core-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.expression/3.0.5.RELEASE/org.springframework.expression-3.0.5.RELEASE.jar" sourcepath="/IVY_CACHE/org.springframework/org.springframework.expression/3.0.5.RELEASE/org.springframework.expression-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.test/3.0.5.RELEASE/org.springframework.test-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.test/3.0.5.RELEASE/org.springframework.test-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.web/3.0.5.RELEASE/org.springframework.web-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.web/3.0.5.RELEASE/org.springframework.web-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.web.servlet/3.0.5.RELEASE/org.springframework.web.servlet-3.0.5.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.web.servlet/3.0.5.RELEASE/org.springframework.web.servlet-sources-3.0.5.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.beans/3.1.1.RELEASE/org.springframework.beans-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.beans/3.1.1.RELEASE/org.springframework.beans-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.context/3.1.1.RELEASE/org.springframework.context-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.context/3.1.1.RELEASE/org.springframework.context-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.core/3.1.1.RELEASE/org.springframework.core-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.core/3.1.1.RELEASE/org.springframework.core-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.expression/3.1.1.RELEASE/org.springframework.expression-3.1.1.RELEASE.jar" sourcepath="/IVY_CACHE/org.springframework/org.springframework.expression/3.1.1.RELEASE/org.springframework.expression-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.test/3.1.1.RELEASE/org.springframework.test-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.test/3.1.1.RELEASE/org.springframework.test-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.web/3.1.1.RELEASE/org.springframework.web-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.web/3.1.1.RELEASE/org.springframework.web-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework/org.springframework.web.servlet/3.1.1.RELEASE/org.springframework.web.servlet-3.1.1.RELEASE.jar" sourcepath="IVY_CACHE/org.springframework/org.springframework.web.servlet/3.1.1.RELEASE/org.springframework.web.servlet-sources-3.1.1.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework.security/org.springframework.security.core/3.0.2.RELEASE/org.springframework.security.core-3.0.2.RELEASE.jar" sourcepath="/IVY_CACHE/org.springframework.security/org.springframework.security.core/3.0.2.RELEASE/org.springframework.security.core-sources-3.0.2.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/org.springframework.security/org.springframework.security.web/3.0.2.RELEASE/org.springframework.security.web-3.0.2.RELEASE.jar" sourcepath="/IVY_CACHE/org.springframework.security/org.springframework.security.web/3.0.2.RELEASE/org.springframework.security.web-sources-3.0.2.RELEASE.jar"/>
<classpathentry kind="var" path="IVY_CACHE/com.sun.facelets/com.springsource.com.sun.facelets/1.1.14/com.springsource.com.sun.facelets-1.1.14.jar" sourcepath="/IVY_CACHE/com.sun.facelets/com.springsource.com.sun.facelets/1.1.14/com.springsource.com.sun.facelets-sources-1.1.14.jar"/>

View File

@@ -11,6 +11,7 @@
<configurations>
<include file="${spring.build.dir}/common/default-ivy-configurations.xml"/>
<conf name="mojarra21" visibility="public"/>
<conf name="mojarra20" visibility="public"/>
<conf name="myfaces20" visibility="public"/>
<conf name="mojarra12" visibility="public"/>
@@ -31,22 +32,26 @@
<dependency org="javax.portlet" name="com.springsource.javax.portlet" rev="2.0.0" conf="provided->runtime" />
<dependency org="org.apache.commons" name="com.springsource.org.apache.commons.logging" rev="1.1.1" conf="compile->runtime"/>
<dependency org="org.richfaces" name="com.springsource.org.richfaces" rev="3.1.4.GA" conf="optional->runtime" />
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.5.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.5.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.5.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.5.RELEASE" conf="compile->runtime" />
<dependency org="org.springframework" name="org.springframework.web" rev="3.0.5.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.web.portlet" rev="3.0.5.RELEASE" conf="optional->runtime" />
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="3.0.5.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.beans" rev="3.1.1.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.context" rev="3.1.1.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.core" rev="3.1.1.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.expression" rev="3.1.1.RELEASE" conf="compile->runtime" />
<dependency org="org.springframework" name="org.springframework.web" rev="3.1.1.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.web.portlet" rev="3.1.1.RELEASE" conf="optional->runtime" />
<dependency org="org.springframework" name="org.springframework.web.servlet" rev="3.1.1.RELEASE" conf="compile->runtime"/>
<dependency org="org.springframework.security" name="org.springframework.security.core" rev="3.0.2.RELEASE" conf="optional->runtime" />
<dependency org="org.springframework.security" name="org.springframework.security.web" rev="3.0.2.RELEASE" conf="optional->runtime" />
<dependency org="org.springframework.webflow" name="org.springframework.binding" rev="latest.integration" conf="compile->runtime"/>
<dependency org="org.springframework.webflow" name="org.springframework.js" rev="latest.integration" conf="compile->runtime"/>
<dependency org="org.springframework.webflow" name="org.springframework.webflow" rev="latest.integration" conf="compile->runtime"/>
<!-- JSF 2.1 Mojarra dependencies -->
<dependency org="com.sun.faces" name="jsf-api" rev="2.1.7" conf="provided, mojarra21->default" />
<dependency org="com.sun.faces" name="jsf-impl" rev="2.1.7" conf="provided, mojarra21->default" />
<!-- JSF 2.0 Mojarra dependencies -->
<dependency org="com.sun.faces" name="jsf-api" rev="2.0.3" conf="provided, mojarra20->default" />
<dependency org="com.sun.faces" name="jsf-impl" rev="2.0.3" conf="provided, mojarra20->default" />
<dependency org="com.sun.faces" name="jsf-api" rev="2.0.6" conf="provided, mojarra20->default" />
<dependency org="com.sun.faces" name="jsf-impl" rev="2.0.6" conf="provided, mojarra20->default" />
<!-- JSF 2.0 MyFaces dependencies -->
<dependency org="org.apache.myfaces.core" name="myfaces-api" rev="2.0.1-SNAPSHOT" conf="myfaces20->default" />
@@ -70,7 +75,7 @@
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.5.2" conf="test->runtime" />
<dependency org="org.junit" name="com.springsource.junit" rev="3.8.2" conf="test->runtime" />
<dependency org="org.jboss.el" name="com.springsource.org.jboss.el" rev="2.0.0.GA" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.test" rev="3.0.5.RELEASE" conf="test->runtime" />
<dependency org="org.springframework" name="org.springframework.test" rev="3.1.1.RELEASE" conf="test->runtime" />
</dependencies>

View File

@@ -108,13 +108,13 @@
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-api</artifactId>
<version>2.0.3</version>
<version>2.1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.sun.faces</groupId>
<artifactId>jsf-impl</artifactId>
<version>2.0.3</version>
<version>2.1.7</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -216,6 +216,6 @@
</testResources>
</build>
<properties>
<spring.version>3.0.5.RELEASE</spring.version>
<spring.version>3.1.1.RELEASE</spring.version>
</properties>
</project>

View File

@@ -61,6 +61,13 @@ public class FlowFacesContextMessageDelegate {
this.context = context;
}
/**
* Whether Web Flow's MessageContext contains any errors.
*/
public boolean hasErrorMessages() {
return context.getMessageContext().hasErrorMessages();
}
/**
* @see FlowFacesContext#addMessage(String, FacesMessage)
*/

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2011 the original author or authors.
* Copyright 2004-2012 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,6 +15,7 @@
*/
package org.springframework.faces.webflow;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -55,7 +56,7 @@ public class FlowPartialViewContext extends PartialViewContextWrapper {
RequestContext requestContext = RequestContextHolder.getRequestContext();
String[] fragmentIds = (String[]) requestContext.getFlashScope().get(View.RENDER_FRAGMENTS_ATTRIBUTE);
if (fragmentIds != null && fragmentIds.length > 0) {
return Arrays.asList(fragmentIds);
return new ArrayList<String>(Arrays.asList(fragmentIds));
}
}
return getWrapped().getRenderIds();

View File

@@ -26,7 +26,11 @@ 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.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;
@@ -116,4 +120,17 @@ 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.getViewRoot().visitTree(VisitContext.createVisitContext(facesContext),
new PostRestoreStateEventVisitCallback());
} catch (AbortProcessingException e) {
facesContext.getApplication().publishEvent(facesContext, ExceptionQueuedEvent.class,
new ExceptionQueuedEventContext(facesContext, e, null, facesContext.getCurrentPhaseId()));
}
}
}

View File

@@ -112,7 +112,11 @@ public class Jsf2FlowFacesContext extends FlowFacesContext {
}
public boolean isValidationFailed() {
return getDelegate().isValidationFailed();
if (getMessageDelegate().hasErrorMessages()) {
return true;
} else {
return getDelegate().isValidationFailed();
}
}
public void setExceptionHandler(ExceptionHandler exceptionHandler) {
@@ -127,6 +131,12 @@ public class Jsf2FlowFacesContext extends FlowFacesContext {
getDelegate().validationFailed();
}
// --------------- JSF 2.1 Pass-through delegate methods ------------------//
public boolean isReleased() {
return getDelegate().isReleased();
}
protected class Jsf2FlowExternalContext extends FlowExternalContext {
Log logger = LogFactory.getLog(FlowExternalContext.class);
@@ -242,5 +252,18 @@ public class Jsf2FlowFacesContext extends FlowFacesContext {
return delegate.encodePartialActionURL(url);
}
// --------------- JSF 2.1 Pass-through delegate methods ------------------//
public int getSessionMaxInactiveInterval() {
return delegate.getSessionMaxInactiveInterval();
}
public boolean isSecure() {
return delegate.isSecure();
}
public void setSessionMaxInactiveInterval(int interval) {
delegate.setSessionMaxInactiveInterval(interval);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2004-2010 the original author or authors.
* Copyright 2004-2012 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.
@@ -50,8 +50,14 @@ public class JsfAjaxHandler extends AbstractAjaxHandler {
}
protected boolean isAjaxRequestInternal(HttpServletRequest request, HttpServletResponse response) {
String facesRequestHeader = request.getHeader("Faces-Request");
return ("partial/ajax".equals(facesRequestHeader)) ? true : false;
FacesContext facesContext = FlowFacesContext.getCurrentInstance();
if (facesContext != null) {
return facesContext.getPartialViewContext().isAjaxRequest();
} else {
String header = request.getHeader("Faces-Request");
String param = request.getParameter("javax.faces.partial.ajax");
return ("partial/ajax".equals(header) || "true".equals(param)) ? true : false;
}
}
protected void sendAjaxRedirectInternal(final String targetUrl, final HttpServletRequest request,

View File

@@ -15,12 +15,15 @@
*/
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;
/**
@@ -66,4 +69,18 @@ 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

@@ -16,7 +16,6 @@
package org.springframework.faces.webflow;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isAtLeastJsf12;
import static org.springframework.faces.webflow.JsfRuntimeInformation.isLessThanJsf20;
import java.io.IOException;
import java.io.Serializable;
@@ -137,17 +136,8 @@ public class JsfView implements View {
}
public Serializable getUserEventState() {
if (isLessThanJsf20()) {
// Set the temporary UIViewRoot state so that it will be available across the redirect
return new ViewRootHolder(getViewRoot());
} else {
// In JSF 2 the partial state saving algorithm attaches a system event listener to the UIViewRoot which
// holds on to a reference to the FacesContext instance. The FacesContext instance is released at end of
// each request. Hence, keeping the UIViewRoot across the redirect is not feasible.
// @see com.sun.faces.context.StateContext$AddRemoveListener
logger.debug("User event state requested but not saved.");
return null;
}
// Set the temporary UIViewRoot state so that it will be available across the redirect
return new ViewRootHolder(getViewRoot());
}
public boolean hasFlowEvent() {

View File

@@ -128,6 +128,9 @@ public class JsfViewFactory implements ViewFactory {
view = createJsfView(viewRoot, lifecycle, context);
}
}
if (isAtLeastJsf20()) {
JsfUtils.publishPostRestoreStateEvent();
}
if (!facesContext.getRenderResponse()) {
JsfUtils.notifyAfterListeners(PhaseId.RESTORE_VIEW, lifecycle, facesContext);
}
@@ -182,4 +185,5 @@ public class JsfViewFactory implements ViewFactory {
processTree(context, child);
}
}
}

View File

@@ -0,0 +1,28 @@
package org.springframework.faces.webflow;
import javax.faces.component.UIComponent;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.component.visit.VisitResult;
import javax.faces.event.PostRestoreStateEvent;
/**
* A VisitCallback used to deliver a PostRestoreStataEvent similar to
* {@code RestoreViewPhase.deliverPostRestoreStateEvent(..)} in Sun's JSF.
*
* @since 2.3.1
*/
class PostRestoreStateEventVisitCallback implements VisitCallback {
private PostRestoreStateEvent event;
public VisitResult visit(VisitContext context, UIComponent target) {
if (this.event == null) {
this.event = new PostRestoreStateEvent(target);
} else {
this.event.setComponent(target);
}
target.processEvent(event);
return VisitResult.ACCEPT;
}
}

View File

@@ -27,15 +27,17 @@ public class FlowFacesContextTests extends TestCase {
FacesContext facesContext;
RequestContext requestContext = (RequestContext) EasyMock.createMock(RequestContext.class);
RequestContext requestContext;
MessageContext messageContext;
MessageContext prepopulatedMessageContext;
@SuppressWarnings("cast")
protected void setUp() throws Exception {
jsf.setUp();
facesContext = new FlowFacesContext(requestContext, jsf.facesContext());
requestContext = (RequestContext) EasyMock.createMock(RequestContext.class);
facesContext = new Jsf2FlowFacesContext(requestContext, jsf.facesContext());
setupMessageContext();
}
@@ -60,7 +62,6 @@ public class FlowFacesContextTests extends TestCase {
assertEquals("foo", summaryMessage.getText());
Message detailMessage = messageContext.getMessagesBySource("foo_detail")[0];
assertEquals("bar", detailMessage.getText());
}
public final void testGetGlobalMessagesOnly() {
@@ -262,6 +263,16 @@ public class FlowFacesContextTests extends TestCase {
assertSame(facesContext, facesContext.getELContext().getContext(FacesContext.class));
}
public final void testValidationFailed() {
messageContext = new DefaultMessageContext();
EasyMock.expect(requestContext.getMessageContext()).andStubReturn(messageContext);
EasyMock.replay(new Object[] { requestContext });
facesContext.addMessage("foo", new FacesMessage(FacesMessage.SEVERITY_ERROR, "foo", "bar"));
assertEquals(true, facesContext.isValidationFailed());
}
private void setupMessageContext() {
prepopulatedMessageContext = new DefaultMessageContext();
prepopulatedMessageContext.addMessage(new MessageBuilder().source("null_summary").defaultText("foo").info()

View File

@@ -16,6 +16,7 @@ import org.springframework.webflow.test.MockRequestContext;
public class FlowPartialViewContextTests extends TestCase {
@SuppressWarnings("unchecked")
public void testReturnFragmentIds() throws Exception {
String[] fragmentIds = new String[] { "foo", "bar" };
@@ -46,4 +47,18 @@ public class FlowPartialViewContextTests extends TestCase {
assertEquals(renderIds, context.getRenderIds());
}
@SuppressWarnings("unchecked")
public void testReturnFragmentIdsMutable() throws Exception {
String[] fragmentIds = new String[] { "foo", "bar" };
RequestContext requestContext = new MockRequestContext();
requestContext.getFlashScope().asMap().put(View.RENDER_FRAGMENTS_ATTRIBUTE, fragmentIds);
RequestContextHolder.setRequestContext(requestContext);
Collection<String> renderIds = new FlowPartialViewContext(null).getRenderIds();
renderIds.add("baz");
assertEquals(Arrays.asList("foo", "bar", "baz"), renderIds);
}
}

View File

@@ -28,13 +28,14 @@ import org.apache.myfaces.test.mock.MockServletConfig;
import org.apache.myfaces.test.mock.MockServletContext;
import org.apache.myfaces.test.mock.lifecycle.MockLifecycle;
import org.apache.myfaces.test.mock.lifecycle.MockLifecycleFactory;
import org.apache.myfaces.test.mock.visit.MockVisitContextFactory;
/**
* Helper for using the mock JSF environment provided by shale-test inside unit tests that do not extend
* {@link AbstractJsfTestCase}
*
* @author Jeremy Grelle
* @author Phil Webb
* @author Phillip Webb
*/
public class JSFMockHelper {
@@ -113,6 +114,11 @@ public class JSFMockHelper {
public void setUp() throws Exception {
// Ensure no pre-existing FacesContext ..
if (FacesContext.getCurrentInstance() != null) {
FacesContext.getCurrentInstance().release();
}
// Set up a new thread context class loader
threadContextClassLoader = Thread.currentThread().getContextClassLoader();
Thread.currentThread().setContextClassLoader(
@@ -132,8 +138,9 @@ public class JSFMockHelper {
FactoryFinder.setFactory(FactoryFinder.FACES_CONTEXT_FACTORY, MockBaseFacesContextFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.LIFECYCLE_FACTORY, MockLifecycleFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.RENDER_KIT_FACTORY, MockRenderKitFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY, MockPartialViewContextFactory.class
.getName());
FactoryFinder.setFactory(FactoryFinder.PARTIAL_VIEW_CONTEXT_FACTORY,
MockPartialViewContextFactory.class.getName());
FactoryFinder.setFactory(FactoryFinder.VISIT_CONTEXT_FACTORY, MockVisitContextFactory.class.getName());
lifecycleFactory = (MockLifecycleFactory) FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
lifecycle = (MockLifecycle) lifecycleFactory.getLifecycle(LifecycleFactory.DEFAULT_LIFECYCLE);
facesContextFactory = (FacesContextFactory) FactoryFinder.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);

View File

@@ -11,13 +11,20 @@ import javax.faces.component.UIOutput;
import javax.faces.component.UIPanel;
import javax.faces.component.UIViewRoot;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ExceptionQueuedEvent;
import javax.faces.event.ExceptionQueuedEventContext;
import javax.faces.event.PhaseEvent;
import javax.faces.event.PhaseId;
import javax.faces.event.PhaseListener;
import javax.faces.event.PostRestoreStateEvent;
import javax.faces.event.SystemEvent;
import javax.faces.lifecycle.Lifecycle;
import junit.framework.TestCase;
import org.apache.myfaces.test.mock.MockApplication20;
import org.easymock.EasyMock;
import org.jboss.el.ExpressionFactoryImpl;
import org.springframework.binding.expression.ExpressionParser;
@@ -82,6 +89,8 @@ public class JsfViewFactoryTests extends TestCase {
private void configureJsf() throws Exception {
jsfMock.setUp();
ExceptionEventAwareMockApplication application = new ExceptionEventAwareMockApplication();
((MockBaseFacesContext) FlowFacesContext.getCurrentInstance()).setApplication(application);
trackingListener = new TrackingPhaseListener();
jsfMock.lifecycle().addPhaseListener(trackingListener);
jsfMock.facesContext().setViewRoot(null);
@@ -98,7 +107,7 @@ public class JsfViewFactoryTests extends TestCase {
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
UIViewRoot newRoot = new UIViewRoot();
MockUIViewRoot newRoot = new MockUIViewRoot();
newRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setCreateView(newRoot);
context.inViewState();
@@ -115,7 +124,7 @@ public class JsfViewFactoryTests extends TestCase {
}
/**
* View already exists in view/flash scope and must be restored and the lifecycle executed, no event signaled
* View already exists in view/flash scope and must be restored and the lifecycle executed, no flow event signaled
*/
public final void testGetView_Restore() {
@@ -124,7 +133,7 @@ public class JsfViewFactoryTests extends TestCase {
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
UIViewRoot existingRoot = new UIViewRoot();
MockUIViewRoot existingRoot = new MockUIViewRoot();
existingRoot.setViewId(VIEW_ID);
UIInput input = new UIInput();
input.setId("invalidInput");
@@ -144,10 +153,11 @@ public class JsfViewFactoryTests extends TestCase {
assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId());
assertFalse("An unexpected event was signaled,", restoredView.hasFlowEvent());
assertTrue("The input component's valid flag was not reset", input.isValid());
assertTrue("The PostRestoreViewEvent was not seen", existingRoot.isPostRestoreStateEventSeen());
}
/**
* View already exists in view/flash scope and must be restored and the lifecycle executed, no event signaled
* View already exists in view/flash scope and must be restored and the lifecycle executed, no flow event signaled
*/
public final void testGetView_RestoreWithBindings() {
@@ -156,7 +166,7 @@ public class JsfViewFactoryTests extends TestCase {
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
UIViewRoot existingRoot = new UIViewRoot();
MockUIViewRoot existingRoot = new MockUIViewRoot();
existingRoot.setViewId(VIEW_ID);
UIPanel panel = new UIPanel();
panel.setId("panel1");
@@ -190,11 +200,12 @@ public class JsfViewFactoryTests extends TestCase {
assertFalse("An unexpected event was signaled,", restoredView.hasFlowEvent());
assertSame("The UIInput binding was not restored properly", input, testBean.getInput());
assertSame("The faceted UIOutput binding was not restored properly", output, testBean.getOutput());
assertTrue("The PostRestoreViewEvent was not seen", existingRoot.isPostRestoreStateEventSeen());
}
/**
* Ajax Request - View already exists in view/flash scope and must be restored and the lifecycle executed, no event
* signaled
* Ajax Request - View already exists in view/flash scope and must be restored and the lifecycle executed, no flow
* event signaled
*/
public final void testGetView_Restore_Ajax() {
@@ -203,7 +214,7 @@ public class JsfViewFactoryTests extends TestCase {
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
UIViewRoot existingRoot = new UIViewRoot();
MockUIViewRoot existingRoot = new MockUIViewRoot();
existingRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setRestoreView(existingRoot);
@@ -223,6 +234,7 @@ public class JsfViewFactoryTests extends TestCase {
assertTrue("An ViewRoot was not set", ((JsfView) restoredView).getViewRoot() instanceof UIViewRoot);
assertEquals("View name did not match", VIEW_ID, ((JsfView) restoredView).getViewRoot().getViewId());
assertFalse("An unexpected event was signaled,", restoredView.hasFlowEvent());
assertTrue("The PostRestoreViewEvent was not seen", existingRoot.isPostRestoreStateEventSeen());
}
/**
@@ -234,7 +246,7 @@ public class JsfViewFactoryTests extends TestCase {
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
UIViewRoot newRoot = new UIViewRoot();
MockUIViewRoot newRoot = new MockUIViewRoot();
newRoot.setViewId(VIEW_ID);
jsfMock.facesContext().setViewRoot(newRoot);
jsfMock.facesContext().renderResponse();
@@ -248,6 +260,30 @@ public class JsfViewFactoryTests extends TestCase {
assertEquals("View name did not match", VIEW_ID, ((JsfView) newView).getViewRoot().getViewId());
assertSame("View root was not the third party instance", newRoot, ((JsfView) newView).getViewRoot());
assertFalse("An unexpected event was signaled,", newView.hasFlowEvent());
assertTrue("The PostRestoreViewEvent was not seen", newRoot.isPostRestoreStateEventSeen());
}
public void testGetView_ExceptionsOnPostRestoreStateEvent() throws Exception {
lifecycle = new NoExecutionLifecycle(jsfMock.lifecycle());
factory = new JsfViewFactory(parser.parseExpression(VIEW_ID,
new FluentParserContext().template().evaluate(RequestContext.class).expectResult(String.class)),
lifecycle);
MockUIViewRoot existingRoot = new MockUIViewRoot();
existingRoot.setThrowOnPostRestoreStateEvent(true);
existingRoot.setViewId(VIEW_ID);
((MockViewHandler) viewHandler).setRestoreView(existingRoot);
context.inViewState();
EasyMock.expectLastCall().andReturn(Boolean.TRUE);
EasyMock.replay(new Object[] { context });
factory.getView(context);
ExceptionEventAwareMockApplication application = (ExceptionEventAwareMockApplication) FlowFacesContext
.getCurrentInstance().getApplication();
assertNotNull("Expected exception event", application.getExceptionQueuedEventContext());
assertSame("Expected same exception", existingRoot.getAbortProcessingException(), application
.getExceptionQueuedEventContext().getException());
}
private class NoExecutionLifecycle extends FlowLifecycle {
@@ -337,4 +373,51 @@ public class JsfViewFactoryTests extends TestCase {
this.input = input;
}
}
private static class MockUIViewRoot extends UIViewRoot {
private boolean postRestoreStateEventSeen;
private boolean throwOnPostRestoreStateEvent;
private AbortProcessingException abortProcessingException;
public void processEvent(ComponentSystemEvent event) throws AbortProcessingException {
if (event instanceof PostRestoreStateEvent) {
assertSame("Component did not match", this, ((PostRestoreStateEvent) event).getComponent());
postRestoreStateEventSeen = true;
if (throwOnPostRestoreStateEvent) {
abortProcessingException = new AbortProcessingException();
throw abortProcessingException;
}
}
}
public void setThrowOnPostRestoreStateEvent(boolean throwOnPostRestoreStateEvent) {
this.throwOnPostRestoreStateEvent = throwOnPostRestoreStateEvent;
}
public boolean isPostRestoreStateEventSeen() {
return postRestoreStateEventSeen;
}
public AbortProcessingException getAbortProcessingException() {
return abortProcessingException;
}
}
private static class ExceptionEventAwareMockApplication extends MockApplication20 {
private ExceptionQueuedEventContext exceptionQueuedEventContext;
public void publishEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass, Object source) {
if (ExceptionQueuedEvent.class.equals(systemEventClass)) {
this.exceptionQueuedEventContext = (ExceptionQueuedEventContext) source;
} else {
super.publishEvent(facesContext, systemEventClass, source);
}
}
public ExceptionQueuedEventContext getExceptionQueuedEventContext() {
return exceptionQueuedEventContext;
}
}
}

View File

@@ -38,4 +38,8 @@ public class MockBaseFacesContext extends MockFacesContext20 {
}
return application;
}
public void setApplication(Application application) {
this.application = application;
}
}

View File

@@ -8,7 +8,7 @@ Import-Template:
org.springframework.binding.*;version="[2.4.0, 2.5.0)",
org.springframework.js.*;version="[2.4.0, 2.5.0)",
org.springframework.webflow.*;version="[2.4.0, 2.5.0)",
org.springframework.*;version="[3.0.5.RELEASE, 3.1.0)",
org.springframework.*;version="[3.1.0.RELEASE, 3.2.0)",
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
javax.el;version="[1.0.0, 2.0.0)",
javax.portlet;version="[2.0.0, 3.0.0)";resolution:=optional,