mvc binding tests

conversion context change
This commit is contained in:
Keith Donald
2008-03-20 22:00:14 +00:00
parent ddee81604a
commit b7acf27f31
38 changed files with 379 additions and 171 deletions

View File

@@ -47,6 +47,6 @@ public interface ConversionExecutor {
* @param source the source object to convert
* @param context the conversion context, useful for influencing the behavior of the converter
*/
public Object execute(Object source, ConversionContext context) throws ConversionException;
public Object execute(Object source, Object context) throws ConversionException;
}

View File

@@ -52,6 +52,6 @@ public interface Converter {
* @return the converted object, an instance of the target type
* @throws ConversionException an exception occurred during the type conversion
*/
public Object convert(Object source, Class targetClass, ConversionContext context) throws ConversionException;
public Object convert(Object source, Class targetClass, Object context) throws ConversionException;
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.Converter;
@@ -58,11 +57,11 @@ public abstract class AbstractConverter implements Converter {
* @return the converted object
* @throws ConversionException an exception occured converting the source value
*/
public Object convert(Object source, ConversionContext context) throws ConversionException {
public Object convert(Object source, Object context) throws ConversionException {
return convert(source, getTargetClasses()[0], context);
}
public Object convert(Object source, Class targetClass, ConversionContext context) throws ConversionException {
public Object convert(Object source, Class targetClass, Object context) throws ConversionException {
try {
return doConvert(source, targetClass, context);
} catch (ConversionException e) {
@@ -82,8 +81,8 @@ public abstract class AbstractConverter implements Converter {
* @param targetClass the target type to convert to
* @param context an optional conversion context that may be used to influence the conversion process, could be null
* @return the converted source value
* @throws Exception an exception occured, will be wrapped in a conversion exception if necessary
* @throws Exception an exception occurred, will be wrapped in a conversion exception if necessary
*/
protected abstract Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception;
protected abstract Object doConvert(Object source, Class targetClass, Object context) throws Exception;
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.format.FormatterRegistry;
import org.springframework.util.Assert;
@@ -45,7 +44,7 @@ public abstract class AbstractFormattingConverter extends AbstractConverter {
return formatterRegistry;
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
return getFormatterRegistry().getFormatter(targetClass).parseValue((String) source);
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.Converter;
@@ -91,7 +90,7 @@ class ConversionExecutorImpl implements ConversionExecutor {
return execute(source, null);
}
public Object execute(Object source, ConversionContext context) throws ConversionException {
public Object execute(Object source, Object context) throws ConversionException {
if (targetClass.isInstance(source)) {
// source is already assignment compatible with target class
return source;

View File

@@ -1,35 +0,0 @@
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.format.Formatter;
public class FormatterBackedConversionExecutor implements ConversionExecutor {
private Formatter formatter;
private Class targetClass;
public FormatterBackedConversionExecutor(Formatter formatter, Class targetClass) {
this.formatter = formatter;
this.targetClass = targetClass;
}
public Object execute(Object source) throws ConversionException {
return execute(source, null);
}
public Object execute(Object source, ConversionContext context) throws ConversionException {
return formatter.parseValue((String) source);
}
public Class getSourceClass() {
return String.class;
}
public Class getTargetClass() {
return targetClass;
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
/**
* Package private converter that is a "no op".
@@ -36,7 +35,7 @@ class NoOpConverter extends AbstractConverter {
this.targetClass = targetClass;
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
return source;
}

View File

@@ -1,6 +1,5 @@
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.convert.ConversionService;
@@ -52,7 +51,7 @@ public class RuntimeBindingConversionExecutor implements ConversionExecutor {
return execute(source, null);
}
public Object execute(Object source, ConversionContext context) throws ConversionException {
public Object execute(Object source, Object context) throws ConversionException {
return conversionService.getConversionExecutor(source.getClass(), targetClass).execute(source);
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.util.StringUtils;
/**
@@ -71,7 +70,7 @@ public class TextToBoolean extends AbstractConverter {
return new Class[] { Boolean.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
String text = (String) source;
if (!StringUtils.hasText(text)) {
return null;

View File

@@ -20,7 +20,6 @@ import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.core.enums.LabeledEnum;
import org.springframework.util.ClassUtils;
import org.springframework.util.StringUtils;
@@ -53,7 +52,7 @@ public class TextToClass extends AbstractConverter {
return new Class[] { Class.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
String text = (String) source;
if (StringUtils.hasText(text)) {
text = text.trim();

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.binding.convert.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.core.enums.LabeledEnum;
import org.springframework.core.enums.LabeledEnumResolver;
import org.springframework.core.enums.StaticLabeledEnumResolver;
@@ -37,7 +36,7 @@ public class TextToLabeledEnum extends AbstractConverter {
return new Class[] { LabeledEnum.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
String label = (String) source;
return labeledEnumResolver.getLabeledEnumByLabel(targetClass, label);
}

View File

@@ -26,11 +26,10 @@ import org.springframework.util.ObjectUtils;
*/
public final class StaticExpression implements Expression {
/**
* The value expression.
*/
private Object value;
private String expressionString;
/**
* Create a static evaluator for the given value.
* @param value the value
@@ -64,11 +63,19 @@ public final class StaticExpression implements Expression {
}
public Class getValueType(Object context) {
return Object.class;
return value.getClass();
}
public String getExpressionString() {
return null;
return expressionString;
}
/**
* Sets the static expression string.
* @param expressionString the static expression string
*/
public void setExpressionString(String expressionString) {
this.expressionString = expressionString;
}
public String toString() {

View File

@@ -23,6 +23,7 @@ import org.springframework.binding.convert.ConversionService;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.mapping.Mapping;
import org.springframework.core.style.StylerUtils;
import org.springframework.util.Assert;
/**
@@ -128,7 +129,7 @@ public class DefaultMapping implements Mapping {
if (sourceValue != null) {
if (typeConverter != null) {
try {
targetValue = typeConverter.execute(targetValue);
targetValue = typeConverter.execute(targetValue, context);
} catch (ConversionException e) {
context.setTypeConversionErrorResult(sourceValue, e.getTargetClass());
return;
@@ -147,7 +148,7 @@ public class DefaultMapping implements Mapping {
try {
ConversionExecutor typeConverter = conversionService.getConversionExecutor(sourceValue
.getClass(), targetType);
targetValue = typeConverter.execute(sourceValue);
targetValue = typeConverter.execute(sourceValue, context);
} catch (ConversionException e) {
context.setTypeConversionErrorResult(sourceValue, e.getTargetClass());
return;
@@ -156,12 +157,15 @@ public class DefaultMapping implements Mapping {
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("Mapping '" + sourceExpression + "' value [" + sourceValue + "] to target '"
+ targetExpression + "'; setting target value to [" + targetValue + "]");
}
try {
targetExpression.setValue(context.getTarget(), targetValue);
if (logger.isDebugEnabled()) {
String sourceType = sourceValue != null ? sourceValue.getClass().getName() : "null";
String targetType = targetValue != null ? targetValue.getClass().getName() : "null";
logger.debug("Mapped source [" + sourceType + "] " + sourceExpression + " value "
+ StylerUtils.style(sourceValue) + " to target [" + targetType + "] " + targetExpression
+ " value " + StylerUtils.style(targetValue));
}
context.setSuccessResult(sourceValue, targetValue);
} catch (EvaluationException e) {
context.setTargetAccessError(sourceValue, e);
@@ -191,4 +195,5 @@ public class DefaultMapping implements Mapping {
public String toString() {
return sourceExpression + " -> " + targetExpression;
}
}

View File

@@ -49,6 +49,10 @@ class DefaultMappingContext implements MappingContext {
return conversionService;
}
public Mapping getCurrentMapping() {
return currentMapping;
}
public void setCurrentMapping(Mapping mapping) {
if (this.currentMapping != null) {
throw new IllegalStateException("The current mapping has not finished yet");

View File

@@ -42,6 +42,12 @@ public interface MappingContext {
*/
public ConversionService getConversionService();
/**
* Returns the current mapping.
* @return the current mapping
*/
public Mapping getCurrentMapping();
/**
* Sets the current mapping. Called when a single mapping operation is about to begin. This updates progress of the
* overall mapping transaction.

View File

@@ -19,7 +19,6 @@ import java.util.Date;
import junit.framework.TestCase;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
/**
@@ -65,7 +64,7 @@ public class ConversionExecutorImplTests extends TestCase {
return new Class[] { Date.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
return source == null ? null : new Date();
}
}

View File

@@ -20,13 +20,12 @@ import java.util.List;
import javax.faces.model.DataModel;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.support.AbstractConverter;
import org.springframework.util.ClassUtils;
public class DataModelConverter extends AbstractConverter {
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
Constructor emptyConstructor = ClassUtils.getConstructorIfAvailable(targetClass, new Class[] {});
DataModel model = (DataModel) emptyConstructor.newInstance(new Object[] {});
model.setWrappedData(source);

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
<classpathentry kind="src" path="src/main/java"/>
<classpathentry kind="src" path="src/main/resources"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
<classpathentry combineaccessrules="false" kind="src" path="/spring-binding"/>

View File

@@ -15,7 +15,7 @@
*/
package org.springframework.webflow.definition;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
/**
* An interface to be implemented by objects that are annotated with attributes they wish to expose to clients.
@@ -38,10 +38,10 @@ public interface Annotated {
public String getDescription();
/**
* Returns an immutable attribute map containing the attributes annotating this object. These attributes provide
* descriptive characteristics or properties that may affect object behavior.
* Returns a attribute map containing the attributes annotating this object. These attributes provide descriptive
* characteristics or properties that may affect object behavior.
* @return the attribute map
*/
public AttributeMap getAttributes();
public MutableAttributeMap getAttributes();
}

View File

@@ -92,7 +92,7 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
* @see #postProcessResult(Event)
*/
public String getName() {
return getAttributeMap().getString(NAME_ATTRIBUTE);
return getAttributes().getString(NAME_ATTRIBUTE);
}
/**
@@ -100,7 +100,7 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
* @param name the action name
*/
public void setName(String name) {
getAttributeMap().put(NAME_ATTRIBUTE, name);
getAttributes().put(NAME_ATTRIBUTE, name);
}
/**
@@ -116,7 +116,7 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
* Returns the name of the action method to invoke when the target action is executed.
*/
public String getMethod() {
return getAttributeMap().getString(METHOD_ATTRIBUTE);
return getAttributes().getString(METHOD_ATTRIBUTE);
}
/**
@@ -124,7 +124,7 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
* @param method the action method name
*/
public void setMethod(String method) {
getAttributeMap().put(METHOD_ATTRIBUTE, method);
getAttributes().put(METHOD_ATTRIBUTE, method);
}
/**
@@ -132,17 +132,16 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
* @param attributeName the name of the attribute to set
* @param attributeValue the value of the attribute
* @return this object, to support call chaining
* @since 1.0.4
*/
public AnnotatedAction putAttribute(String attributeName, Object attributeValue) {
getAttributeMap().put(attributeName, attributeValue);
getAttributes().put(attributeName, attributeValue);
return this;
}
public Event execute(RequestContext context) throws Exception {
AttributeMap originalAttributes = getAttributeMap();
AttributeMap originalAttributes = getAttributes();
try {
context.setAttributes(getAttributeMap());
context.setAttributes(getAttributes());
Event result = getTargetAction().execute(context);
return postProcessResult(result);
} finally {
@@ -171,7 +170,7 @@ public class AnnotatedAction extends AnnotatedObject implements Action {
}
public String toString() {
return new ToStringCreator(this).append("targetAction", getTargetAction()).append("attributes",
getAttributeMap()).toString();
return new ToStringCreator(this).append("targetAction", getTargetAction())
.append("attributes", getAttributes()).toString();
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.webflow.engine;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.Annotated;
@@ -56,7 +55,7 @@ public abstract class AnnotatedObject implements Annotated {
return attributes.getString(DESCRIPTION_PROPERTY);
}
public AttributeMap getAttributes() {
public MutableAttributeMap getAttributes() {
return attributes;
}
@@ -78,10 +77,4 @@ public abstract class AnnotatedObject implements Annotated {
attributes.put(DESCRIPTION_PROPERTY, description);
}
/**
* Returns the mutable attribute map for this annotated object. May be used to set attributes after construction.
*/
public MutableAttributeMap getAttributeMap() {
return attributes;
}
}

View File

@@ -196,7 +196,7 @@ public class Flow extends AnnotatedObject implements FlowDefinition {
*/
public static Flow create(String id, AttributeMap attributes) {
Flow flow = new Flow(id);
flow.getAttributeMap().putAll(attributes);
flow.getAttributes().putAll(attributes);
return flow;
}

View File

@@ -211,7 +211,7 @@ public class FlowArtifactFactory {
if (executionCriteria != null) {
transition.setExecutionCriteria(executionCriteria);
}
transition.getAttributeMap().putAll(attributes);
transition.getAttributes().putAll(attributes);
return transition;
}
@@ -234,6 +234,6 @@ public class FlowArtifactFactory {
FlowExecutionExceptionHandler[] exceptionHandlers, AttributeMap attributes) {
state.getEntryActionList().addAll(entryActions);
state.getExceptionHandlerSet().addAll(exceptionHandlers);
state.getAttributeMap().putAll(attributes);
state.getAttributes().putAll(attributes);
}
}

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.webflow.engine.builder.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.support.AbstractConverter;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
@@ -64,7 +63,7 @@ class TextToTargetStateResolver extends AbstractConverter {
return new Class[] { TargetStateResolver.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
String targetStateId = (String) source;
if (!StringUtils.hasText(targetStateId)) {
return null;

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.webflow.engine.builder.support;
import org.springframework.binding.convert.ConversionContext;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.support.AbstractConverter;
import org.springframework.binding.expression.Expression;
@@ -71,7 +70,7 @@ class TextToTransitionCriteria extends AbstractConverter {
return new Class[] { TransitionCriteria.class };
}
protected Object doConvert(Object source, Class targetClass, ConversionContext context) throws Exception {
protected Object doConvert(Object source, Class targetClass, Object context) throws Exception {
String encodedCriteria = (String) source;
ExpressionParser parser = flowBuilderContext.getExpressionParser();
if (!StringUtils.hasText(encodedCriteria)

View File

@@ -24,7 +24,9 @@ import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.binding.collection.MapAdaptable;
import org.springframework.binding.convert.support.FormatterBackedConversionExecutor;
import org.springframework.binding.convert.ConversionException;
import org.springframework.binding.convert.ConversionExecutor;
import org.springframework.binding.expression.EvaluationException;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.ExpressionParser;
import org.springframework.binding.expression.support.ParserContextImpl;
@@ -38,6 +40,7 @@ import org.springframework.binding.mapping.MappingResults;
import org.springframework.binding.mapping.MappingResultsCriteria;
import org.springframework.binding.mapping.impl.DefaultMapper;
import org.springframework.binding.mapping.impl.DefaultMapping;
import org.springframework.binding.mapping.impl.MappingContext;
import org.springframework.binding.mapping.results.TargetAccessError;
import org.springframework.validation.BindingResult;
import org.springframework.webflow.core.collection.ParameterMap;
@@ -62,7 +65,7 @@ class MvcView implements View {
private MappingResults mappingResults;
private boolean postbackSuccess;
private boolean viewErrors;
private String eventId;
@@ -101,30 +104,29 @@ class MvcView implements View {
public void resume() {
determineEventId(context);
if (eventId == null) {
// nothing to do
return;
}
Object model = getModelObject();
if (model == null) {
postbackSuccess = true;
return;
}
if (shouldBind(model)) {
mappingResults = bind(model);
if (!mappingResults.hasErrorResults()) {
postbackSuccess = true;
} else {
if (onlyPropertyNotFoundErrorsPresent(mappingResults)) {
postbackSuccess = true;
}
if (mappingResults.hasErrorResults() && !onlyPropertyNotFoundErrorsPresent(mappingResults)) {
viewErrors = true;
}
}
}
public boolean eventSignaled() {
return postbackSuccess && eventId != null;
return eventId != null && !viewErrors;
}
public Event getEvent() {
if (!eventSignaled()) {
return null;
}
return new Event(this, eventId, context.getRequestParameters().asAttributeMap());
}
@@ -146,7 +148,7 @@ class MvcView implements View {
BindingModel bindingModel = new BindingModel(modelObject, expressionParser, formatterRegistry, context
.getMessageContext());
bindingModel.setMappingResults(mappingResults);
model.put(BindingResult.MODEL_KEY_PREFIX + getModelExpression().getExpressionString(), model);
model.put(BindingResult.MODEL_KEY_PREFIX + getModelExpression().getExpressionString(), bindingModel);
}
}
@@ -171,7 +173,7 @@ class MvcView implements View {
return transition.getAttributes().getBoolean("bind").booleanValue();
}
}
return false;
return true;
}
private MappingResults bind(Object model) {
@@ -187,9 +189,7 @@ class MvcView implements View {
.parseExpression(name, new ParserContextImpl().eval(MapAdaptable.class));
Expression target = expressionParser.parseExpression(name, new ParserContextImpl().eval(model.getClass()));
DefaultMapping mapping = new DefaultMapping(source, target);
Class targetClass = target.getValueType(model);
Formatter formatter = formatterRegistry.getFormatter(target.getExpressionString(), targetClass);
mapping.setTypeConverter(new FormatterBackedConversionExecutor(formatter, targetClass));
mapping.setTypeConverter(new FormatterBackedMappingConversionExecutor(formatterRegistry));
mapper.addMapping(mapping);
}
}
@@ -252,4 +252,49 @@ class MvcView implements View {
}
}
private static class FormatterBackedMappingConversionExecutor implements ConversionExecutor {
private FormatterRegistry formatterRegistry;
public FormatterBackedMappingConversionExecutor(FormatterRegistry formatterRegistry) {
this.formatterRegistry = formatterRegistry;
}
public Object execute(Object source) throws ConversionException {
throw new UnsupportedOperationException("Should never be called");
}
public Object execute(Object source, Object context) throws ConversionException {
String formattedValue = (String) source;
MappingContext mappingContext = (MappingContext) context;
Expression target = mappingContext.getCurrentMapping().getTargetExpression();
Class targetClass = getTargetClass();
if (targetClass == null) {
try {
targetClass = target.getValueType(mappingContext.getTarget());
} catch (EvaluationException e) {
// ignore
}
}
if (targetClass == null) {
return formattedValue;
}
Formatter formatter = formatterRegistry.getFormatter(target.getExpressionString(), targetClass);
if (formatter != null) {
return formatter.parseValue(formattedValue);
} else {
return formattedValue;
}
}
public Class getSourceClass() {
return String.class;
}
public Class getTargetClass() {
return null;
}
}
}

View File

@@ -21,8 +21,6 @@ import java.security.Principal;
import java.util.HashMap;
import org.springframework.binding.collection.SharedMapDecorator;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.util.ClassUtils;
import org.springframework.webflow.context.ExternalContext;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.LocalAttributeMap;
@@ -56,6 +54,8 @@ public class MockExternalContext implements ExternalContext {
private Object nativeResponse = new Object();
private Principal currentUser;
private StringWriter responseWriter = new StringWriter();
private boolean ajaxRequest;
@@ -114,10 +114,7 @@ public class MockExternalContext implements ExternalContext {
}
public Principal getCurrentUser() {
if (ClassUtils.isPresent("org.springframework.security.context.SecurityContextHolder"))
return SecurityContextHolder.getContext().getAuthentication();
else
return null;
return currentUser;
}
public Object getNativeContext() {
@@ -238,6 +235,14 @@ public class MockExternalContext implements ExternalContext {
this.nativeResponse = nativeResponse;
}
/**
* Sets the current user principal as a string.
* @param currentUser the current user name
*/
public void setCurrentUser(String currentUser) {
this.currentUser = new MockPrincipal(currentUser);
}
// convenience helpers
/**
@@ -342,4 +347,17 @@ public class MockExternalContext implements ExternalContext {
return redirectInPopup;
}
private class MockPrincipal implements Principal {
private String name;
private MockPrincipal(String name) {
this.name = name;
}
public String getName() {
return name;
}
}
}

View File

@@ -23,6 +23,7 @@ import org.springframework.webflow.definition.StateDefinition;
import org.springframework.webflow.engine.Flow;
import org.springframework.webflow.engine.RequestControlContext;
import org.springframework.webflow.engine.State;
import org.springframework.webflow.engine.TransitionableState;
import org.springframework.webflow.execution.FlowExecutionException;
import org.springframework.webflow.execution.FlowSession;
@@ -50,7 +51,7 @@ public class MockFlowSession implements FlowSession {
*/
public MockFlowSession() {
setDefinition(new Flow("mockFlow"));
State state = new State(definition, "mockState") {
State state = new TransitionableState(definition, "mockState") {
protected void doEnter(RequestControlContext context) throws FlowExecutionException {
// nothing to do
}

View File

@@ -19,7 +19,7 @@ import junit.framework.TestCase;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.core.io.ResourceLoader;
import org.springframework.webflow.core.collection.AttributeMap;
import org.springframework.webflow.core.collection.MutableAttributeMap;
import org.springframework.webflow.definition.FlowDefinition;
import org.springframework.webflow.definition.StateDefinition;
@@ -80,7 +80,7 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
private static class FooFlow implements FlowDefinition {
private String id = "foo";
public AttributeMap getAttributes() {
public MutableAttributeMap getAttributes() {
return null;
}
@@ -118,7 +118,7 @@ public class FlowDefinitionRegistryImplTests extends TestCase {
private static class BarFlow implements FlowDefinition {
private String id = "bar";
public AttributeMap getAttributes() {
public MutableAttributeMap getAttributes() {
return null;
}

View File

@@ -32,8 +32,8 @@ public class AnnotatedObjectTests extends TestCase {
}
public void testPutCustomAttributes() {
object.getAttributeMap().put("foo", "bar");
assertEquals("bar", object.getAttributeMap().get("foo"));
object.getAttributes().put("foo", "bar");
assertEquals("bar", object.getAttributes().get("foo"));
}
}

View File

@@ -39,7 +39,7 @@ public class AnnotedActionTests extends TestCase {
}
public void testExecuteWithCustomAttribute() throws Exception {
action.getAttributeMap().put("attr", "value");
action.getAttributes().put("attr", "value");
action.setTargetAction(new AbstractAction() {
protected Event doExecute(RequestContext context) throws Exception {
assertEquals("value", context.getAttributes().getString("attr"));
@@ -50,7 +50,7 @@ public class AnnotedActionTests extends TestCase {
}
public void testExecuteWithName() throws Exception {
action.getAttributeMap().put("name", "foo");
action.getAttributes().put("name", "foo");
action.setTargetAction(new AbstractAction() {
protected Event doExecute(RequestContext context) throws Exception {
assertEquals("foo", context.getAttributes().getString("name"));

View File

@@ -1,14 +1,12 @@
package org.springframework.webflow.expression;
import java.security.Principal;
import junit.framework.TestCase;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.support.ParserContextImpl;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.webflow.TestBean;
import org.springframework.webflow.action.FormAction;
import org.springframework.webflow.core.collection.AttributeMap;
@@ -50,13 +48,10 @@ public class WebFlowOgnlExpressionParserTests extends TestCase {
}
public void testResolveCurrentUser() {
SecurityContextImpl security = new SecurityContextImpl();
Authentication auth = new TestingAuthenticationToken("user", "password", null);
security.setAuthentication(auth);
SecurityContextHolder.setContext(security);
MockRequestContext context = new MockRequestContext();
context.getMockExternalContext().setCurrentUser("Keith");
Expression exp = parser.parseExpression("currentUser", new ParserContextImpl().eval(RequestContext.class));
assertSame(auth, exp.getValue(context));
assertEquals("Keith", ((Principal) exp.getValue(context)).getName());
}
public void testResolveRequestScope() {

View File

@@ -1,15 +1,13 @@
package org.springframework.webflow.expression.el;
import java.security.Principal;
import junit.framework.TestCase;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.binding.expression.Expression;
import org.springframework.binding.expression.el.DefaultExpressionFactoryUtils;
import org.springframework.binding.expression.support.ParserContextImpl;
import org.springframework.security.Authentication;
import org.springframework.security.context.SecurityContextHolder;
import org.springframework.security.context.SecurityContextImpl;
import org.springframework.security.providers.TestingAuthenticationToken;
import org.springframework.webflow.TestBean;
import org.springframework.webflow.action.FormAction;
import org.springframework.webflow.core.collection.AttributeMap;
@@ -52,13 +50,10 @@ public class WebFlowELExpressionParserTests extends TestCase {
}
public void testResolveCurrentUser() {
SecurityContextImpl security = new SecurityContextImpl();
Authentication auth = new TestingAuthenticationToken("user", "password", null);
security.setAuthentication(auth);
SecurityContextHolder.setContext(security);
MockRequestContext context = new MockRequestContext();
context.getMockExternalContext().setCurrentUser("Keith");
Expression exp = parser.parseExpression("currentUser", new ParserContextImpl().eval(RequestContext.class));
assertSame(auth, exp.getValue(context));
assertEquals("Keith", ((Principal) exp.getValue(context)).getName());
}
public void testResolveRequestScope() {

View File

@@ -1,4 +1,4 @@
package org.springframework.webflow.mvc;
package org.springframework.webflow.mvc.view;
import java.io.IOException;
import java.io.InputStream;

View File

@@ -0,0 +1,183 @@
package org.springframework.webflow.mvc.view;
import java.security.Principal;
import java.util.Calendar;
import java.util.Date;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import junit.framework.TestCase;
import org.springframework.binding.expression.support.StaticExpression;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.mock.web.MockServletContext;
import org.springframework.validation.BindingResult;
import org.springframework.web.servlet.View;
import org.springframework.webflow.test.MockFlowExecutionKey;
import org.springframework.webflow.test.MockRequestContext;
public class MvcViewTests extends TestCase {
private boolean renderCalled;
private Map model;
public void testRender() throws Exception {
MockRequestContext context = new MockRequestContext();
context.getRequestScope().put("foo", "bar");
context.getFlowScope().put("bar", "baz");
context.getFlowScope().put("bindBean", new BindBean());
context.getConversationScope().put("baz", "boop");
context.getFlashScope().put("boop", "bing");
context.getMockExternalContext().setCurrentUser("Keith");
context.getMockExternalContext().setNativeContext(new MockServletContext());
context.getMockExternalContext().setNativeRequest(new MockHttpServletRequest());
context.getMockExternalContext().setNativeResponse(new MockHttpServletResponse());
context.getMockFlowExecutionContext().setKey(new MockFlowExecutionKey("c1v1"));
org.springframework.web.servlet.View mvcView = new MockView();
MvcView view = new MvcView(mvcView, context);
view.render();
assertTrue(renderCalled);
assertEquals("bar", model.get("foo"));
assertEquals("baz", model.get("bar"));
assertEquals("boop", model.get("baz"));
assertEquals("bing", model.get("boop"));
assertEquals("c1v1", model.get("flowExecutionKey"));
assertEquals("Keith", ((Principal) model.get("currentUser")).getName());
assertEquals(context, model.get("flowRequestContext"));
assertEquals("/mockFlow?execution=c1v1", model.get("flowExecutionUrl"));
assertNull(model.get(BindingResult.MODEL_KEY_PREFIX + "bindBean"));
}
public void testRenderWithBindingModel() throws Exception {
MockRequestContext context = new MockRequestContext();
Object bindBean = new BindBean();
StaticExpression modelObject = new StaticExpression(bindBean);
modelObject.setExpressionString("bindBean");
context.getCurrentState().getAttributes().put("model", modelObject);
context.getFlowScope().put("bindBean", bindBean);
context.getMockExternalContext().setNativeContext(new MockServletContext());
context.getMockExternalContext().setNativeRequest(new MockHttpServletRequest());
context.getMockExternalContext().setNativeResponse(new MockHttpServletResponse());
context.getMockFlowExecutionContext().setKey(new MockFlowExecutionKey("c1v1"));
org.springframework.web.servlet.View mvcView = new MockView();
MvcView view = new MvcView(mvcView, context);
view.render();
assertEquals(context.getFlowScope().get("bindBean"), model.get("bindBean"));
BindingModel bm = (BindingModel) model.get(BindingResult.MODEL_KEY_PREFIX + "bindBean");
assertNotNull(bm);
assertEquals(null, bm.getFieldValue("stringProperty"));
assertEquals("3", bm.getFieldValue("integerProperty"));
assertEquals("1/1/08", bm.getFieldValue("dateProperty"));
}
public void testResumeNoEvent() throws Exception {
MockRequestContext context = new MockRequestContext();
context.getMockExternalContext().setNativeContext(new MockServletContext());
context.getMockExternalContext().setNativeRequest(new MockHttpServletRequest());
context.getMockExternalContext().setNativeResponse(new MockHttpServletResponse());
context.getMockFlowExecutionContext().setKey(new MockFlowExecutionKey("c1v1"));
org.springframework.web.servlet.View mvcView = new MockView();
MvcView view = new MvcView(mvcView, context);
view.resume();
assertFalse(view.eventSignaled());
assertNull(view.getEvent());
}
public void testResumeEventNoModelBinding() throws Exception {
MockRequestContext context = new MockRequestContext();
context.putRequestParameter("_eventId", "submit");
context.getMockExternalContext().setNativeContext(new MockServletContext());
context.getMockExternalContext().setNativeRequest(new MockHttpServletRequest());
context.getMockExternalContext().setNativeResponse(new MockHttpServletResponse());
context.getMockFlowExecutionContext().setKey(new MockFlowExecutionKey("c1v1"));
org.springframework.web.servlet.View mvcView = new MockView();
MvcView view = new MvcView(mvcView, context);
view.resume();
assertTrue(view.eventSignaled());
assertEquals("submit", view.getEvent().getId());
}
public void testResumeEventModelBinding() throws Exception {
MockRequestContext context = new MockRequestContext();
context.putRequestParameter("_eventId", "submit");
context.putRequestParameter("stringProperty", "foo");
context.putRequestParameter("integerProperty", "5");
context.putRequestParameter("dateProperty", "1/1/07");
BindBean bindBean = new BindBean();
StaticExpression modelObject = new StaticExpression(bindBean);
modelObject.setExpressionString("bindBean");
context.getCurrentState().getAttributes().put("model", modelObject);
context.getFlowScope().put("bindBean", bindBean);
context.getMockExternalContext().setNativeContext(new MockServletContext());
context.getMockExternalContext().setNativeRequest(new MockHttpServletRequest());
context.getMockExternalContext().setNativeResponse(new MockHttpServletResponse());
context.getMockFlowExecutionContext().setKey(new MockFlowExecutionKey("c1v1"));
org.springframework.web.servlet.View mvcView = new MockView();
MvcView view = new MvcView(mvcView, context);
view.resume();
assertTrue(view.eventSignaled());
assertEquals("submit", view.getEvent().getId());
assertEquals("foo", bindBean.getStringProperty());
assertEquals(new Integer(5), bindBean.getIntegerProperty());
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, 2007);
assertEquals(cal.getTime(), bindBean.getDateProperty());
}
private class MockView implements View {
public String getContentType() {
return "text/html";
}
public void render(Map model, HttpServletRequest request, HttpServletResponse response) throws Exception {
renderCalled = true;
MvcViewTests.this.model = model;
}
}
public static class BindBean {
private String stringProperty;
private Integer integerProperty = new Integer(3);
private Date dateProperty;
public BindBean() {
Calendar cal = Calendar.getInstance();
cal.clear();
cal.set(Calendar.YEAR, 2008);
dateProperty = cal.getTime();
}
public String getStringProperty() {
return stringProperty;
}
public void setStringProperty(String stringProperty) {
this.stringProperty = stringProperty;
}
public Integer getIntegerProperty() {
return integerProperty;
}
public void setIntegerProperty(Integer integerProperty) {
this.integerProperty = integerProperty;
}
public Date getDateProperty() {
return dateProperty;
}
public void setDateProperty(Date dateProperty) {
this.dateProperty = dateProperty;
}
}
}

View File

@@ -69,7 +69,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
public void testSameSession() {
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -105,7 +105,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -115,7 +115,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributeMap().put("commit", Boolean.TRUE);
endState.getAttributes().put("commit", Boolean.TRUE);
flowSession.setState(endState);
hibernateListener.sessionEnded(context, flowSession, null);
@@ -128,7 +128,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -146,7 +146,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertSessionBound();
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributeMap().put("commit", Boolean.TRUE);
endState.getAttributes().put("commit", Boolean.TRUE);
flowSession.setState(endState);
hibernateListener.sessionEnded(context, flowSession, null);
@@ -162,7 +162,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -172,7 +172,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
endState.getAttributeMap().put("commit", Boolean.FALSE);
endState.getAttributes().put("commit", Boolean.FALSE);
flowSession.setState(endState);
hibernateListener.sessionEnded(context, flowSession, null);
assertEquals("Table should only have two rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
@@ -184,7 +184,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -204,7 +204,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -222,7 +222,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
assertSessionNotBound();
hibernateListener.exceptionThrown(context, new FlowExecutionException("foo", "bar", "test"));
assertSessionNotBound();
@@ -231,7 +231,7 @@ public class HibernateFlowExecutionListenerTests extends TestCase {
public void testLazyInitializedCollection() {
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
hibernateListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();

View File

@@ -55,7 +55,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -65,7 +65,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributeMap().put("commit", Boolean.TRUE);
endState.getAttributes().put("commit", Boolean.TRUE);
flowSession.setState(endState);
jpaListener.sessionEnded(context, flowSession, null);
@@ -78,7 +78,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -96,7 +96,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertSessionBound();
EndState endState = new EndState(flowSession.getDefinitionInternal(), "success");
endState.getAttributeMap().put("commit", Boolean.TRUE);
endState.getAttributes().put("commit", Boolean.TRUE);
flowSession.setState(endState);
jpaListener.sessionEnded(context, flowSession, null);
@@ -111,7 +111,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -121,7 +121,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should still only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
EndState endState = new EndState(flowSession.getDefinitionInternal(), "cancel");
endState.getAttributeMap().put("commit", Boolean.FALSE);
endState.getAttributes().put("commit", Boolean.FALSE);
flowSession.setState(endState);
jpaListener.sessionEnded(context, flowSession, null);
assertEquals("Table should only have two rows", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
@@ -133,7 +133,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -153,7 +153,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
jpaListener.sessionStarting(context, flowSession, null);
context.setActiveSession(flowSession);
assertSessionBound();
@@ -171,7 +171,7 @@ public class JpaFlowExecutionListenerTests extends TestCase {
assertEquals("Table should only have one row", 1, jdbcTemplate.queryForInt("select count(*) from T_BEAN"));
MockRequestContext context = new MockRequestContext();
MockFlowSession flowSession = new MockFlowSession();
flowSession.getDefinitionInternal().getAttributeMap().put("persistenceContext", "true");
flowSession.getDefinition().getAttributes().put("persistenceContext", "true");
assertSessionNotBound();
jpaListener.exceptionThrown(context, new FlowExecutionException("foo", "bar", "test"));
assertSessionNotBound();

View File

@@ -14,7 +14,11 @@
<logger name="org.springframework.beans">
<level value="warn" />
</logger>
<logger name="org.springframework.binding">
<level value="debug" />
</logger>
<logger name="org.springframework.jdbc">
<level value="warn" />
</logger>