diff --git a/spring-webflow/.classpath b/spring-webflow/.classpath
index 3cb0bef3..3650210c 100644
--- a/spring-webflow/.classpath
+++ b/spring-webflow/.classpath
@@ -36,5 +36,6 @@
+
diff --git a/spring-webflow/ivy.xml b/spring-webflow/ivy.xml
index 69b546ea..db726492 100644
--- a/spring-webflow/ivy.xml
+++ b/spring-webflow/ivy.xml
@@ -72,6 +72,7 @@
+
\ No newline at end of file
diff --git a/spring-webflow/src/etc/test-resources/jsf-flow.xml b/spring-webflow/src/etc/test-resources/jsf-flow.xml
new file mode 100644
index 00000000..8cf2899d
--- /dev/null
+++ b/spring-webflow/src/etc/test-resources/jsf-flow.xml
@@ -0,0 +1,32 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FacesAPI.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FacesAPI.java
deleted file mode 100644
index 6482e7f2..00000000
--- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/FacesAPI.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package org.springframework.webflow.executor.jsf;
-
-import javax.faces.application.Application;
-
-public class FacesAPI {
-
- private static final int version = specifyVersion();
-
- private FacesAPI() {
-
- }
-
- private final static int specifyVersion() {
- try {
- Application.class.getMethod("getExpressionFactory", null);
- } catch (NoSuchMethodException e) {
- return 11;
- }
- return 12;
- }
-
- public final static int getVersion() {
- return version;
- }
-}
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfELExpressionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf11ELExpressionParser.java
similarity index 62%
rename from spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfELExpressionParser.java
rename to spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf11ELExpressionParser.java
index cfe7e824..90bde56c 100644
--- a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/JsfELExpressionParser.java
+++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf11ELExpressionParser.java
@@ -10,32 +10,26 @@ import org.springframework.binding.expression.el.ELContextFactory;
import org.springframework.binding.expression.el.JBossELExpressionParser;
/**
- * A JSF-aware ExpressionParser that allows JSF managed beans to be referenced in expressions in the FlowDefinition.
+ * A JSF-aware ExpressionParser that allows JSF 1.1 managed beans to be referenced in expressions in the FlowDefinition.
* @author Jeremy Grelle
*
*/
-public class JsfELExpressionParser extends JBossELExpressionParser {
+public class Jsf11ELExpressionParser extends JBossELExpressionParser {
- public JsfELExpressionParser() {
- super(new JsfELContextFactory());
+ public Jsf11ELExpressionParser() {
+ super(new Jsf11ELContextFactory());
}
- public JsfELExpressionParser(ELContextFactory contextFactory) {
+ public Jsf11ELExpressionParser(ELContextFactory contextFactory) {
super(contextFactory);
}
- private static class JsfELContextFactory implements ELContextFactory {
+ private static class Jsf11ELContextFactory implements ELContextFactory {
public ELContext getELContext(Object target) {
FacesContext context = FacesContext.getCurrentInstance();
- if (FacesAPI.getVersion() < 12) {
- return new Jsf11ELContext(context);
- }
- if (context != null) {
- return context.getELContext();
- }
- return null;
+ return new Jsf11ELContext(context);
}
private static class Jsf11ELContext extends ELContext {
diff --git a/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf12ELExpressionParser.java b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf12ELExpressionParser.java
new file mode 100644
index 00000000..61283850
--- /dev/null
+++ b/spring-webflow/src/main/java/org/springframework/webflow/executor/jsf/Jsf12ELExpressionParser.java
@@ -0,0 +1,36 @@
+package org.springframework.webflow.executor.jsf;
+
+import javax.el.ELContext;
+import javax.faces.context.FacesContext;
+
+import org.springframework.binding.expression.el.ELContextFactory;
+import org.springframework.binding.expression.el.JBossELExpressionParser;
+
+/**
+ * A JSF-aware ExpressionParser that allows JSF 1.2 managed beans to be referenced in expressions in the FlowDefinition.
+ * @author Jeremy Grelle
+ *
+ */
+public class Jsf12ELExpressionParser extends JBossELExpressionParser {
+
+ public Jsf12ELExpressionParser() {
+ super(new Jsf11ELContextFactory());
+ }
+
+ public Jsf12ELExpressionParser(ELContextFactory contextFactory) {
+ super(contextFactory);
+ }
+
+ private static class Jsf11ELContextFactory implements ELContextFactory {
+
+ public ELContext getELContext(Object target) {
+
+ FacesContext context = FacesContext.getCurrentInstance();
+ if (context != null) {
+ return context.getELContext();
+ }
+ return null;
+ }
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF.java
new file mode 100644
index 00000000..5ac41b76
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF.java
@@ -0,0 +1,80 @@
+package org.springframework.webflow.executor.jsf;
+
+import org.apache.shale.test.base.AbstractJsfTestCase;
+import org.apache.shale.test.mock.MockApplication;
+import org.apache.shale.test.mock.MockExternalContext;
+import org.apache.shale.test.mock.MockFacesContextFactory;
+import org.apache.shale.test.mock.MockHttpServletRequest;
+import org.apache.shale.test.mock.MockHttpServletResponse;
+import org.apache.shale.test.mock.MockHttpSession;
+import org.apache.shale.test.mock.MockLifecycle;
+import org.apache.shale.test.mock.MockLifecycleFactory;
+import org.apache.shale.test.mock.MockRenderKit;
+import org.apache.shale.test.mock.MockServletConfig;
+import org.apache.shale.test.mock.MockFacesContext;
+import org.apache.shale.test.mock.MockServletContext;
+
+public class JSF extends AbstractJsfTestCase {
+
+ public JSF(String name) {
+ super(name);
+ }
+
+ public void setUp() throws Exception {
+ super.setUp();
+ }
+
+ public void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+
+ public MockApplication application() {
+ return application;
+ }
+
+ public MockServletConfig config() {
+ return config;
+ }
+
+ public MockExternalContext externalContext() {
+ return externalContext;
+ }
+
+ public MockFacesContext facesContext() {
+ return facesContext;
+ }
+
+ public MockFacesContextFactory facesContextFactory() {
+ return facesContextFactory;
+ }
+
+ public MockLifecycle lifecycle() {
+ return lifecycle;
+ }
+
+ public MockLifecycleFactory lifecycleFactory() {
+ return lifecycleFactory;
+ }
+
+ public MockRenderKit renderKit() {
+ return renderKit;
+ }
+
+ public MockHttpServletRequest request() {
+ return request;
+ }
+
+ public MockHttpServletResponse response() {
+ return response;
+ }
+
+ public MockServletContext servletContext() {
+ return servletContext;
+ }
+
+ public MockHttpSession session() {
+ return session;
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF11ManagedBeanAccessTests.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF11ManagedBeanAccessTests.java
new file mode 100644
index 00000000..43c1c5bb
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF11ManagedBeanAccessTests.java
@@ -0,0 +1,140 @@
+package org.springframework.webflow.executor.jsf;
+
+import java.io.FileNotFoundException;
+
+import javax.faces.el.ValueBinding;
+
+import org.easymock.MockControl;
+import org.springframework.util.ResourceUtils;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.webflow.definition.registry.FlowDefinitionResource;
+import org.springframework.webflow.execution.FlowExecutionException;
+import org.springframework.webflow.execution.ViewSelection;
+import org.springframework.webflow.test.MockFlowServiceLocator;
+import org.springframework.webflow.test.execution.AbstractXmlFlowExecutionTests;
+
+public class JSF11ManagedBeanAccessTests extends AbstractXmlFlowExecutionTests {
+
+ JSF jsf;
+ JSFManagedBean jsfBean;
+ JSFModel jsfModel;
+ FlowPhaseListener flowPhaseListener;
+ FlowNavigationHandler flowNavigationHandler;
+ MockService service;
+ MockControl serviceControl;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ serviceControl = MockControl.createControl(MockService.class);
+ service = (MockService) serviceControl.getMock();
+ jsf = new JSF("JSFManagedBeanAccessTests");
+ jsf.setUp();
+ configureJSFForSWF();
+ }
+
+ private void configureJSFForSWF() {
+ DelegatingFlowVariableResolver dfvr = new DelegatingFlowVariableResolver(jsf.application()
+ .getVariableResolver());
+ FlowVariableResolver fvr = new FlowVariableResolver(dfvr);
+ jsf.application().setVariableResolver(fvr);
+ FlowPropertyResolver fpr = new FlowPropertyResolver(jsf.application().getPropertyResolver());
+ jsf.application().setPropertyResolver(fpr);
+
+ // flowPhaseListener = new FlowPhaseListener();
+ // jsf.lifecycle().addPhaseListener(flowPhaseListener);
+ flowNavigationHandler = new FlowNavigationHandler(jsf.application().getNavigationHandler());
+ jsf.application().setNavigationHandler(flowNavigationHandler);
+
+ jsf.externalContext().getRequestMap().put("JsfBean", new JSFManagedBean());
+
+ // flowPhaseListener.setupELContext(jsf.facesContext());
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ jsf.tearDown();
+ // flowPhaseListener.teardownELContext();
+ }
+
+ public void testManagedBeanExpression() {
+ ValueBinding vb = jsf.application().createValueBinding("#{JsfBean}");
+ jsfBean = (JSFManagedBean) vb.getValue(jsf.facesContext());
+ assertNotNull(jsfBean);
+ }
+
+ public void testSWFExplicitlyScopedPropertyInjection() {
+ testManagedBeanExpression();
+ startFlow();
+
+ ValueBinding propBinding = jsf.application().createValueBinding("#{flowScope.jsfModel}");
+ jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
+ assertNotNull(jsfModel);
+ jsfBean.setModel(jsfModel);
+ }
+
+ public void testManagedBeanProperyAsArgument() {
+ testManagedBeanExpression();
+ jsfBean.setProp1("arg");
+ service.doSomething(jsfBean.getProp1());
+ serviceControl.replay();
+
+ startFlow();
+ signalEvent("event1");
+ serviceControl.verify();
+ assertCurrentStateEquals("viewState2");
+ }
+
+ public void testEvalManagedBeanMethod() {
+ testManagedBeanExpression();
+ startFlow();
+
+ ValueBinding propBinding = jsf.application().createValueBinding("#{flowScope.jsfModel}");
+ jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
+ assertNotNull(jsfModel);
+ jsfModel.setValue("foo");
+
+ signalEvent("event2");
+ assertFalse(jsfBean.getValues().isEmpty());
+ String addedValue = jsfBean.getValues().get(0).toString();
+ assertEquals(jsfModel.getValue(), addedValue);
+ assertCurrentStateEquals("viewState2");
+ }
+
+ public void testSWFScopedPropertyInjection() {
+ // testManagedBeanExpression();
+ // startFlow();
+
+ // TODO - Add a flow scoped bean definition to the test application context
+ // ValueBinding propBinding = jsf.application().createValueBinding("#{flowScopedModel}");
+ // jsfModel = (JSFModel) propBinding.getValue(jsf.facesContext());
+ // assertNotNull("This test won't pass until custom scopes are implemented.", jsfModel);
+ // jsfBean.setModel(jsfModel);
+ }
+
+ protected ViewSelection startFlow() throws FlowExecutionException {
+ ViewSelection view = super.startFlow();
+ FlowExecutionHolder holder = new FlowExecutionHolder(getFlowExecution());
+ FlowExecutionHolderUtils.setFlowExecutionHolder(holder, jsf.facesContext());
+ holder.setViewSelection(view);
+ return view;
+ }
+
+ protected FlowDefinitionResource getFlowDefinitionResource() {
+ try {
+ return createFlowDefinitionResource(ResourceUtils.getFile("classpath:jsf-flow.xml").getPath());
+ } catch (FileNotFoundException e) {
+ fail(e.getMessage());
+ return null;
+ }
+ }
+
+ protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
+ serviceRegistry.setExpressionParser(new Jsf11ELExpressionParser());
+ serviceRegistry.registerBean("serviceBean", service);
+ StaticWebApplicationContext ctx = new StaticWebApplicationContext();
+ ctx.registerPrototype("jsfModel", JSFModel.class);
+ jsf.externalContext().getApplicationMap()
+ .put(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
+ }
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF12ManagedBeanAccessTests.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF12ManagedBeanAccessTests.java
new file mode 100644
index 00000000..948a2a0e
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSF12ManagedBeanAccessTests.java
@@ -0,0 +1,18 @@
+package org.springframework.webflow.executor.jsf;
+
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+import org.springframework.webflow.test.MockFlowServiceLocator;
+
+public class JSF12ManagedBeanAccessTests extends JSF11ManagedBeanAccessTests {
+
+ protected void registerMockServices(MockFlowServiceLocator serviceRegistry) {
+ serviceRegistry.setExpressionParser(new Jsf12ELExpressionParser());
+ serviceRegistry.registerBean("serviceBean", service);
+ StaticWebApplicationContext ctx = new StaticWebApplicationContext();
+ ctx.registerPrototype("jsfModel", JSFModel.class);
+ jsf.externalContext().getApplicationMap()
+ .put(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, ctx);
+ }
+
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFManagedBean.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFManagedBean.java
new file mode 100644
index 00000000..a987891b
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFManagedBean.java
@@ -0,0 +1,37 @@
+package org.springframework.webflow.executor.jsf;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class JSFManagedBean {
+
+ String prop1;
+ JSFModel model;
+ List values = new ArrayList();
+
+ public JSFModel getModel() {
+ return model;
+ }
+
+ public void setModel(JSFModel model) {
+ this.model = model;
+ }
+
+ public String getProp1() {
+ return prop1;
+ }
+
+ public void setProp1(String prop1) {
+ this.prop1 = prop1;
+ }
+
+ public void addValue(String value)
+ {
+ values.add(value);
+ }
+
+ public List getValues()
+ {
+ return values;
+ }
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFModel.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFModel.java
new file mode 100644
index 00000000..2a7e41a7
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/JSFModel.java
@@ -0,0 +1,13 @@
+package org.springframework.webflow.executor.jsf;
+
+public class JSFModel {
+ String value;
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+}
diff --git a/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/MockService.java b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/MockService.java
new file mode 100644
index 00000000..5e629066
--- /dev/null
+++ b/spring-webflow/src/test/java/org/springframework/webflow/executor/jsf/MockService.java
@@ -0,0 +1,6 @@
+package org.springframework.webflow.executor.jsf;
+
+public interface MockService {
+
+ public void doSomething(String arg);
+}