Add Java config option for configuring Spring Web Flow
Issue: SWF-1548
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.faces.webflow.JsfResourceRequestHandler;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
import org.springframework.webflow.config.FlowDefinitionRegistryBuilder;
|
||||
import org.springframework.webflow.config.FlowExecutorBuilder;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
|
||||
|
||||
/**
|
||||
* A base class for {@link Configuration @Configuration} classes to configure
|
||||
* Spring Web Flow in JSF applications.
|
||||
* <p>
|
||||
* Provides protected method access to builders for one (or more) of the following:
|
||||
* <ul>
|
||||
* <li>{@link FlowExecutor}
|
||||
* <li>{@link FlowDefinitionRegistry}
|
||||
* <li>{@link FlowBuilderServices}
|
||||
* </ul>
|
||||
* <p>
|
||||
* Also registers a HandlerMapping bean to provide JSF 2 resource handling at
|
||||
* {@code "/javax.faces.resource/**"} or Rich Faces at {@code "/rfRes/**"}.
|
||||
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class AbstractFacesFlowConfiguration {
|
||||
|
||||
private static final boolean isRichFacesPresent =
|
||||
ClassUtils.isPresent("org.richfaces.application.CoreConfiguration",
|
||||
ResourcesBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowExecutor} instance.
|
||||
* @param flowRegistry the {@link FlowDefinitionRegistry} to configure on the flow executor
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowExecutorBuilder getFlowExecutorBuilder(FlowDefinitionLocator flowRegistry) {
|
||||
return new FlowExecutorBuilder(flowRegistry, this.applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowDefinitionRegistry} instance.
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowDefinitionRegistryBuilder getFlowDefinitionRegistryBuilder() {
|
||||
return new FlowDefinitionRegistryBuilder(this.applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowDefinitionRegistry} instance.
|
||||
* @param flowBuilderServices the {@link FlowBuilderServices} to configure on the flow registry with
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowDefinitionRegistryBuilder getFlowDefinitionRegistryBuilder(FlowBuilderServices flowBuilderServices) {
|
||||
return new FlowDefinitionRegistryBuilder(this.applicationContext, flowBuilderServices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowBuilderServices} instance.
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowBuilderServicesBuilder getFlowBuilderServicesBuilder() {
|
||||
return new FlowBuilderServicesBuilder();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public SimpleUrlHandlerMapping jsrResourceHandlerMapping() {
|
||||
|
||||
Map<String, Object> urlMap = new HashMap<String, Object>();
|
||||
urlMap.put("/javax.faces.resource/**", jsfResourceRequestHandler());
|
||||
if (isRichFacesPresent) {
|
||||
urlMap.put("/rfRes/**", jsfResourceRequestHandler());
|
||||
}
|
||||
|
||||
SimpleUrlHandlerMapping handlerMapping = new SimpleUrlHandlerMapping();
|
||||
handlerMapping.setUrlMap(urlMap);
|
||||
handlerMapping.setOrder(0);
|
||||
return handlerMapping;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JsfResourceRequestHandler jsfResourceRequestHandler() {
|
||||
return new JsfResourceRequestHandler();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public HttpRequestHandlerAdapter httpRequestHandlerAdapter() {
|
||||
return new HttpRequestHandlerAdapter();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.faces.webflow.context.portlet.JsfResourceRequestHandler;
|
||||
|
||||
/**
|
||||
* Extends {@link AbstractFacesFlowConfiguration} and registers a
|
||||
* {@link JsfResourceRequestHandler} bean for serving resources in a Portlet environment.
|
||||
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class AbstractFacesPortletFlowConfiguration extends AbstractFacesFlowConfiguration {
|
||||
|
||||
@Bean
|
||||
public JsfResourceRequestHandler jsfPortletResourceRequestHandler() {
|
||||
return new JsfResourceRequestHandler();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.faces.model.converter.FacesConversionService;
|
||||
import org.springframework.faces.webflow.FacesSpringELExpressionParser;
|
||||
import org.springframework.faces.webflow.JsfViewFactoryCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
|
||||
/**
|
||||
* A builder for {@link FlowBuilderServices} instances for use in JSF applications.
|
||||
* Designed for programmatic use in {@code @Bean} factory methods. For XML
|
||||
* configuration consider using the {@code webflow-config} and {@code faces-config}
|
||||
* XML namespaces.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class FlowBuilderServicesBuilder {
|
||||
|
||||
private boolean enableManagedBeans = false;
|
||||
|
||||
private ConversionService conversionService = new FacesConversionService();
|
||||
|
||||
private ExpressionParser expressionParser;
|
||||
|
||||
private ViewFactoryCreator viewFactoryCreator = new JsfViewFactoryCreator();
|
||||
|
||||
private boolean enableDevelopmentMode;
|
||||
|
||||
|
||||
/**
|
||||
* Whether to enable access to JSF-managed beans from EL expressions.
|
||||
* When this attribute is set to true, a special EL expression parser will be registered.
|
||||
* @param enableManagedBeans whether to enable JSF managed bean resolution
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setEnableManagedBeans(boolean enableManagedBeans) {
|
||||
this.enableManagedBeans = enableManagedBeans;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ConversionService} to use.
|
||||
* By default a {@link DefaultConversionService} instance is used.
|
||||
* @param conversionService the conversion service
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ExpressionParser} to use.
|
||||
* By default a {@link WebFlowSpringELExpressionParser} with SpEL expressions is used.
|
||||
* @param expressionParser the expression parser to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setExpressionParser(ExpressionParser expressionParser) {
|
||||
this.expressionParser = expressionParser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom {@link ViewFactoryCreator} to use for rendering.
|
||||
* By default an {@link JsfViewFactoryCreator} instance is used.
|
||||
* @param viewFactoryCreator the ViewFactory creator to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setViewFactoryCreator(ViewFactoryCreator viewFactoryCreator) {
|
||||
this.viewFactoryCreator = viewFactoryCreator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put all flows in development mode. When set to {@code true}, changes to a flow
|
||||
* definition are auto-detected and result in a flow refresh.
|
||||
* By default this is set to {@code false}
|
||||
* @param enableDevelopmentMode whether to enable development mode
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setDevelopmentMode(boolean enableDevelopmentMode) {
|
||||
this.enableDevelopmentMode = enableDevelopmentMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a {@link FlowBuilderServices} instance.
|
||||
*/
|
||||
public FlowBuilderServices build() {
|
||||
FlowBuilderServices flowBuilderServices = new FlowBuilderServices();
|
||||
flowBuilderServices.setConversionService(this.conversionService);
|
||||
flowBuilderServices.setExpressionParser(getExpressionParser());
|
||||
flowBuilderServices.setViewFactoryCreator(this.viewFactoryCreator);
|
||||
flowBuilderServices.setDevelopment(this.enableDevelopmentMode);
|
||||
return flowBuilderServices;
|
||||
}
|
||||
|
||||
private ExpressionParser getExpressionParser() {
|
||||
if (this.expressionParser != null) {
|
||||
Assert.isTrue(!this.enableManagedBeans,
|
||||
"Do not specify a custom expression-parser when enable-managed-beans is true");
|
||||
return this.expressionParser;
|
||||
}
|
||||
else {
|
||||
return (this.enableManagedBeans ?
|
||||
new FacesSpringELExpressionParser(new SpelExpressionParser(), this.conversionService) :
|
||||
new WebFlowSpringELExpressionParser(new SpelExpressionParser(), this.conversionService));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
|
||||
static final String PORTLET_RESOURCE_HANDLER_BEAN_NAME = "jsfPortletResourceRequestHandler";
|
||||
|
||||
private static final boolean RICH_FACES_PRESENT =
|
||||
private static final boolean isRichFacesPresent =
|
||||
ClassUtils.isPresent("org.richfaces.application.CoreConfiguration",
|
||||
ResourcesBeanDefinitionParser.class.getClassLoader());
|
||||
|
||||
@@ -106,7 +106,7 @@ public class ResourcesBeanDefinitionParser implements BeanDefinitionParser {
|
||||
Map<String, String> urlMap = new ManagedMap<String, String>();
|
||||
urlMap.put("/javax.faces.resource/**", SERVLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
|
||||
if (RICH_FACES_PRESENT) {
|
||||
if (isRichFacesPresent) {
|
||||
urlMap.put("/rfRes/**", SERVLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
}
|
||||
|
||||
|
||||
@@ -27,17 +27,19 @@ import org.springframework.web.HttpRequestHandler;
|
||||
import org.springframework.web.context.support.WebApplicationObjectSupport;
|
||||
|
||||
/**
|
||||
* Handles a request by delegating to the JSF ResourceHandler, which serves web application and classpath resources such
|
||||
* as images, CSS and JavaScript files from well-known locations.
|
||||
*
|
||||
* Handles a request by delegating to the JSF ResourceHandler, which serves web
|
||||
* application and classpath resources such as images, CSS and JavaScript files
|
||||
* from well-known locations.
|
||||
*
|
||||
* @since 2.2.0
|
||||
* @author Rossen Stoyanchev
|
||||
* @see ResourceHandler
|
||||
*/
|
||||
public class JsfResourceRequestHandler extends WebApplicationObjectSupport implements HttpRequestHandler {
|
||||
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response) throws ServletException,
|
||||
IOException {
|
||||
public void handleRequest(HttpServletRequest request, HttpServletResponse response)
|
||||
throws ServletException, IOException {
|
||||
|
||||
FacesContextHelper helper = new FacesContextHelper();
|
||||
try {
|
||||
FacesContext facesContext = helper.getFacesContext(getServletContext(), request, response);
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.faces.model.converter.FacesConversionService;
|
||||
import org.springframework.faces.webflow.FacesSpringELExpressionParser;
|
||||
import org.springframework.faces.webflow.JSFMockHelper;
|
||||
import org.springframework.faces.webflow.JsfViewFactoryCreator;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
public abstract class AbstractFacesFlowBuilderServicesConfigurationTests extends TestCase {
|
||||
|
||||
protected ApplicationContext context;
|
||||
|
||||
protected FlowBuilderServices builderServices;
|
||||
|
||||
protected final JSFMockHelper jsf = new JSFMockHelper();
|
||||
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.jsf.setUp();
|
||||
this.context = initApplicationContext();
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
this.jsf.tearDown();
|
||||
}
|
||||
|
||||
public void testConfigureDefaults() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesDefault");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testEnableManagedBeans() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesLegacy");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof FacesSpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesAllCustomized() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesAllCustom");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesConversionServiceCustomized() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesConversionServiceCustom");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
|
||||
assertTrue(((SpringELExpressionParser) this.builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public static class TestViewFactoryCreator implements ViewFactoryCreator {
|
||||
|
||||
public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
|
||||
ConversionService conversionService, BinderConfiguration binderConfiguration,
|
||||
Validator validator, ValidationHintResolver validationHintResolver) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public String getViewIdByConvention(String viewStateId) {
|
||||
return viewStateId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestConversionService implements ConversionService {
|
||||
|
||||
public Object executeConversion(Object source, Class<?> targetClass) throws ConversionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class<?> targetClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Class<?> getClassForAlias(String name) throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.faces.webflow.JsfResourceRequestHandler;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
|
||||
public abstract class AbstractResourcesConfigurationTests extends TestCase {
|
||||
|
||||
protected ApplicationContext context;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.context = initApplicationContext();
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
public void testConfigureDefaults() {
|
||||
Map<String, ?> map = this.context.getBeansOfType(HttpRequestHandlerAdapter.class);
|
||||
assertEquals(1, map.values().size());
|
||||
|
||||
Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.SERVLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
assertNotNull(resourceHandler);
|
||||
assertTrue(resourceHandler instanceof JsfResourceRequestHandler);
|
||||
|
||||
map = this.context.getBeansOfType(SimpleUrlHandlerMapping.class);
|
||||
assertEquals(1, map.values().size());
|
||||
SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) map.values().iterator().next();
|
||||
assertSame(resourceHandler, handlerMapping.getHandlerMap().get("/javax.faces.resource/**"));
|
||||
assertEquals(0, handlerMapping.getOrder());
|
||||
}
|
||||
|
||||
public void testConfigurePortlet() {
|
||||
Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.PORTLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
assertNotNull(resourceHandler);
|
||||
assertTrue(resourceHandler instanceof org.springframework.faces.webflow.context.portlet.JsfResourceRequestHandler);
|
||||
}
|
||||
}
|
||||
@@ -1,120 +1,15 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.faces.model.converter.FacesConversionService;
|
||||
import org.springframework.faces.webflow.FacesSpringELExpressionParser;
|
||||
import org.springframework.faces.webflow.JSFMockHelper;
|
||||
import org.springframework.faces.webflow.JsfViewFactoryCreator;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
public class FacesFlowBuilderServicesBeanDefinitionParserTests extends TestCase {
|
||||
public class FacesFlowBuilderServicesBeanDefinitionParserTests
|
||||
extends AbstractFacesFlowBuilderServicesConfigurationTests {
|
||||
|
||||
private ClassPathXmlApplicationContext context;
|
||||
private FlowBuilderServices builderServices;
|
||||
private final JSFMockHelper jsf = new JSFMockHelper();
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.jsf.setUp();
|
||||
this.context = new ClassPathXmlApplicationContext("org/springframework/faces/config/flow-builder-services.xml");
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new ClassPathXmlApplicationContext("org/springframework/faces/config/flow-builder-services.xml");
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
this.jsf.tearDown();
|
||||
}
|
||||
|
||||
public void testConfigureDefaults() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesDefault");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testEnableManagedBeans() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesLegacy");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof FacesSpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof FacesConversionService);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesAllCustomized() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesAllCustom");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesConversionServiceCustomized() {
|
||||
this.builderServices = (FlowBuilderServices) this.context.getBean("flowBuilderServicesConversionServiceCustom");
|
||||
assertNotNull(this.builderServices);
|
||||
assertTrue(this.builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
|
||||
assertTrue(((SpringELExpressionParser) this.builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(this.builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertFalse(this.builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public static class TestViewFactoryCreator implements ViewFactoryCreator {
|
||||
|
||||
public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
|
||||
ConversionService conversionService, BinderConfiguration binderConfiguration,
|
||||
Validator validator, ValidationHintResolver validationHintResolver) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public String getViewIdByConvention(String viewStateId) {
|
||||
return viewStateId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestConversionService implements ConversionService {
|
||||
|
||||
public Object executeConversion(Object source, Class<?> targetClass) throws ConversionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class<?> targetClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Class<?> getClassForAlias(String name) throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
|
||||
public class FacesFlowBuilderServicesJavaConfigTests extends AbstractFacesFlowBuilderServicesConfigurationTests {
|
||||
|
||||
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(FacesFlowConfig.class);
|
||||
}
|
||||
|
||||
|
||||
static class FacesFlowConfig extends AbstractFacesFlowConfiguration {
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesDefault() {
|
||||
return getFlowBuilderServicesBuilder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesLegacy() {
|
||||
return getFlowBuilderServicesBuilder().setEnableManagedBeans(true).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesAllCustom() {
|
||||
return getFlowBuilderServicesBuilder()
|
||||
.setExpressionParser(customExpressionParser())
|
||||
.setViewFactoryCreator(customViewFactoryCreator())
|
||||
.setConversionService(customConversionService())
|
||||
.setDevelopmentMode(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesConversionServiceCustom() {
|
||||
return getFlowBuilderServicesBuilder().setConversionService(customConversionService()).build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebFlowSpringELExpressionParser customExpressionParser() {
|
||||
return new WebFlowSpringELExpressionParser(new SpelExpressionParser());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ViewFactoryCreator customViewFactoryCreator() {
|
||||
return new TestViewFactoryCreator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public ConversionService customConversionService() {
|
||||
return new TestConversionService();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,44 +1,14 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.faces.webflow.JsfResourceRequestHandler;
|
||||
import org.springframework.web.servlet.handler.SimpleUrlHandlerMapping;
|
||||
import org.springframework.web.servlet.mvc.HttpRequestHandlerAdapter;
|
||||
|
||||
public class ResourcesBeanDefinitionParserTests extends TestCase {
|
||||
public class ResourcesBeanDefinitionParserTests extends AbstractResourcesConfigurationTests {
|
||||
|
||||
private ClassPathXmlApplicationContext context;
|
||||
|
||||
public void setUp() throws Exception {
|
||||
this.context = new ClassPathXmlApplicationContext("org/springframework/faces/config/resources.xml");
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new ClassPathXmlApplicationContext("org/springframework/faces/config/resources.xml");
|
||||
}
|
||||
|
||||
protected void tearDown() throws Exception {
|
||||
}
|
||||
|
||||
public void testConfigureDefaults() {
|
||||
Map<String, ?> map = this.context.getBeansOfType(HttpRequestHandlerAdapter.class);
|
||||
assertEquals(1, map.values().size());
|
||||
|
||||
Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.SERVLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
assertNotNull(resourceHandler);
|
||||
assertTrue(resourceHandler instanceof JsfResourceRequestHandler);
|
||||
|
||||
map = this.context.getBeansOfType(SimpleUrlHandlerMapping.class);
|
||||
assertEquals(1, map.values().size());
|
||||
SimpleUrlHandlerMapping handlerMapping = (SimpleUrlHandlerMapping) map.values().iterator().next();
|
||||
assertEquals(ResourcesBeanDefinitionParser.SERVLET_RESOURCE_HANDLER_BEAN_NAME,
|
||||
handlerMapping.getUrlMap().get("/javax.faces.resource/**"));
|
||||
assertEquals(0, handlerMapping.getOrder());
|
||||
}
|
||||
|
||||
public void testConfigurePortlet() {
|
||||
Object resourceHandler = this.context.getBean(ResourcesBeanDefinitionParser.PORTLET_RESOURCE_HANDLER_BEAN_NAME);
|
||||
assertNotNull(resourceHandler);
|
||||
assertTrue(resourceHandler instanceof org.springframework.faces.webflow.context.portlet.JsfResourceRequestHandler);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
public class ResourcesJavaConfigTests extends AbstractResourcesConfigurationTests {
|
||||
|
||||
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(FacesFlowConfig.class);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
static class FacesFlowConfig extends AbstractFacesPortletFlowConfiguration {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -26,8 +26,10 @@
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="customViewFactoryCreator" class="org.springframework.faces.config.FacesFlowBuilderServicesBeanDefinitionParserTests$TestViewFactoryCreator"/>
|
||||
<bean id="customViewFactoryCreator"
|
||||
class="org.springframework.faces.config.AbstractFacesFlowBuilderServicesConfigurationTests$TestViewFactoryCreator"/>
|
||||
|
||||
<bean id="customConversionService" class="org.springframework.faces.config.FacesFlowBuilderServicesBeanDefinitionParserTests$TestConversionService"/>
|
||||
<bean id="customConversionService"
|
||||
class="org.springframework.faces.config.AbstractFacesFlowBuilderServicesConfigurationTests$TestConversionService"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
|
||||
/**
|
||||
* A base class for {@link Configuration @Configuration} classes to configure
|
||||
* Spring Web Flow.
|
||||
* <p>
|
||||
* Does not provides any configuration (i.e. no {@code @Bean} methods}.
|
||||
* Instead it provides access, via protected methods, to builders for one (or more)
|
||||
* of the following:
|
||||
* <ul>
|
||||
* <li>{@link FlowExecutor}
|
||||
* <li>{@link FlowDefinitionRegistry}
|
||||
* <li>{@link FlowBuilderServices}
|
||||
* </ul>
|
||||
* <p>
|
||||
* Sub-classes are expected to declare {@code @Bean} methods themselves and use the
|
||||
* appropriate builder from these methods.
|
||||
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class AbstractFlowConfiguration implements ApplicationContextAware {
|
||||
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
|
||||
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||
this.applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public ApplicationContext getApplicationContext() {
|
||||
return this.applicationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowExecutor} instance.
|
||||
* @param flowRegistry the {@link FlowDefinitionRegistry} to configure on the flow executor
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowExecutorBuilder getFlowExecutorBuilder(FlowDefinitionLocator flowRegistry) {
|
||||
return new FlowExecutorBuilder(flowRegistry, this.applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowDefinitionRegistry} instance.
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowDefinitionRegistryBuilder getFlowDefinitionRegistryBuilder() {
|
||||
return new FlowDefinitionRegistryBuilder(this.applicationContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowDefinitionRegistry} instance.
|
||||
* @param flowBuilderServices the {@link FlowBuilderServices} to configure on the flow registry with
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowDefinitionRegistryBuilder getFlowDefinitionRegistryBuilder(FlowBuilderServices flowBuilderServices) {
|
||||
return new FlowDefinitionRegistryBuilder(this.applicationContext, flowBuilderServices);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a builder for creating a {@link FlowBuilderServices} instance.
|
||||
* @return the created builder
|
||||
*/
|
||||
protected FlowBuilderServicesBuilder getFlowBuilderServicesBuilder() {
|
||||
return new FlowBuilderServicesBuilder(this.applicationContext);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
|
||||
import org.springframework.webflow.validation.BeanValidationHintResolver;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
/**
|
||||
* A builder for creating {@link FlowBuilderServices} instances designed for programmatic
|
||||
* use in {@code @Bean} factory methods. For XML configuration consider using the
|
||||
* {@code webflow-config} XML namespace.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class FlowBuilderServicesBuilder {
|
||||
|
||||
private ConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
private ExpressionParser expressionParser;
|
||||
|
||||
private ViewFactoryCreator viewFactoryCreator;
|
||||
|
||||
private Validator validator;
|
||||
|
||||
private ValidationHintResolver validationHintResolver;
|
||||
|
||||
private boolean enableDevelopmentMode;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with the given ApplicationContext.
|
||||
*
|
||||
* @param applicationContext the ApplicationContext to use to initialize a
|
||||
* default ViewFactoryCreator instance with.
|
||||
*/
|
||||
public FlowBuilderServicesBuilder(ApplicationContext applicationContext) {
|
||||
Assert.notNull(applicationContext, "applicationContext is required");
|
||||
this.viewFactoryCreator = initViewFactoryCreator(applicationContext);
|
||||
}
|
||||
|
||||
private static ViewFactoryCreator initViewFactoryCreator(ApplicationContext applicationContext) {
|
||||
MvcViewFactoryCreator viewFactoryCreator = new MvcViewFactoryCreator();
|
||||
viewFactoryCreator.setApplicationContext(applicationContext);
|
||||
return viewFactoryCreator;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the {@link ConversionService} to use.
|
||||
* By default a {@link DefaultConversionService} instance is used.
|
||||
* @param conversionService the conversion service
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link ExpressionParser} to use.
|
||||
* By default a {@link WebFlowSpringELExpressionParser} with SpEL expressions is used.
|
||||
* @param expressionParser the expression parser to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setExpressionParser(ExpressionParser expressionParser) {
|
||||
this.expressionParser = expressionParser;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a custom {@link ViewFactoryCreator} to use for rendering.
|
||||
* By default an {@link MvcViewFactoryCreator} instance is used.
|
||||
* @param viewFactoryCreator the ViewFactory creator to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setViewFactoryCreator(ViewFactoryCreator viewFactoryCreator) {
|
||||
this.viewFactoryCreator = viewFactoryCreator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link Validator} to use for validating a model declared on a view state.
|
||||
* By default bean validation (JSR-303) is enabled if a bean validation provider is
|
||||
* present on the classpath.
|
||||
* @param validator the validator to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setValidator(Validator validator) {
|
||||
this.validator = validator;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* The {@link ValidationHintResolver} to use to resolve validation hints such as bean validation groups.
|
||||
* By default a {@link BeanValidationHintResolver} is used.
|
||||
* @param resolver the resolver to use
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setValidationHintResolver(ValidationHintResolver resolver) {
|
||||
this.validationHintResolver = resolver;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Put all flows in development mode. When set to {@code true}, changes to a flow
|
||||
* definition are auto-detected and result in a flow refresh.
|
||||
* By default this is set to {@code false}
|
||||
* @param enableDevelopmentMode whether to enable development mode
|
||||
*/
|
||||
public FlowBuilderServicesBuilder setDevelopmentMode(boolean enableDevelopmentMode) {
|
||||
this.enableDevelopmentMode = enableDevelopmentMode;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a {@link FlowBuilderServices} instance.
|
||||
*/
|
||||
public FlowBuilderServices build() {
|
||||
FlowBuilderServices flowBuilderServices = new FlowBuilderServices();
|
||||
flowBuilderServices.setConversionService(this.conversionService);
|
||||
flowBuilderServices.setExpressionParser(getExpressionParser());
|
||||
flowBuilderServices.setViewFactoryCreator(this.viewFactoryCreator);
|
||||
flowBuilderServices.setValidator(this.validator);
|
||||
flowBuilderServices.setValidationHintResolver(this.validationHintResolver);
|
||||
flowBuilderServices.setDevelopment(this.enableDevelopmentMode);
|
||||
return flowBuilderServices;
|
||||
}
|
||||
|
||||
private ExpressionParser getExpressionParser() {
|
||||
if (this.expressionParser != null) {
|
||||
return this.expressionParser;
|
||||
}
|
||||
else {
|
||||
return new WebFlowSpringELExpressionParser(new SpelExpressionParser(), this.conversionService);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,363 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.DefaultFlowHolder;
|
||||
import org.springframework.webflow.engine.builder.FlowAssembler;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.FlowBuilderContext;
|
||||
import org.springframework.webflow.engine.builder.model.FlowModelFlowBuilder;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderContextImpl;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.engine.model.builder.DefaultFlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.builder.FlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
|
||||
/**
|
||||
* A builder for creating {@link FlowDefinitionRegistry} instances designed for programmatic
|
||||
* use in {@code @Bean} factory methods. For XML configuration consider using the
|
||||
* {@code webflow-config} XML namespace.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class FlowDefinitionRegistryBuilder {
|
||||
|
||||
private final List<FlowLocation> flowLocations = new ArrayList<FlowLocation>();
|
||||
|
||||
private final List<String> flowLocationPatterns = new ArrayList<String>();
|
||||
|
||||
private final List<FlowBuilderInfo> flowBuilderInfos = new ArrayList<FlowBuilderInfo>();
|
||||
|
||||
private FlowBuilderServices flowBuilderServices;
|
||||
|
||||
private FlowDefinitionRegistry parent;
|
||||
|
||||
private FlowDefinitionResourceFactory flowResourceFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with the given ApplicationContext.
|
||||
*
|
||||
* @param applicationContext the ApplicationContext to use for initializing the
|
||||
* FlowDefinitionResourceFactory and FlowBuilderServices instances with
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder(ApplicationContext appContext) {
|
||||
this(appContext, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new instance with the given ApplicationContext and {@link FlowBuilderServices}.
|
||||
*
|
||||
* @param applicationContext the ApplicationContext to use for initializing the
|
||||
* FlowDefinitionResourceFactory and FlowBuilderServices instances with
|
||||
* @param builderServices a {@link FlowBuilderServices} instance to configure
|
||||
* on the FlowDefinitionRegistry
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder(ApplicationContext appContext, FlowBuilderServices builderServices) {
|
||||
Assert.notNull(appContext, "applicationContext is required");
|
||||
this.flowResourceFactory = new FlowDefinitionResourceFactory(appContext);
|
||||
if (builderServices != null) {
|
||||
this.flowBuilderServices = builderServices;
|
||||
}
|
||||
else {
|
||||
this.flowBuilderServices = new FlowBuilderServicesBuilder(appContext).build();
|
||||
this.flowBuilderServices.setApplicationContext(appContext);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Configure the base path where flow definitions are found. When specified, all
|
||||
* flow locations are relative to this path. Also when specified, by default flows
|
||||
* are assigned an id equal to the the path segment between their base path and
|
||||
* file name.
|
||||
* <p>
|
||||
* For example, if a flow definition is located at
|
||||
* '/WEB-INF/hotels/booking/booking-flow.xml' and the base path is '/WEB-INF', the
|
||||
* remaining path to this flow is 'hotels/booking' which then becomes the flow id.
|
||||
* <p>
|
||||
* If a flow definition is found directly on the base path, the file name minus
|
||||
* its extension is used as the flow id.
|
||||
* @param basePath the base path to use
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder setBasePath(String basePath) {
|
||||
if (basePath != null) {
|
||||
this.flowResourceFactory.setBasePath(basePath);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a flow defined at the following location as an .xml file.
|
||||
* This may be a path to a single resource or a ANT-style path expression that
|
||||
* matches multiple resources.
|
||||
* @param path the resource path to the externalized flow definition resource.
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowLocation(String path) {
|
||||
this.addFlowLocation(path, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a flow defined at the following location as an .xml file.
|
||||
* This may be a path to a single resource or a ANT-style path expression that
|
||||
* matches multiple resources.
|
||||
* @param path the resource path to the externalized flow definition resource.
|
||||
* @param id the unique id to assign to the added flow definition in the registry
|
||||
* Specify only if you wish to provide a custom flow definition identifier.
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowLocation(String path, String id) {
|
||||
this.flowLocations.add(new FlowLocation(path, id, null));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a flow defined at the following location as an .xml file.
|
||||
* This may be a path to a single resource or a ANT-style path expression that
|
||||
* matches multiple resources.
|
||||
* @param path the resource path to the externalized flow definition resource.
|
||||
* @param id the unique id to assign to the added flow definition in the registry
|
||||
* Specify only if you wish to provide a custom flow definition identifier.
|
||||
* @param attributes meta-attributes to assign to the flow definition
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowLocation(String path, String id, Map<String, Object> attributes) {
|
||||
this.flowLocations.add(new FlowLocation(path, id, attributes));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a set of flows resolved from a resource location pattern.
|
||||
* @param pattern the pattern to use
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowLocationPattern(String pattern) {
|
||||
this.flowLocationPatterns.add(pattern);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@link FlowBuilderServices} to use for defining custom services needed
|
||||
* to build the flows registered in this registry.
|
||||
* @param flowBuilderServices the {@link FlowBuilderServices} instance
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder setFlowBuilderServices(FlowBuilderServices flowBuilderServices) {
|
||||
this.flowBuilderServices = flowBuilderServices;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom {@link FlowBuilder} instance.
|
||||
* @param builder the FlowBuilder to configure
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowBuilder(FlowBuilder builder) {
|
||||
addFlowBuilder(builder, null, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom {@link FlowBuilder} instance with the given flow id.
|
||||
* @param builder the FlowBuilder to configure
|
||||
* @param id the id assign to the flow definition in this registry.
|
||||
* Specify when you wish to provide a custom flow definition identifier.
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowBuilder(FlowBuilder builder, String id) {
|
||||
addFlowBuilder(builder, id, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a custom {@link FlowBuilder} instance with the given flow id.
|
||||
* @param builder the FlowBuilder to configure
|
||||
* @param id the id assign to the flow definition in this registry.
|
||||
* Specify when you wish to provide a custom flow definition identifier.
|
||||
* @param attributes attributes to assign to the flow definition.
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder addFlowBuilder(FlowBuilder builder, String id, Map<String, Object> attributes) {
|
||||
if (!StringUtils.hasText(id)) {
|
||||
id = StringUtils.uncapitalize(StringUtils.delete(
|
||||
ClassUtils.getShortName(builder.getClass()), "FlowBuilder"));
|
||||
}
|
||||
this.flowBuilderInfos.add(new FlowBuilderInfo(builder, id, attributes));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure a parent registry. Registries can be organized in a hierarchy.
|
||||
* If a child registry does not contain a flow, its parent registry is queried.
|
||||
* @param parent the parent registry
|
||||
*/
|
||||
public FlowDefinitionRegistryBuilder setParent(FlowDefinitionRegistry parent) {
|
||||
this.parent = parent;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a {@link FlowDefinitionRegistry} instance.
|
||||
*/
|
||||
public FlowDefinitionRegistry build() {
|
||||
|
||||
DefaultFlowRegistry flowRegistry = new DefaultFlowRegistry();
|
||||
flowRegistry.setParent(this.parent);
|
||||
|
||||
registerFlowLocations(flowRegistry);
|
||||
registerFlowLocationPatterns(flowRegistry);
|
||||
registerFlowBuilders(flowRegistry);
|
||||
|
||||
return flowRegistry;
|
||||
}
|
||||
|
||||
private void registerFlowLocations(DefaultFlowRegistry flowRegistry) {
|
||||
for (FlowLocation location : this.flowLocations) {
|
||||
String path = location.getPath();
|
||||
String id = location.getId();
|
||||
AttributeMap<Object> attributes = location.getAttributes();
|
||||
updateFlowAttributes(attributes);
|
||||
FlowDefinitionResource resource = this.flowResourceFactory.createResource(path, attributes, id);
|
||||
registerFlow(resource, flowRegistry);
|
||||
}
|
||||
}
|
||||
|
||||
private void registerFlowLocationPatterns(DefaultFlowRegistry flowRegistry) {
|
||||
for (String pattern : this.flowLocationPatterns) {
|
||||
AttributeMap<Object> attributes = new LocalAttributeMap<Object>();
|
||||
updateFlowAttributes(attributes);
|
||||
FlowDefinitionResource[] resources;
|
||||
try {
|
||||
resources = this.flowResourceFactory.createResources(pattern, attributes);
|
||||
} catch (IOException e) {
|
||||
IllegalStateException ise = new IllegalStateException(
|
||||
"An I/O Exception occurred resolving the flow location pattern '" + pattern + "'");
|
||||
ise.initCause(e);
|
||||
throw ise;
|
||||
}
|
||||
for (FlowDefinitionResource resource : resources) {
|
||||
registerFlow(resource, flowRegistry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void registerFlow(FlowDefinitionResource resource, DefaultFlowRegistry flowRegistry) {
|
||||
FlowModelBuilder flowModelBuilder = null;
|
||||
if (resource.getPath().getFilename().endsWith(".xml")) {
|
||||
flowModelBuilder = new XmlFlowModelBuilder(resource.getPath(), flowRegistry.getFlowModelRegistry());
|
||||
} else {
|
||||
throw new IllegalArgumentException(resource
|
||||
+ " is not a supported resource type; supported types are [.xml]");
|
||||
}
|
||||
FlowModelHolder flowModelHolder = new DefaultFlowModelHolder(flowModelBuilder);
|
||||
FlowBuilder flowBuilder = new FlowModelFlowBuilder(flowModelHolder);
|
||||
FlowBuilderContext builderContext = new FlowBuilderContextImpl(
|
||||
resource.getId(), resource.getAttributes(), flowRegistry, this.flowBuilderServices);
|
||||
FlowAssembler assembler = new FlowAssembler(flowBuilder, builderContext);
|
||||
DefaultFlowHolder flowHolder = new DefaultFlowHolder(assembler);
|
||||
|
||||
flowRegistry.getFlowModelRegistry().registerFlowModel(resource.getId(), flowModelHolder);
|
||||
flowRegistry.registerFlowDefinition(flowHolder);
|
||||
}
|
||||
|
||||
private void registerFlowBuilders(DefaultFlowRegistry flowRegistry) {
|
||||
for (FlowBuilderInfo info : this.flowBuilderInfos) {
|
||||
AttributeMap<Object> attributes = info.getAttributes();
|
||||
updateFlowAttributes(attributes);
|
||||
FlowBuilderContext builderContext = new FlowBuilderContextImpl(
|
||||
info.getId(), attributes, flowRegistry, this.flowBuilderServices);
|
||||
FlowAssembler assembler = new FlowAssembler(info.getBuilder(), builderContext);
|
||||
flowRegistry.registerFlowDefinition(assembler.assembleFlow());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateFlowAttributes(AttributeMap<Object> attributes) {
|
||||
if (this.flowBuilderServices.getDevelopment()) {
|
||||
attributes.asMap().put("development", true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class FlowLocation {
|
||||
|
||||
private final String path;
|
||||
|
||||
private final String id;
|
||||
|
||||
private final AttributeMap<Object> attributes;
|
||||
|
||||
|
||||
public FlowLocation(String path, String id, Map<String, Object> attributes) {
|
||||
this.path = path;
|
||||
this.id = id;
|
||||
this.attributes = (attributes != null) ?
|
||||
new LocalAttributeMap<Object>(attributes) :
|
||||
new LocalAttributeMap<Object>(Collections.<String, Object>emptyMap());
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return this.path;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public AttributeMap<Object> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
}
|
||||
|
||||
private static class FlowBuilderInfo {
|
||||
|
||||
private final FlowBuilder builder;
|
||||
|
||||
private final String id;
|
||||
|
||||
private final AttributeMap<Object> attributes;
|
||||
|
||||
public FlowBuilderInfo(FlowBuilder builder, String id, Map<String, Object> attributes) {
|
||||
this.builder = builder;
|
||||
this.id = id;
|
||||
this.attributes = (attributes != null) ?
|
||||
new LocalAttributeMap<Object>(attributes) :
|
||||
new LocalAttributeMap<Object>(Collections.<String, Object>emptyMap());
|
||||
}
|
||||
|
||||
public FlowBuilder getBuilder() {
|
||||
return this.builder;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public AttributeMap<Object> getAttributes() {
|
||||
return this.attributes;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.impl.SessionBindingConversationManager;
|
||||
import org.springframework.webflow.core.collection.LocalAttributeMap;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionLocator;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionFactory;
|
||||
import org.springframework.webflow.execution.FlowExecutionListener;
|
||||
import org.springframework.webflow.execution.factory.ConditionalFlowExecutionListenerLoader;
|
||||
import org.springframework.webflow.execution.factory.FlowExecutionListenerCriteriaFactory;
|
||||
import org.springframework.webflow.execution.repository.impl.DefaultFlowExecutionRepository;
|
||||
import org.springframework.webflow.execution.repository.snapshot.FlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SerializedFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.execution.repository.snapshot.SimpleFlowExecutionSnapshotFactory;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.executor.FlowExecutorImpl;
|
||||
import org.springframework.webflow.mvc.builder.MvcEnvironment;
|
||||
|
||||
/**
|
||||
* A builder for {@link FlowExecutor} instances designed for programmatic use in
|
||||
* {@code @Bean} factory methods. For XML configuration consider using the
|
||||
* {@code webflow-config} XML namespace.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @since 2.4
|
||||
*/
|
||||
public class FlowExecutorBuilder {
|
||||
|
||||
private final FlowDefinitionLocator flowRegistry;
|
||||
|
||||
private Integer maxFlowExecutions;
|
||||
|
||||
private Integer maxFlowExecutionSnapshots;
|
||||
|
||||
private MvcEnvironment environment;
|
||||
|
||||
private LocalAttributeMap<Object> executionAttributes = new LocalAttributeMap<Object>();
|
||||
|
||||
private ConditionalFlowExecutionListenerLoader listenerLoader;
|
||||
|
||||
private FlowExecutionListenerCriteriaFactory listenerCriteriaFactory = new FlowExecutionListenerCriteriaFactory();
|
||||
|
||||
private ConversationManager conversationManager;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new instance with the given flow registry and ApplicationContext.
|
||||
*
|
||||
* @param flowRegistry the flow registry that will locate flow definitions
|
||||
* @param applicationContext the Spring ApplicationContext to use for
|
||||
* initializing an instance of {@link MvcEnvironment}
|
||||
*/
|
||||
public FlowExecutorBuilder(FlowDefinitionLocator flowRegistry, ApplicationContext applicationContext) {
|
||||
Assert.notNull(flowRegistry, "FlowDefinitionLocator is required");
|
||||
Assert.notNull(applicationContext, "applicationContext is required");
|
||||
this.flowRegistry = flowRegistry;
|
||||
this.environment = MvcEnvironment.environmentFor(applicationContext);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the maximum number of allowed flow executions per user.
|
||||
* @param maxFlowExecutions the max flow executions
|
||||
*/
|
||||
public FlowExecutorBuilder setMaxFlowExecutions(int maxFlowExecutions) {
|
||||
this.maxFlowExecutions = maxFlowExecutions;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the maximum number of history snapshots allowed per flow execution.
|
||||
* @param maxFlowExecutionSnapshots the max flow execution snapshots
|
||||
*/
|
||||
public FlowExecutorBuilder setMaxFlowExecutionSnapshots(int maxFlowExecutionSnapshots) {
|
||||
this.maxFlowExecutionSnapshots = maxFlowExecutionSnapshots;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether flow executions should redirect after they pause before rendering.
|
||||
* @param redirectOnPause whether to redirect or not
|
||||
*/
|
||||
public FlowExecutorBuilder setAlwaysRedirectOnPause(boolean redirectOnPause) {
|
||||
this.executionAttributes.put("alwaysRedirectOnPause", redirectOnPause);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether flow executions redirect after they pause for transitions that remain
|
||||
* in the same view state. This attribute effectively overrides the value of the
|
||||
* "always-redirect-on-pause" attribute in same state transitions.
|
||||
* @param redirectInSameState whether to redirect or not
|
||||
*/
|
||||
public FlowExecutorBuilder setRedirectInSameState(boolean redirectInSameState) {
|
||||
this.executionAttributes.put("redirectInSameState", redirectInSameState);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a single flow execution meta attribute.
|
||||
* @param name the attribute name
|
||||
* @param value the attribute value
|
||||
*/
|
||||
public FlowExecutorBuilder addFlowExecutionAttribute(String name, Object value) {
|
||||
this.executionAttributes.put(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link FlowExecutionListener} that observes the lifecycle of all flow
|
||||
* executions launched by this executor.
|
||||
* @param listener the listener to be registered
|
||||
*/
|
||||
public FlowExecutorBuilder addFlowExecutionListener(FlowExecutionListener listener) {
|
||||
return addFlowExecutionListener(listener, "*");
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a {@link FlowExecutionListener} that observes the lifecycle of flow
|
||||
* executions launched by this executor.
|
||||
* @param listener the listener to be registered
|
||||
* @param criteria the criteria that determines the flow definitions a listener
|
||||
* should observe, delimited by commas or '*' for "all".
|
||||
* Example: 'flow1,flow2,flow3'.
|
||||
*/
|
||||
public FlowExecutorBuilder addFlowExecutionListener(FlowExecutionListener listener, String criteria) {
|
||||
if (this.listenerLoader == null) {
|
||||
this.listenerLoader = new ConditionalFlowExecutionListenerLoader();
|
||||
}
|
||||
this.listenerLoader.addListener(listener, this.listenerCriteriaFactory.getListenerCriteria(criteria));
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ConversationManager implementation to use for storing conversations
|
||||
* in the session effectively controlling how state is stored physically when
|
||||
* a flow execution is paused.. Note that when this attribute is provided, the
|
||||
* "max-execution-snapshots" attribute is meaningless.
|
||||
* @param conversationManager the ConversationManager instance to use
|
||||
*/
|
||||
public FlowExecutorBuilder setConversationManager(ConversationManager conversationManager) {
|
||||
this.conversationManager = conversationManager;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create and return a {@link FlowExecutor} instance.
|
||||
*/
|
||||
public FlowExecutor build() {
|
||||
FlowExecutionImplFactory executionFactory = getExecutionFactory();
|
||||
DefaultFlowExecutionRepository executionRepository = getFlowExecutionRepository(executionFactory);
|
||||
executionFactory.setExecutionKeyFactory(executionRepository);
|
||||
return new FlowExecutorImpl(this.flowRegistry, executionFactory, executionRepository);
|
||||
}
|
||||
|
||||
|
||||
private FlowExecutionImplFactory getExecutionFactory() {
|
||||
FlowExecutionImplFactory executionFactory = new FlowExecutionImplFactory();
|
||||
executionFactory.setExecutionAttributes(getExecutionAttributes());
|
||||
if (this.listenerLoader != null) {
|
||||
executionFactory.setExecutionListenerLoader(this.listenerLoader);
|
||||
}
|
||||
return executionFactory;
|
||||
}
|
||||
|
||||
private DefaultFlowExecutionRepository getFlowExecutionRepository(FlowExecutionFactory executionFactory) {
|
||||
ConversationManager manager = getConversationManager();
|
||||
FlowExecutionSnapshotFactory snapshotFactory = getSnapshotFactory(executionFactory);
|
||||
DefaultFlowExecutionRepository repository = new DefaultFlowExecutionRepository(manager, snapshotFactory);
|
||||
if (this.maxFlowExecutionSnapshots != null) {
|
||||
repository.setMaxSnapshots((this.maxFlowExecutionSnapshots == 0) ? 1 : this.maxFlowExecutionSnapshots);
|
||||
}
|
||||
return repository;
|
||||
}
|
||||
|
||||
private ConversationManager getConversationManager() {
|
||||
ConversationManager manager = this.conversationManager;
|
||||
if (manager == null) {
|
||||
manager = new SessionBindingConversationManager();
|
||||
}
|
||||
if (this.maxFlowExecutions != null && manager instanceof SessionBindingConversationManager) {
|
||||
((SessionBindingConversationManager) manager).setMaxConversations(this.maxFlowExecutions);
|
||||
}
|
||||
return manager;
|
||||
}
|
||||
|
||||
private FlowExecutionSnapshotFactory getSnapshotFactory(FlowExecutionFactory executionFactory) {
|
||||
FlowExecutionSnapshotFactory factory = null;
|
||||
if (this.maxFlowExecutionSnapshots != null && this.maxFlowExecutionSnapshots == 0) {
|
||||
factory = new SimpleFlowExecutionSnapshotFactory(executionFactory, this.flowRegistry);
|
||||
}
|
||||
else {
|
||||
factory = new SerializedFlowExecutionSnapshotFactory(executionFactory, this.flowRegistry);
|
||||
}
|
||||
return factory;
|
||||
}
|
||||
|
||||
private LocalAttributeMap<Object> getExecutionAttributes() {
|
||||
LocalAttributeMap<Object> attributes = new LocalAttributeMap<Object>(this.executionAttributes.asMap());
|
||||
if (!attributes.contains("alwaysRedirectOnPause")) {
|
||||
attributes.put("alwaysRedirectOnPause", (this.environment != MvcEnvironment.PORTLET));
|
||||
}
|
||||
if (!attributes.contains("redirectInSameState")) {
|
||||
attributes.put("redirectInSameState", (this.environment != MvcEnvironment.PORTLET));
|
||||
}
|
||||
return attributes;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -411,7 +411,7 @@ Determines if flow executions always redirect after they pause.
|
||||
<xsd:documentation>
|
||||
<![CDATA[
|
||||
Determines if flow executions redirect after they pause for transitions that remain in the same view state.
|
||||
This attribute effectively overrides the value of the "always-redirect-on-pause" attribute in same state tranisitions.
|
||||
This attribute effectively overrides the value of the "always-redirect-on-pause" attribute in same state transitions.
|
||||
]]>
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
public abstract class AbstractFlowBuilderServicesConfigurationTests extends TestCase {
|
||||
|
||||
protected ApplicationContext context;
|
||||
|
||||
protected FlowBuilderServices builderServices;
|
||||
|
||||
public void setUp() {
|
||||
context = initApplicationContext();
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
||||
public void testFlowBuilderServicesDefaultConfig() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesDefault");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
|
||||
assertTrue(builderServices.getConversionService() instanceof DefaultConversionService);
|
||||
assertNull(builderServices.getValidator());
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesAllCustomized() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesAllCustom");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getValidator() instanceof EmptySpringValidator);
|
||||
assertTrue(builderServices.getValidationHintResolver() instanceof MyBeanValidationHintResolver);
|
||||
assertTrue(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesConversionServiceCustomized() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesConversionServiceCustom");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
|
||||
assertNull(builderServices.getValidator());
|
||||
assertNull(builderServices.getValidationHintResolver());
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public static class TestViewFactoryCreator implements ViewFactoryCreator {
|
||||
|
||||
public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
|
||||
ConversionService conversionService, BinderConfiguration binderConfiguration,
|
||||
Validator validator, ValidationHintResolver validationHintResolver) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public String getViewIdByConvention(String viewStateId) {
|
||||
return viewStateId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestConversionService implements ConversionService {
|
||||
|
||||
public Object executeConversion(Object source, Class<?> targetClass) throws ConversionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class<?> targetClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Set<ConversionExecutor> getConversionExecutors(Class<?> sourceClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Class<?> getClassForAlias(String alias) throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationException;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.ConversationParameters;
|
||||
import org.springframework.webflow.core.collection.AttributeMap;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.execution.FlowExecutionListenerAdapter;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.executor.FlowExecutorImpl;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
|
||||
public abstract class AbstractFlowExecutorConfigurationTests extends TestCase {
|
||||
|
||||
private ApplicationContext context;
|
||||
|
||||
public void setUp() {
|
||||
context = initApplicationContext();
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
||||
|
||||
public void testConfigOk() {
|
||||
FlowExecutor executor = context.getBean("flowExecutor", FlowExecutor.class);
|
||||
executor.launchExecution("flow", null, new MockExternalContext());
|
||||
FlowExecutor executor2 = context.getBean("flowExecutorSimpleRepo", FlowExecutor.class);
|
||||
executor2.launchExecution("flow", null, new MockExternalContext());
|
||||
}
|
||||
|
||||
public void testCustomConversationManager() {
|
||||
FlowExecutorImpl executor = context.getBean("flowExecutor", FlowExecutorImpl.class);
|
||||
try {
|
||||
executor.getExecutionRepository().parseFlowExecutionKey("e1s1");
|
||||
fail("ExceptionThrowingConversationManager would have raised an exception");
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigurationListener extends FlowExecutionListenerAdapter {
|
||||
|
||||
public void sessionCreating(RequestContext context, FlowDefinition definition) {
|
||||
AttributeMap<Object> attributes = context.getFlowExecutionContext().getAttributes();
|
||||
assertEquals(4, attributes.size());
|
||||
assertEquals(Boolean.FALSE, attributes.getBoolean("alwaysRedirectOnPause"));
|
||||
assertEquals(Boolean.TRUE, attributes.getBoolean("redirectInSameState"));
|
||||
assertEquals("bar", attributes.get("foo"));
|
||||
assertEquals(new Integer(2), attributes.get("bar"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExceptionThrowingConversationManager implements ConversationManager {
|
||||
|
||||
public Conversation beginConversation(ConversationParameters params) throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Conversation getConversation(ConversationId id) throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConversationId parseConversationId(String encodedId) throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,77 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException;
|
||||
|
||||
public abstract class AbstractFlowRegistryConfigurationTests extends TestCase {
|
||||
|
||||
protected ApplicationContext context;
|
||||
|
||||
protected FlowDefinitionRegistry registry;
|
||||
|
||||
public void setUp() {
|
||||
this.context = initApplicationContext();
|
||||
this.registry = (FlowDefinitionRegistry) context.getBean("flowRegistry");
|
||||
}
|
||||
|
||||
protected abstract ApplicationContext initApplicationContext();
|
||||
|
||||
|
||||
public void testRegistryFlowLocationsPopulated() {
|
||||
FlowDefinition flow = registry.getFlowDefinition("flow");
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("bar", flow.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(2), flow.getAttributes().get("bar"));
|
||||
}
|
||||
|
||||
public void testRegistryFlowLocationPatternsPopulated() {
|
||||
FlowDefinition flow1 = registry.getFlowDefinition("flow1");
|
||||
assertEquals("flow1", flow1.getId());
|
||||
FlowDefinition flow2 = registry.getFlowDefinition("flow2");
|
||||
assertEquals("flow2", flow2.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulated() {
|
||||
FlowDefinition foo = registry.getFlowDefinition("foo");
|
||||
assertEquals("foo", foo.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulatedWithId() {
|
||||
FlowDefinition foo = registry.getFlowDefinition("foo2");
|
||||
assertEquals("foo2", foo.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulatedWithAttributes() {
|
||||
FlowDefinition foo3 = registry.getFlowDefinition("foo3");
|
||||
assertEquals("foo3", foo3.getId());
|
||||
assertEquals("bar", foo3.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(2), foo3.getAttributes().get("bar"));
|
||||
}
|
||||
|
||||
public void testNoSuchFlow() {
|
||||
try {
|
||||
registry.getFlowDefinition("not there");
|
||||
} catch (NoSuchFlowDefinitionException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testBogusPath() {
|
||||
try {
|
||||
registry.getFlowDefinition("bogus");
|
||||
fail("Should have failed");
|
||||
} catch (FlowDefinitionConstructionException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testParent() {
|
||||
assertNotNull(registry.getParent());
|
||||
assertEquals("parentFlow", registry.getParent().getFlowDefinition("parentFlow").getId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,115 +1,13 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionExecutorNotFoundException;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.validation.Validator;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.springframework.webflow.engine.builder.ViewFactoryCreator;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
|
||||
import org.springframework.webflow.validation.ValidationHintResolver;
|
||||
|
||||
public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
|
||||
|
||||
private ClassPathXmlApplicationContext context;
|
||||
private FlowBuilderServices builderServices;
|
||||
|
||||
public void setUp() {
|
||||
context = new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-builder-services.xml");
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesDefaultConfig() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesDefault");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
|
||||
assertTrue(builderServices.getConversionService() instanceof DefaultConversionService);
|
||||
assertNull(builderServices.getValidator());
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesAllCustomized() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesAllCustom");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof TestViewFactoryCreator);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getValidator() instanceof EmptySpringValidator);
|
||||
assertTrue(builderServices.getValidationHintResolver() instanceof MyBeanValidationHintResolver);
|
||||
assertTrue(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public void testFlowBuilderServicesConversionServiceCustomized() {
|
||||
builderServices = (FlowBuilderServices) context.getBean("flowBuilderServicesConversionServiceCustom");
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
|
||||
assertNull(builderServices.getValidator());
|
||||
assertNull(builderServices.getValidationHintResolver());
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
|
||||
public static class TestViewFactoryCreator implements ViewFactoryCreator {
|
||||
|
||||
public ViewFactory createViewFactory(Expression viewIdExpression, ExpressionParser expressionParser,
|
||||
ConversionService conversionService, BinderConfiguration binderConfiguration,
|
||||
Validator validator, ValidationHintResolver validationHintResolver) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public String getViewIdByConvention(String viewStateId) {
|
||||
return viewStateId;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class TestConversionService implements ConversionService {
|
||||
|
||||
public Object executeConversion(Object source, Class<?> targetClass) throws ConversionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Object executeConversion(String converterId, Object source, Class<?> targetClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class<?> sourceClass, Class<?> targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Set<ConversionExecutor> getConversionExecutors(Class<?> sourceClass) {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public Class<?> getClassForAlias(String alias) throws ConversionExecutionException {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
public class FlowBuilderServicesBeanDefinitionParserTests extends AbstractFlowBuilderServicesConfigurationTests {
|
||||
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-builder-services.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
|
||||
public class FlowBuilderServicesJavaConfigTests extends AbstractFlowBuilderServicesConfigurationTests {
|
||||
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(WebFlowConfig.class);
|
||||
}
|
||||
|
||||
|
||||
static class WebFlowConfig extends AbstractFlowConfiguration {
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesDefault() {
|
||||
return getFlowBuilderServicesBuilder().build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesAllCustom() {
|
||||
return getFlowBuilderServicesBuilder()
|
||||
.setExpressionParser(customExpressionParser())
|
||||
.setViewFactoryCreator(customViewFactoryCreator())
|
||||
.setConversionService(customConversionService())
|
||||
.setValidator(customValidator())
|
||||
.setValidationHintResolver(customValidationHintResolver())
|
||||
.setDevelopmentMode(true)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowBuilderServices flowBuilderServicesConversionServiceCustom() {
|
||||
return getFlowBuilderServicesBuilder()
|
||||
.setConversionService(customConversionService())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public WebFlowSpringELExpressionParser customExpressionParser() {
|
||||
return new WebFlowSpringELExpressionParser(new SpelExpressionParser());
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestViewFactoryCreator customViewFactoryCreator() {
|
||||
return new TestViewFactoryCreator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public TestConversionService customConversionService() {
|
||||
return new TestConversionService();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public EmptySpringValidator customValidator() {
|
||||
return new EmptySpringValidator();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MyBeanValidationHintResolver customValidationHintResolver() {
|
||||
return new MyBeanValidationHintResolver();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
|
||||
public class FlowDefinitionRegistryJavaConfigTests extends AbstractFlowRegistryConfigurationTests {
|
||||
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(WebFlowConfig.class);
|
||||
}
|
||||
|
||||
|
||||
static class WebFlowConfig extends AbstractFlowConfiguration {
|
||||
|
||||
@Bean
|
||||
public FlowDefinitionRegistry flowRegistry() {
|
||||
|
||||
Map<String, Object> flowAttributes = new HashMap<String, Object>();
|
||||
flowAttributes.put("foo", "bar");
|
||||
flowAttributes.put("bar", 2);
|
||||
|
||||
return getFlowDefinitionRegistryBuilder().setParent(parentRegistry())
|
||||
.addFlowLocation("org/springframework/webflow/config/flow.xml", "flow", flowAttributes)
|
||||
.addFlowLocation("/some/path/that/is/bogus.xml")
|
||||
.addFlowLocationPattern("org/springframework/webflow/config/flows/*.xml")
|
||||
.addFlowBuilder(new FooFlowBuilder())
|
||||
.addFlowBuilder(new FooFlowBuilder(), "foo2")
|
||||
.addFlowBuilder(new FooFlowBuilder(), "foo3", flowAttributes)
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowDefinitionRegistry parentRegistry() {
|
||||
return getFlowDefinitionRegistryBuilder()
|
||||
.addFlowLocation("org/springframework/webflow/config/flow.xml", "parentFlow")
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,70 +1,12 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.webflow.conversation.Conversation;
|
||||
import org.springframework.webflow.conversation.ConversationException;
|
||||
import org.springframework.webflow.conversation.ConversationId;
|
||||
import org.springframework.webflow.conversation.ConversationManager;
|
||||
import org.springframework.webflow.conversation.ConversationParameters;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.execution.FlowExecutionListenerAdapter;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
import org.springframework.webflow.executor.FlowExecutorImpl;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
|
||||
public class FlowExecutorBeanDefinitionParserTests extends TestCase {
|
||||
private ClassPathXmlApplicationContext context;
|
||||
|
||||
public void setUp() {
|
||||
context = new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-executor.xml");
|
||||
}
|
||||
|
||||
public void testConfigOk() {
|
||||
FlowExecutor executor = context.getBean("flowExecutor", FlowExecutor.class);
|
||||
executor.launchExecution("flow", null, new MockExternalContext());
|
||||
FlowExecutor executor2 = context.getBean("flowExecutorSimpleRepo", FlowExecutor.class);
|
||||
executor2.launchExecution("flow", null, new MockExternalContext());
|
||||
}
|
||||
|
||||
public void testCustomConversationManager() {
|
||||
FlowExecutorImpl executor = context.getBean("flowExecutor", FlowExecutorImpl.class);
|
||||
try {
|
||||
executor.getExecutionRepository().parseFlowExecutionKey("e1s1");
|
||||
fail("ExceptionThrowingConversationManager would have raised an exception");
|
||||
} catch (UnsupportedOperationException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public static class ConfigurationListener extends FlowExecutionListenerAdapter {
|
||||
public void sessionCreating(RequestContext context, FlowDefinition definition) {
|
||||
assertEquals(4, context.getFlowExecutionContext().getAttributes().size());
|
||||
assertEquals(Boolean.FALSE,
|
||||
context.getFlowExecutionContext().getAttributes().getBoolean("alwaysRedirectOnPause"));
|
||||
assertEquals(Boolean.TRUE,
|
||||
context.getFlowExecutionContext().getAttributes().getBoolean("redirectInSameState"));
|
||||
assertEquals("bar", context.getFlowExecutionContext().getAttributes().get("foo"));
|
||||
assertEquals(new Integer(2), context.getFlowExecutionContext().getAttributes().get("bar"));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ExceptionThrowingConversationManager implements ConversationManager {
|
||||
|
||||
public Conversation beginConversation(ConversationParameters conversationParameters)
|
||||
throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Conversation getConversation(ConversationId id) throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public ConversationId parseConversationId(String encodedId) throws ConversationException {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
public class FlowExecutorBeanDefinitionParserTests extends AbstractFlowExecutorConfigurationTests {
|
||||
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-executor.xml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.executor.FlowExecutor;
|
||||
|
||||
/**
|
||||
* Tests for configuring Web Flow by extending {@link AbstractFlowConfiguration}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class FlowExecutorJavaConfigTests extends AbstractFlowExecutorConfigurationTests {
|
||||
|
||||
@Override
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new AnnotationConfigApplicationContext(WebFlowConfig.class);
|
||||
}
|
||||
|
||||
|
||||
@Configuration
|
||||
static class WebFlowConfig extends AbstractFlowConfiguration {
|
||||
|
||||
@Bean
|
||||
public FlowExecutor flowExecutor() {
|
||||
return getFlowExecutorBuilder(flowRegistry())
|
||||
.setMaxFlowExecutions(1).setMaxFlowExecutionSnapshots(2)
|
||||
.setConversationManager(new ExceptionThrowingConversationManager())
|
||||
.setAlwaysRedirectOnPause(false)
|
||||
.setRedirectInSameState(true)
|
||||
.addFlowExecutionAttribute("foo", "bar")
|
||||
.addFlowExecutionAttribute("bar", 2)
|
||||
.addFlowExecutionListener(new ConfigurationListener(), "*")
|
||||
.build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowDefinitionRegistry flowRegistry() {
|
||||
return getFlowDefinitionRegistryBuilder()
|
||||
.addFlowLocation("org/springframework/webflow/config/flow.xml").build();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public FlowExecutor flowExecutorSimpleRepo() {
|
||||
return getFlowExecutorBuilder(flowRegistry())
|
||||
.setMaxFlowExecutions(1).setMaxFlowExecutionSnapshots(0)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -2,56 +2,17 @@ package org.springframework.webflow.config;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
import org.springframework.webflow.definition.FlowDefinition;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionConstructionException;
|
||||
import org.springframework.webflow.definition.registry.FlowDefinitionRegistry;
|
||||
import org.springframework.webflow.definition.registry.NoSuchFlowDefinitionException;
|
||||
import org.springframework.webflow.engine.builder.support.FlowBuilderServices;
|
||||
import org.springframework.webflow.mvc.builder.MvcViewFactoryCreator;
|
||||
|
||||
public class FlowRegistryBeanDefinitionParserTests extends TestCase {
|
||||
private ClassPathXmlApplicationContext context;
|
||||
private FlowDefinitionRegistry registry;
|
||||
public class FlowRegistryBeanDefinitionParserTests extends AbstractFlowRegistryConfigurationTests {
|
||||
|
||||
public void setUp() {
|
||||
context = new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-registry.xml");
|
||||
registry = (FlowDefinitionRegistry) context.getBean("flowRegistry");
|
||||
}
|
||||
|
||||
public void testRegistryFlowLocationsPopulated() {
|
||||
FlowDefinition flow = registry.getFlowDefinition("flow");
|
||||
assertEquals("flow", flow.getId());
|
||||
assertEquals("bar", flow.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(2), flow.getAttributes().get("bar"));
|
||||
}
|
||||
|
||||
public void testRegistryFlowLocationPatternsPopulated() {
|
||||
FlowDefinition flow1 = registry.getFlowDefinition("flow1");
|
||||
assertEquals("flow1", flow1.getId());
|
||||
FlowDefinition flow2 = registry.getFlowDefinition("flow2");
|
||||
assertEquals("flow2", flow2.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulated() {
|
||||
FlowDefinition foo = registry.getFlowDefinition("foo");
|
||||
assertEquals("foo", foo.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulatedWithId() {
|
||||
FlowDefinition foo = registry.getFlowDefinition("foo2");
|
||||
assertEquals("foo2", foo.getId());
|
||||
}
|
||||
|
||||
public void testRegistryFlowBuildersPopulatedWithAttributes() {
|
||||
FlowDefinition foo3 = registry.getFlowDefinition("foo3");
|
||||
assertEquals("foo3", foo3.getId());
|
||||
assertEquals("bar", foo3.getAttributes().get("foo"));
|
||||
assertEquals(new Integer(2), foo3.getAttributes().get("bar"));
|
||||
protected ApplicationContext initApplicationContext() {
|
||||
return new ClassPathXmlApplicationContext("org/springframework/webflow/config/flow-registry.xml");
|
||||
}
|
||||
|
||||
public void testDefaultFlowBuilderServices() {
|
||||
@@ -66,24 +27,4 @@ public class FlowRegistryBeanDefinitionParserTests extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNoSuchFlow() {
|
||||
try {
|
||||
registry.getFlowDefinition("not there");
|
||||
} catch (NoSuchFlowDefinitionException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void testBogusPath() {
|
||||
try {
|
||||
registry.getFlowDefinition("bogus");
|
||||
fail("Should have failed");
|
||||
} catch (FlowDefinitionConstructionException e) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testParent() {
|
||||
assertNotNull(registry.getParent());
|
||||
assertEquals("parentFlow", registry.getParent().getFlowDefinition("parentFlow").getId());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,9 +27,11 @@
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean id="customViewFactoryCreator" class="org.springframework.webflow.config.FlowBuilderServicesBeanDefinitionParserTests$TestViewFactoryCreator"/>
|
||||
<bean id="customViewFactoryCreator"
|
||||
class="org.springframework.webflow.config.AbstractFlowBuilderServicesConfigurationTests$TestViewFactoryCreator"/>
|
||||
|
||||
<bean id="customConversionService" class="org.springframework.webflow.config.FlowBuilderServicesBeanDefinitionParserTests$TestConversionService"/>
|
||||
<bean id="customConversionService"
|
||||
class="org.springframework.webflow.config.AbstractFlowBuilderServicesConfigurationTests$TestConversionService"/>
|
||||
|
||||
<bean id="customValidator" class="org.springframework.webflow.config.EmptySpringValidator" />
|
||||
|
||||
|
||||
@@ -21,9 +21,11 @@
|
||||
</webflow:flow-execution-listeners>
|
||||
</webflow:flow-executor>
|
||||
|
||||
<bean id="listener" class="org.springframework.webflow.config.FlowExecutorBeanDefinitionParserTests$ConfigurationListener" />
|
||||
<bean id="listener"
|
||||
class="org.springframework.webflow.config.AbstractFlowExecutorConfigurationTests$ConfigurationListener" />
|
||||
|
||||
<bean id="conversationManager" class="org.springframework.webflow.config.FlowExecutorBeanDefinitionParserTests.ExceptionThrowingConversationManager" />
|
||||
<bean id="conversationManager"
|
||||
class="org.springframework.webflow.config.AbstractFlowExecutorConfigurationTests.ExceptionThrowingConversationManager" />
|
||||
|
||||
<webflow:flow-registry id="flowRegistry">
|
||||
<webflow:flow-location path="org/springframework/webflow/config/flow.xml" />
|
||||
|
||||
Reference in New Issue
Block a user