diff --git a/spring-faces/src/main/java/META-INF/spring.handlers b/spring-faces/src/main/java/META-INF/spring.handlers
new file mode 100644
index 00000000..d533e40a
--- /dev/null
+++ b/spring-faces/src/main/java/META-INF/spring.handlers
@@ -0,0 +1 @@
+http\://www.springframework.org/schema/faces-config=org.springframework.faces.config.FacesConfigNamespaceHandler
\ No newline at end of file
diff --git a/spring-faces/src/main/java/META-INF/spring.schemas b/spring-faces/src/main/java/META-INF/spring.schemas
new file mode 100644
index 00000000..7188d258
--- /dev/null
+++ b/spring-faces/src/main/java/META-INF/spring.schemas
@@ -0,0 +1 @@
+http\://www.springframework.org/schema/faces-config/spring-faces-config-2.0.xsd=org/springframework/faces/config/spring-faces-config-2.0.xsd
\ No newline at end of file
diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java b/spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java
new file mode 100644
index 00000000..5390f3a5
--- /dev/null
+++ b/spring-faces/src/main/java/org/springframework/faces/config/FacesConfigNamespaceHandler.java
@@ -0,0 +1,11 @@
+package org.springframework.faces.config;
+
+import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
+
+public class FacesConfigNamespaceHandler extends NamespaceHandlerSupport {
+
+ public void init() {
+ registerBeanDefinitionParser("flow-builder-services", new FacesFlowBuilderServicesBeanDefinitionParser());
+ }
+
+}
diff --git a/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java
new file mode 100644
index 00000000..c357f663
--- /dev/null
+++ b/spring-faces/src/main/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParser.java
@@ -0,0 +1,82 @@
+package org.springframework.faces.config;
+
+import org.springframework.beans.factory.support.BeanDefinitionBuilder;
+import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
+import org.springframework.beans.factory.xml.BeanDefinitionParser;
+import org.springframework.faces.expression.LegacyJSFELExpressionParser;
+import org.springframework.faces.model.converter.FacesConversionService;
+import org.springframework.faces.webflow.JsfViewFactoryCreator;
+import org.springframework.util.StringUtils;
+import org.springframework.webflow.core.expression.el.WebFlowELExpressionParser;
+import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
+import org.w3c.dom.Element;
+
+public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefinitionParser implements
+ BeanDefinitionParser {
+
+ private static final String ENABLE_MANAGED_BEANS_ATTRIBUTE = "enable-managed-beans";
+
+ private static final String EXPRESSION_PARSER_ATTRIBUTE = "expression-parser";
+
+ private static final String EXPRESSION_PARSER_PROPERTY = "expressionParser";
+
+ private static final String VIEW_FACTORY_CREATOR_ATTRIBUTE = "view-factory-creator";
+
+ private static final String VIEW_FACTORY_CREATOR_PROPERTY = "viewFactoryCreator";
+
+ private static final String CONVERSION_SERVICE_ATTRIBUTE = "conversion-service";
+
+ private static final String CONVERSION_SERVICE_PROPERTY = "conversionService";
+
+ protected Class getBeanClass(Element element) {
+ return FlowBuilderServices.class;
+ }
+
+ protected void doParse(Element element, BeanDefinitionBuilder definitionBuilder) {
+ boolean enableManagedBeans = parseEnableManagedBeans(element, definitionBuilder);
+ if (!enableManagedBeans) {
+ parseExpressionParser(element, definitionBuilder);
+ }
+ parseViewFactoryCreator(element, definitionBuilder);
+ parseConversionService(element, definitionBuilder);
+ }
+
+ private boolean parseEnableManagedBeans(Element element, BeanDefinitionBuilder definitionBuilder) {
+ String enableManagedBeans = element.getAttribute(ENABLE_MANAGED_BEANS_ATTRIBUTE);
+ if (StringUtils.hasText(enableManagedBeans)) {
+ boolean enabled = Boolean.parseBoolean(enableManagedBeans);
+ if (enabled) {
+ definitionBuilder.addPropertyValue(EXPRESSION_PARSER_PROPERTY, new LegacyJSFELExpressionParser());
+ }
+ return enabled;
+ }
+ return false;
+ }
+
+ private void parseConversionService(Element element, BeanDefinitionBuilder definitionBuilder) {
+ String conversionService = element.getAttribute(CONVERSION_SERVICE_ATTRIBUTE);
+ if (StringUtils.hasText(conversionService)) {
+ definitionBuilder.addPropertyReference(CONVERSION_SERVICE_PROPERTY, conversionService);
+ } else {
+ definitionBuilder.addPropertyValue(CONVERSION_SERVICE_PROPERTY, new FacesConversionService());
+ }
+ }
+
+ private void parseViewFactoryCreator(Element element, BeanDefinitionBuilder definitionBuilder) {
+ String viewFactoryCreator = element.getAttribute(VIEW_FACTORY_CREATOR_ATTRIBUTE);
+ if (StringUtils.hasText(viewFactoryCreator)) {
+ definitionBuilder.addPropertyReference(VIEW_FACTORY_CREATOR_PROPERTY, viewFactoryCreator);
+ } else {
+ definitionBuilder.addPropertyValue(VIEW_FACTORY_CREATOR_PROPERTY, new JsfViewFactoryCreator());
+ }
+ }
+
+ private void parseExpressionParser(Element element, BeanDefinitionBuilder definitionBuilder) {
+ String expressionParser = element.getAttribute(EXPRESSION_PARSER_ATTRIBUTE);
+ if (StringUtils.hasText(expressionParser)) {
+ definitionBuilder.addPropertyReference(EXPRESSION_PARSER_PROPERTY, expressionParser);
+ } else {
+ definitionBuilder.addPropertyValue(EXPRESSION_PARSER_PROPERTY, new WebFlowELExpressionParser());
+ }
+ }
+}
diff --git a/spring-faces/src/main/java/org/springframework/faces/config/spring-faces-config-2.0.xsd b/spring-faces/src/main/java/org/springframework/faces/config/spring-faces-config-2.0.xsd
new file mode 100644
index 00000000..67f2996f
--- /dev/null
+++ b/spring-faces/src/main/java/org/springframework/faces/config/spring-faces-config-2.0.xsd
@@ -0,0 +1,81 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java
index ed89d0e6..2d97ed5b 100644
--- a/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java
+++ b/spring-faces/src/main/java/org/springframework/faces/expression/LegacyJSFELExpressionParser.java
@@ -31,6 +31,10 @@ public class LegacyJSFELExpressionParser extends ELExpressionParser {
putContextFactory(MutableAttributeMap.class, new AttributeMapELContextFactory());
}
+ public LegacyJSFELExpressionParser() {
+ this(ExpressionFactory.newInstance());
+ }
+
private static class RequestContextELContextFactory implements ELContextFactory {
public ELContext getELContext(Object target) {
List customResolvers = new ArrayList();
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParserTests.java b/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParserTests.java
new file mode 100644
index 00000000..1dad5b5f
--- /dev/null
+++ b/spring-faces/src/test/java/org/springframework/faces/config/FacesFlowBuilderServicesBeanDefinitionParserTests.java
@@ -0,0 +1,43 @@
+package org.springframework.faces.config;
+
+import junit.framework.TestCase;
+
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+import org.springframework.faces.expression.LegacyJSFELExpressionParser;
+import org.springframework.faces.model.converter.FacesConversionService;
+import org.springframework.faces.webflow.JSFMockHelper;
+import org.springframework.faces.webflow.JsfViewFactoryCreator;
+import org.springframework.webflow.core.expression.el.WebFlowELExpressionParser;
+import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
+
+public class FacesFlowBuilderServicesBeanDefinitionParserTests extends TestCase {
+
+ private ClassPathXmlApplicationContext context;
+ private FlowBuilderServices builderServices;
+ private JSFMockHelper jsf = new JSFMockHelper();
+
+ public void setUp() throws Exception {
+ jsf.setUp();
+ context = new ClassPathXmlApplicationContext("org/springframework/faces/config/flow-builder-services.xml");
+ }
+
+ protected void tearDown() throws Exception {
+ jsf.tearDown();
+ }
+
+ public void testConfigureDefaults() {
+ builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesDefault");
+ assertNotNull(builderServices);
+ assertTrue(builderServices.getExpressionParser() instanceof WebFlowELExpressionParser);
+ assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
+ assertTrue(builderServices.getConversionService() instanceof FacesConversionService);
+ }
+
+ public void testEnableManagedBeans() {
+ builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesLegacy");
+ assertNotNull(builderServices);
+ assertTrue(builderServices.getExpressionParser() instanceof LegacyJSFELExpressionParser);
+ assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
+ assertTrue(builderServices.getConversionService() instanceof FacesConversionService);
+ }
+}
diff --git a/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml b/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml
new file mode 100644
index 00000000..1876bb3d
--- /dev/null
+++ b/spring-faces/src/test/java/org/springframework/faces/config/flow-builder-services.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file