SWF-1234 Integration with Spring 3 type conversion
This commit is contained in:
@@ -44,6 +44,12 @@
|
||||
<version>1.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<repositories>
|
||||
<!-- Where the el-api is located -->
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.binding.convert;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* A service interface for retrieving type conversion executors. The returned command objects are thread-safe and may be
|
||||
@@ -74,15 +73,6 @@ public interface ConversionService {
|
||||
public ConversionExecutor getConversionExecutor(String id, Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException;
|
||||
|
||||
/**
|
||||
* Return all conversion executors capable of converting <i>from</i> the provided <code>sourceClass</code>. For
|
||||
* example, <code>getConversionExecutor(String.class)</code> would return all converters that convert from String to
|
||||
* some other Object. Mainly useful for adapting a set of converters to some other environment.
|
||||
* @param sourceClass the source class converting from
|
||||
* @return the conversion executors that can convert from that source class
|
||||
*/
|
||||
public Set getConversionExecutors(Class sourceClass);
|
||||
|
||||
/**
|
||||
* Lookup a class by its well-known alias. For example, <code>long</code> for <code>java.lang.Long</code>
|
||||
* @param alias the class alias
|
||||
@@ -90,4 +80,11 @@ public interface ConversionService {
|
||||
*/
|
||||
public Class getClassForAlias(String alias);
|
||||
|
||||
/**
|
||||
* Return the underlying Spring ConversionService.
|
||||
*
|
||||
* @return the conversion service
|
||||
*/
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2004-2010 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.binding.convert.converters;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A Spring Binding Converter that delegates to a Spring {@link ConversionService} to do the actual type conversion.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class SpringConvertingConverterAdapter implements Converter {
|
||||
|
||||
/**
|
||||
* The source value type to convert from.
|
||||
*/
|
||||
private final Class sourceClass;
|
||||
|
||||
/**
|
||||
* The target value type to convert to.
|
||||
*/
|
||||
private final Class targetClass;
|
||||
|
||||
/**
|
||||
* The ConversionService that will perform the conversion.
|
||||
*/
|
||||
private ConversionService conversionService;
|
||||
|
||||
public SpringConvertingConverterAdapter(Class sourceClass, Class targetClass, ConversionService conversionService) {
|
||||
Assert.notNull(sourceClass, "The source class to convert from is required.");
|
||||
Assert.notNull(targetClass, "The target class to convert to is required.");
|
||||
Assert.notNull(conversionService, "A Spring ConversionService is required.");
|
||||
this.sourceClass = sourceClass;
|
||||
this.targetClass = targetClass;
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
public Object convertSourceToTargetClass(Object source, Class targetClass) throws Exception {
|
||||
return conversionService.convert(source, targetClass);
|
||||
}
|
||||
|
||||
public Class getSourceClass() {
|
||||
return sourceClass;
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
return targetClass;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,25 +20,8 @@ import java.math.BigInteger;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import org.springframework.binding.convert.converters.CollectionToCollection;
|
||||
import org.springframework.binding.convert.converters.NumberToNumber;
|
||||
import org.springframework.binding.convert.converters.ObjectToCollection;
|
||||
import org.springframework.binding.convert.converters.StringToBigDecimal;
|
||||
import org.springframework.binding.convert.converters.StringToBigInteger;
|
||||
import org.springframework.binding.convert.converters.StringToBoolean;
|
||||
import org.springframework.binding.convert.converters.StringToByte;
|
||||
import org.springframework.binding.convert.converters.StringToCharacter;
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
import org.springframework.binding.convert.converters.StringToDouble;
|
||||
import org.springframework.binding.convert.converters.StringToEnum;
|
||||
import org.springframework.binding.convert.converters.StringToFloat;
|
||||
import org.springframework.binding.convert.converters.StringToInteger;
|
||||
import org.springframework.binding.convert.converters.StringToLabeledEnum;
|
||||
import org.springframework.binding.convert.converters.StringToLocale;
|
||||
import org.springframework.binding.convert.converters.StringToLong;
|
||||
import org.springframework.binding.convert.converters.StringToShort;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.enums.LabeledEnum;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Default, local implementation of a conversion service. Will automatically register <i>from string</i> converters for
|
||||
@@ -56,29 +39,26 @@ public class DefaultConversionService extends GenericConversionService {
|
||||
addDefaultAliases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new default conversion service with an instance of a Spring ConversionService.
|
||||
*
|
||||
* @param delegateConversionService the Spring conversion service
|
||||
*/
|
||||
public DefaultConversionService(ConversionService delegateConversionService) {
|
||||
super(delegateConversionService);
|
||||
addDefaultConverters();
|
||||
addDefaultAliases();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add all default converters to the conversion service.
|
||||
*
|
||||
* Note: Staring with Spring Web Flow 2.1, this method does not register any Spring Binding converters. All type
|
||||
* conversion is driven through Spring's type conversion instead.
|
||||
*
|
||||
* @see GenericConversionService
|
||||
*/
|
||||
protected void addDefaultConverters() {
|
||||
addConverter(new StringToByte());
|
||||
addConverter(new StringToBoolean());
|
||||
addConverter(new StringToCharacter());
|
||||
addConverter(new StringToShort());
|
||||
addConverter(new StringToInteger());
|
||||
addConverter(new StringToLong());
|
||||
addConverter(new StringToFloat());
|
||||
addConverter(new StringToDouble());
|
||||
addConverter(new StringToBigInteger());
|
||||
addConverter(new StringToBigDecimal());
|
||||
addConverter(new StringToLocale());
|
||||
addConverter(new StringToDate());
|
||||
addConverter(new StringToLabeledEnum());
|
||||
addConverter(new NumberToNumber());
|
||||
addConverter(new ObjectToCollection(this));
|
||||
addConverter(new CollectionToCollection(this));
|
||||
if (ClassUtils.isPresent("java.lang.Enum", this.getClass().getClassLoader())) {
|
||||
addConverter(new StringToEnum());
|
||||
}
|
||||
}
|
||||
|
||||
protected void addDefaultAliases() {
|
||||
|
||||
@@ -17,13 +17,8 @@ package org.springframework.binding.convert.service;
|
||||
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
@@ -36,7 +31,10 @@ import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.binding.convert.converters.ObjectToArray;
|
||||
import org.springframework.binding.convert.converters.ObjectToCollection;
|
||||
import org.springframework.binding.convert.converters.ReverseConverter;
|
||||
import org.springframework.binding.convert.converters.SpringConvertingConverterAdapter;
|
||||
import org.springframework.binding.convert.converters.TwoWayConverter;
|
||||
import org.springframework.core.convert.converter.ConverterRegistry;
|
||||
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -47,11 +45,9 @@ import org.springframework.util.Assert;
|
||||
public class GenericConversionService implements ConversionService {
|
||||
|
||||
/**
|
||||
* An indexed map of converters. Each entry key is a source class that can be converted from, and each entry value
|
||||
* is a map of target classes that can be converted to, ultimately mapping to a specific converter that can perform
|
||||
* the source->target conversion.
|
||||
* Spring ConversionService where existing custom {@link Converter} types will be registered through an adapter.
|
||||
*/
|
||||
private final Map sourceClassConverters = new HashMap();
|
||||
private org.springframework.core.convert.ConversionService delegate;
|
||||
|
||||
/**
|
||||
* A map of custom converters. Custom converters are assigned a unique identifier that can be used to lookup the
|
||||
@@ -69,6 +65,24 @@ public class GenericConversionService implements ConversionService {
|
||||
*/
|
||||
private ConversionService parent;
|
||||
|
||||
/**
|
||||
* Default constructor.
|
||||
*/
|
||||
public GenericConversionService() {
|
||||
FormattingConversionServiceFactoryBean factoryBean = new FormattingConversionServiceFactoryBean();
|
||||
factoryBean.afterPropertiesSet();
|
||||
this.delegate = factoryBean.getObject();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor accepting a specific instance of a Spring ConversionService to delegate to.
|
||||
* @param delegateConversionService the conversion service
|
||||
*/
|
||||
public GenericConversionService(org.springframework.core.convert.ConversionService delegateConversionService) {
|
||||
Assert.notNull(delegateConversionService);
|
||||
this.delegate = delegateConversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the parent of this conversion service. Could be null.
|
||||
*/
|
||||
@@ -84,24 +98,42 @@ public class GenericConversionService implements ConversionService {
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given converter to this conversion service.
|
||||
* @return the Spring ConverterRegistry
|
||||
*/
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
return delegate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the given converter with the underlying Spring ConversionService with the help of an adapter. The
|
||||
* adapter allows an existing Spring Binding converter to be invoked within Spring's type conversion system.
|
||||
*
|
||||
* @param converter the converter
|
||||
*
|
||||
* @see ConverterRegistry
|
||||
* @see org.springframework.core.convert.ConversionService
|
||||
* @see SpringBindingConverterAdapter
|
||||
*/
|
||||
public void addConverter(Converter converter) {
|
||||
Class sourceClass = converter.getSourceClass();
|
||||
Class targetClass = converter.getTargetClass();
|
||||
Map sourceMap = getSourceMap(sourceClass);
|
||||
sourceMap.put(targetClass, converter);
|
||||
((ConverterRegistry) delegate).addConverter(new SpringBindingConverterAdapter(converter));
|
||||
if (converter instanceof TwoWayConverter) {
|
||||
sourceMap = getSourceMap(targetClass);
|
||||
sourceMap.put(sourceClass, new ReverseConverter((TwoWayConverter) converter));
|
||||
TwoWayConverter twoWayConverter = (TwoWayConverter) converter;
|
||||
((ConverterRegistry) delegate).addConverter(new SpringBindingConverterAdapter(new ReverseConverter(
|
||||
twoWayConverter)));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add given custom converter to this conversion service.
|
||||
*
|
||||
* Note: Converters registered through this method will not be involve the Spring type conversion system, which is
|
||||
* now used the default type conversion mechanism. Spring's type conversion does not support named converters. This
|
||||
* method is provided for backwards compatibility.
|
||||
*
|
||||
* @param id the id of the custom converter instance
|
||||
* @param converter the converter
|
||||
*
|
||||
* @deprecated use {@link #addConverter(Converter)} instead
|
||||
*/
|
||||
public void addConverter(String id, Converter converter) {
|
||||
customConverters.put(id, converter);
|
||||
@@ -114,15 +146,6 @@ public class GenericConversionService implements ConversionService {
|
||||
aliasMap.put(alias, targetType);
|
||||
}
|
||||
|
||||
private Map getSourceMap(Class sourceClass) {
|
||||
Map sourceMap = (Map) sourceClassConverters.get(sourceClass);
|
||||
if (sourceMap == null) {
|
||||
sourceMap = new HashMap();
|
||||
sourceClassConverters.put(sourceClass, sourceMap);
|
||||
}
|
||||
return sourceMap;
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
Assert.notNull(sourceClass, "The source class to convert from is required");
|
||||
@@ -132,40 +155,15 @@ public class GenericConversionService implements ConversionService {
|
||||
if (targetClass.isAssignableFrom(sourceClass)) {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new NoOpConverter(sourceClass, targetClass));
|
||||
}
|
||||
// special handling for arrays since they are not indexable classes
|
||||
if (sourceClass.isArray()) {
|
||||
if (targetClass.isArray()) {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToArray(this));
|
||||
} else if (Collection.class.isAssignableFrom(targetClass)) {
|
||||
if (!targetClass.isInterface() && Modifier.isAbstract(targetClass.getModifiers())) {
|
||||
throw new IllegalArgumentException("Conversion target class [" + targetClass.getName()
|
||||
+ "] is invalid; cannot convert to abstract collection types--"
|
||||
+ "request an interface or concrete implementation instead");
|
||||
}
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new ArrayToCollection(this));
|
||||
}
|
||||
}
|
||||
if (targetClass.isArray()) {
|
||||
if (Collection.class.isAssignableFrom(sourceClass)) {
|
||||
Converter collectionToArray = new ReverseConverter(new ArrayToCollection(this));
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, collectionToArray);
|
||||
} else {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new ObjectToArray(this));
|
||||
}
|
||||
}
|
||||
Converter converter = findRegisteredConverter(sourceClass, targetClass);
|
||||
if (converter != null) {
|
||||
// we found a converter
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, converter);
|
||||
if (delegate.canConvert(sourceClass, targetClass)) {
|
||||
return new StaticConversionExecutor(sourceClass, targetClass, new SpringConvertingConverterAdapter(
|
||||
sourceClass, targetClass, delegate));
|
||||
} else if (parent != null) {
|
||||
return parent.getConversionExecutor(sourceClass, targetClass);
|
||||
} else {
|
||||
if (parent != null) {
|
||||
// try the parent
|
||||
return parent.getConversionExecutor(sourceClass, targetClass);
|
||||
} else {
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"No ConversionExecutor found for converting from sourceClass [" + sourceClass.getName()
|
||||
+ "] to target class [" + targetClass.getName() + "]");
|
||||
}
|
||||
throw new ConversionExecutorNotFoundException(sourceClass, targetClass,
|
||||
"No ConversionExecutor found for converting from sourceClass [" + sourceClass.getName()
|
||||
+ "] to target class [" + targetClass.getName() + "]");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,46 +339,6 @@ public class GenericConversionService implements ConversionService {
|
||||
}
|
||||
}
|
||||
|
||||
private Converter findRegisteredConverter(Class sourceClass, Class targetClass) {
|
||||
if (sourceClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Map sourceTargetConverters = findConvertersForSource(currentClass);
|
||||
Converter converter = findTargetConverter(sourceTargetConverters, targetClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
Map objectConverters = findConvertersForSource(Object.class);
|
||||
return findTargetConverter(objectConverters, targetClass);
|
||||
} else {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(sourceClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Map sourceTargetConverters = findConvertersForSource(currentClass);
|
||||
Converter converter = findTargetConverter(sourceTargetConverters, targetClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
if (currentClass.getSuperclass() != null) {
|
||||
classQueue.addFirst(currentClass.getSuperclass());
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public Object executeConversion(Object source, Class targetClass) throws ConversionException {
|
||||
if (source != null) {
|
||||
ConversionExecutor conversionExecutor = getConversionExecutor(source.getClass(), targetClass);
|
||||
@@ -412,97 +370,8 @@ public class GenericConversionService implements ConversionService {
|
||||
}
|
||||
}
|
||||
|
||||
// subclassing support
|
||||
|
||||
public Set getConversionExecutors(Class sourceClass) {
|
||||
Set parentExecutors;
|
||||
if (parent != null) {
|
||||
parentExecutors = parent.getConversionExecutors(sourceClass);
|
||||
} else {
|
||||
parentExecutors = Collections.EMPTY_SET;
|
||||
}
|
||||
Map sourceMap = getSourceMap(sourceClass);
|
||||
if (parentExecutors.isEmpty() && sourceMap.isEmpty()) {
|
||||
return Collections.EMPTY_SET;
|
||||
}
|
||||
Set entries = sourceMap.entrySet();
|
||||
Set conversionExecutors = new HashSet(entries.size() + parentExecutors.size());
|
||||
for (Iterator it = entries.iterator(); it.hasNext();) {
|
||||
Map.Entry entry = (Map.Entry) it.next();
|
||||
Class targetClass = (Class) entry.getKey();
|
||||
Converter converter = (Converter) entry.getValue();
|
||||
conversionExecutors.add(new StaticConversionExecutor(sourceClass, targetClass, converter));
|
||||
}
|
||||
conversionExecutors.addAll(parentExecutors);
|
||||
return conversionExecutors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an indexed map of converters. Each entry key is a source class that can be converted from, and each entry
|
||||
* value is a map of target classes that can be convertered to, ultimately mapping to a specific converter that can
|
||||
* perform the source->target conversion.
|
||||
*/
|
||||
protected Map getSourceClassConverters() {
|
||||
return sourceClassConverters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a registered converter object
|
||||
* @param sourceClass the source class
|
||||
* @param targetClass the target class
|
||||
*/
|
||||
protected Converter getConverter(Class sourceClass, Class targetClass) {
|
||||
Map sourceTargetConverters = findConvertersForSource(sourceClass);
|
||||
return findTargetConverter(sourceTargetConverters, targetClass);
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private Map findConvertersForSource(Class sourceClass) {
|
||||
Map sourceConverters = (Map) sourceClassConverters.get(sourceClass);
|
||||
return sourceConverters != null ? sourceConverters : Collections.EMPTY_MAP;
|
||||
}
|
||||
|
||||
private Converter findTargetConverter(Map sourceTargetConverters, Class targetClass) {
|
||||
if (sourceTargetConverters.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
if (targetClass.isInterface()) {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(targetClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Converter converter = (Converter) sourceTargetConverters.get(currentClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
return (Converter) sourceTargetConverters.get(Object.class);
|
||||
} else {
|
||||
LinkedList classQueue = new LinkedList();
|
||||
classQueue.addFirst(targetClass);
|
||||
while (!classQueue.isEmpty()) {
|
||||
Class currentClass = (Class) classQueue.removeLast();
|
||||
Converter converter = (Converter) sourceTargetConverters.get(currentClass);
|
||||
if (converter != null) {
|
||||
return converter;
|
||||
}
|
||||
if (currentClass.getSuperclass() != null) {
|
||||
classQueue.addFirst(currentClass.getSuperclass());
|
||||
}
|
||||
Class[] interfaces = currentClass.getInterfaces();
|
||||
for (int i = 0; i < interfaces.length; i++) {
|
||||
classQueue.addFirst(interfaces[i]);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Class convertToWrapperClassIfNecessary(Class targetType) {
|
||||
if (targetType.isPrimitive()) {
|
||||
if (targetType.equals(int.class)) {
|
||||
@@ -528,4 +397,5 @@ public class GenericConversionService implements ConversionService {
|
||||
return targetType;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2004-2010 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.binding.convert.service;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.binding.convert.converters.Converter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.GenericConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* A Spring Converter that makes it possible for a Spring Binding Converter to be registered with a Spring
|
||||
* {@link ConversionService}.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
public class SpringBindingConverterAdapter implements GenericConverter {
|
||||
|
||||
private Converter converter;
|
||||
|
||||
public SpringBindingConverterAdapter(Converter converter) {
|
||||
Assert.notNull(converter, "A Spring Binding converter is required.");
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public Object convert(Object source, TypeDescriptor sourceType, TypeDescriptor targetType) {
|
||||
try {
|
||||
return converter.convertSourceToTargetClass(source, targetType.getObjectType());
|
||||
} catch (Exception e) {
|
||||
throw new IllegalArgumentException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public Set getConvertibleTypes() {
|
||||
return Collections.singleton(new ConvertiblePair(converter.getSourceClass(), converter.getTargetClass()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,18 +15,11 @@
|
||||
*/
|
||||
package org.springframework.binding.expression.beanwrapper;
|
||||
|
||||
import java.beans.PropertyEditorSupport;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.beans.BeanWrapperImpl;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.NotReadablePropertyException;
|
||||
import org.springframework.beans.NotWritablePropertyException;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
@@ -95,7 +88,7 @@ public class BeanWrapperExpression implements Expression {
|
||||
public void setValue(Object context, Object value) {
|
||||
try {
|
||||
BeanWrapperImpl beanWrapper = new BeanWrapperImpl(context);
|
||||
registerConvertersAsPropertyEditors(beanWrapper);
|
||||
beanWrapper.setConversionService(conversionService.getDelegateConversionService());
|
||||
beanWrapper.setPropertyValue(expression, value);
|
||||
} catch (NotWritablePropertyException e) {
|
||||
throw new PropertyNotFoundException(context.getClass(), expression, e);
|
||||
@@ -129,39 +122,4 @@ public class BeanWrapperExpression implements Expression {
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adapts the String->Object converters to PropertyEditors for use during a setValue attempt. Excludes any
|
||||
* String->Enum converter, since BeanWrapper has built in support for Enum conversion.
|
||||
* @param registry the registry to register converter-to-editor adapters with
|
||||
*/
|
||||
protected void registerConvertersAsPropertyEditors(PropertyEditorRegistry registry) {
|
||||
Set converters = conversionService.getConversionExecutors(String.class);
|
||||
for (Iterator it = converters.iterator(); it.hasNext();) {
|
||||
ConversionExecutor converter = (ConversionExecutor) it.next();
|
||||
if (!converter.getTargetClass().getName().equals("java.lang.Enum")) {
|
||||
registry.registerCustomEditor(converter.getTargetClass(), new PropertyEditorConverter(converter));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static class PropertyEditorConverter extends PropertyEditorSupport {
|
||||
|
||||
private ConversionExecutor converter;
|
||||
|
||||
public PropertyEditorConverter(ConversionExecutor converter) {
|
||||
this.converter = converter;
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
try {
|
||||
Object convertedValue = converter.execute(text);
|
||||
setValue(convertedValue);
|
||||
} catch (ConversionException e) {
|
||||
IllegalArgumentException iae = new IllegalArgumentException("Unable to convert text '" + text + "'");
|
||||
iae.initCause(e);
|
||||
throw iae;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -149,4 +149,8 @@ public class SpringELExpression implements Expression {
|
||||
return variableValues;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return getExpressionString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,11 +16,12 @@
|
||||
package org.springframework.binding.expression.spel;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
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.ExpressionVariable;
|
||||
@@ -28,16 +29,11 @@ import org.springframework.binding.expression.ParserContext;
|
||||
import org.springframework.binding.expression.ParserException;
|
||||
import org.springframework.binding.expression.support.NullParserContext;
|
||||
import org.springframework.context.expression.MapAccessor;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.expression.EvaluationContext;
|
||||
import org.springframework.expression.PropertyAccessor;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.expression.spel.support.StandardTypeConverter;
|
||||
import org.springframework.format.FormatterRegistry;
|
||||
import org.springframework.format.datetime.DateFormatter;
|
||||
import org.springframework.format.support.FormattingConversionServiceFactoryBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -57,29 +53,17 @@ public class SpringELExpressionParser implements ExpressionParser {
|
||||
private List propertyAccessors = new ArrayList();
|
||||
|
||||
public SpringELExpressionParser(SpelExpressionParser expressionParser) {
|
||||
this(expressionParser, new DefaultConversionService());
|
||||
}
|
||||
|
||||
public SpringELExpressionParser(SpelExpressionParser expressionParser, ConversionService conversionService) {
|
||||
this.expressionParser = expressionParser;
|
||||
this.propertyAccessors.add(new MapAccessor());
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
ensureConversionServiceInitialized();
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
private void ensureConversionServiceInitialized() {
|
||||
if (this.conversionService == null) {
|
||||
FormattingConversionServiceFactoryBean factoryBean = new FormattingConversionServiceFactoryBean() {
|
||||
protected void installFormatters(FormatterRegistry registry) {
|
||||
registry.addFormatterForFieldType(Date.class, new DateFormatter());
|
||||
}
|
||||
};
|
||||
factoryBean.afterPropertiesSet();
|
||||
this.conversionService = factoryBean.getObject();
|
||||
}
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void addPropertyAccessor(PropertyAccessor propertyAccessor) {
|
||||
@@ -90,17 +74,13 @@ public class SpringELExpressionParser implements ExpressionParser {
|
||||
Assert.hasText(expressionString, "The expression string to parse is required and must not be empty");
|
||||
parserContext = (parserContext == null) ? NullParserContext.INSTANCE : parserContext;
|
||||
StandardEvaluationContext evaluationContext = new StandardEvaluationContext();
|
||||
evaluationContext.setTypeConverter(getTypeConverter());
|
||||
evaluationContext.setTypeConverter(new StandardTypeConverter(conversionService.getDelegateConversionService()));
|
||||
evaluationContext.getPropertyAccessors().addAll(propertyAccessors);
|
||||
Map spelExpressionVariables = parseSpelExpressionVariables(parserContext.getExpressionVariables());
|
||||
return new SpringELExpression(parseSpelExpression(expressionString, parserContext), spelExpressionVariables,
|
||||
parserContext.getExpectedEvaluationResultType(), evaluationContext);
|
||||
}
|
||||
|
||||
private TypeConverter getTypeConverter() {
|
||||
return (conversionService != null) ? new StandardTypeConverter(conversionService) : new StandardTypeConverter();
|
||||
}
|
||||
|
||||
private org.springframework.expression.Expression parseSpelExpression(String expression, ParserContext parserContext) {
|
||||
return expressionParser.parseExpression(expression, getSpelParserContext(parserContext));
|
||||
}
|
||||
|
||||
@@ -15,13 +15,11 @@
|
||||
*/
|
||||
package org.springframework.binding.convert.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.security.Principal;
|
||||
import java.util.AbstractList;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
@@ -60,7 +58,6 @@ public class DefaultConversionServiceTests extends TestCase {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
StaticConversionExecutor executor = (StaticConversionExecutor) service.getConversionExecutor(String.class,
|
||||
Boolean.class);
|
||||
assertNotSame(customConverter, executor.getConverter());
|
||||
try {
|
||||
executor.execute("ja");
|
||||
fail();
|
||||
@@ -69,7 +66,6 @@ public class DefaultConversionServiceTests extends TestCase {
|
||||
}
|
||||
service.addConverter(customConverter);
|
||||
executor = (StaticConversionExecutor) service.getConversionExecutor(String.class, Boolean.class);
|
||||
assertSame(customConverter, executor.getConverter());
|
||||
assertTrue(((Boolean) executor.execute("ja")).booleanValue());
|
||||
}
|
||||
|
||||
@@ -510,16 +506,20 @@ public class DefaultConversionServiceTests extends TestCase {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, String[].class);
|
||||
String[] result = (String[]) executor.execute("1,2,3");
|
||||
assertEquals(1, result.length);
|
||||
assertEquals("1,2,3", result[0]);
|
||||
assertEquals(3, result.length);
|
||||
assertEquals("1", result[0]);
|
||||
assertEquals("2", result[1]);
|
||||
assertEquals("3", result[2]);
|
||||
}
|
||||
|
||||
public void testStringToListConversion() {
|
||||
DefaultConversionService service = new DefaultConversionService();
|
||||
ConversionExecutor executor = service.getConversionExecutor(String.class, List.class);
|
||||
List result = (List) executor.execute("1,2,3");
|
||||
assertEquals(1, result.size());
|
||||
assertEquals("1,2,3", result.get(0));
|
||||
assertEquals(3, result.size());
|
||||
assertEquals("1", result.get(0));
|
||||
assertEquals("2", result.get(1));
|
||||
assertEquals("3", result.get(2));
|
||||
}
|
||||
|
||||
public void testStringToArrayConversionWithElementConversion() {
|
||||
@@ -530,25 +530,6 @@ public class DefaultConversionServiceTests extends TestCase {
|
||||
assertEquals(new Integer(123), result[0]);
|
||||
}
|
||||
|
||||
public void testGetConversionExecutorsForSource() {
|
||||
DefaultConversionService service1 = new DefaultConversionService();
|
||||
service1.addConverter(new CustomConverter());
|
||||
GenericConversionService service2 = new GenericConversionService();
|
||||
FormattedStringToNumber formatterConverter = new FormattedStringToNumber(BigDecimal.class);
|
||||
service2.addConverter(formatterConverter);
|
||||
service2.setParent(service1);
|
||||
Set converters = service2.getConversionExecutors(String.class);
|
||||
Iterator it = converters.iterator();
|
||||
while (it.hasNext()) {
|
||||
ConversionExecutor executor = (ConversionExecutor) it.next();
|
||||
if (executor.getTargetClass().equals(BigDecimal.class)) {
|
||||
StaticConversionExecutor se = (StaticConversionExecutor) executor;
|
||||
assertSame(formatterConverter, se.getConverter());
|
||||
}
|
||||
}
|
||||
assertEquals(15, converters.size());
|
||||
}
|
||||
|
||||
private static class CustomConverter implements Converter {
|
||||
|
||||
public Object convertSourceToTargetClass(final Object source, Class targetClass) throws Exception {
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.binding.expression.beanwrapper;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.beans.TypeMismatchException;
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
import org.springframework.binding.convert.service.GenericConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ParserException;
|
||||
import org.springframework.binding.expression.ValueCoercionException;
|
||||
@@ -99,6 +101,10 @@ public class BeanWrapperExpressionParserTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testSetValueWithCoersion() {
|
||||
GenericConversionService cs = (GenericConversionService) parser.getConversionService();
|
||||
StringToDate converter = new StringToDate();
|
||||
converter.setPattern("yyyy-MM-dd");
|
||||
cs.addConverter(converter);
|
||||
Expression e = parser.parseExpression("date", null);
|
||||
e.setValue(bean, "2008-9-15");
|
||||
}
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.springframework.binding.expression.ognl;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
import org.springframework.binding.convert.service.GenericConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionVariable;
|
||||
@@ -203,6 +205,10 @@ public class OgnlExpressionParserTests extends TestCase {
|
||||
}
|
||||
|
||||
public void testSetValueWithCoersion() {
|
||||
GenericConversionService cs = (GenericConversionService) parser.getConversionService();
|
||||
StringToDate converter = new StringToDate();
|
||||
converter.setPattern("yyyy-MM-dd");
|
||||
cs.addConverter(converter);
|
||||
Expression e = parser.parseExpression("date", null);
|
||||
e.setValue(bean, "2008-9-15");
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.faces.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -123,6 +124,7 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle
|
||||
}
|
||||
|
||||
expressionParserBuilder.addConstructorArgValue(spelExpressionParser.getBeanDefinition());
|
||||
expressionParserBuilder.addConstructorArgReference(getConversionService(definitionBuilder));
|
||||
expressionParser = registerInfrastructureComponent(element, context, expressionParserBuilder);
|
||||
|
||||
} else if (enableManagedBeans) {
|
||||
@@ -141,6 +143,12 @@ public class FacesFlowBuilderServicesBeanDefinitionParser extends AbstractSingle
|
||||
}
|
||||
}
|
||||
|
||||
private String getConversionService(BeanDefinitionBuilder definitionBuilder) {
|
||||
RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition()
|
||||
.getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue();
|
||||
return conversionServiceReference.getBeanName();
|
||||
}
|
||||
|
||||
private String registerInfrastructureComponent(Element element, ParserContext context,
|
||||
BeanDefinitionBuilder componentBuilder) {
|
||||
String beanName = context.getReaderContext().generateBeanName(componentBuilder.getRawBeanDefinition());
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.util.ClassUtils;
|
||||
public class DataModelConverter implements Converter {
|
||||
|
||||
public Class getSourceClass() {
|
||||
return Object.class;
|
||||
return List.class;
|
||||
}
|
||||
|
||||
public Class getTargetClass() {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.faces.webflow;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.webflow.expression.spel.WebFlowSpringELExpressionParser;
|
||||
@@ -34,4 +35,9 @@ public class FacesSpringELExpressionParser extends WebFlowSpringELExpressionPars
|
||||
addPropertyAccessor(new JsfManagedBeanPropertyAccessor());
|
||||
}
|
||||
|
||||
public FacesSpringELExpressionParser(SpelExpressionParser expressionParser, ConversionService conversionService) {
|
||||
super(expressionParser, conversionService);
|
||||
addPropertyAccessor(new JsfManagedBeanPropertyAccessor());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ public class FacesFlowBuilderServicesBeanDefinitionParserTests extends TestCase
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof WebFlowSpringELExpressionParser);
|
||||
assertNotNull(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService());
|
||||
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof JsfViewFactoryCreator);
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
@@ -115,5 +115,9 @@ public class FacesFlowBuilderServicesBeanDefinitionParserTests extends TestCase
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,11 +32,12 @@
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->runtime"/>
|
||||
<dependency org="org.jboss.el" name="com.springsource.org.jboss.el" rev="2.0.0.GA" conf="compile->runtime"/>
|
||||
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
|
||||
@@ -53,9 +53,9 @@
|
||||
<version>1.8.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.el</groupId>
|
||||
<artifactId>com.springsource.org.jboss.el</artifactId>
|
||||
<version>2.0.0.GA</version>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -77,6 +77,11 @@
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.jdbc</artifactId>
|
||||
|
||||
@@ -36,12 +36,13 @@
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->runtime"/>
|
||||
<dependency org="org.ognl" name="com.springsource.org.ognl" rev="2.6.9" conf="compile->runtime"/>
|
||||
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context.support" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
|
||||
@@ -73,9 +73,9 @@
|
||||
<version>1.8.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.ognl</groupId>
|
||||
<artifactId>com.springsource.org.ognl</artifactId>
|
||||
<version>2.6.9</version>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -102,6 +102,11 @@
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.jdbc</artifactId>
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
package org.springframework.webflow.samples.booking;
|
||||
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component("conversionService")
|
||||
public class ApplicationConversionService extends DefaultConversionService {
|
||||
|
||||
@Override
|
||||
protected void addDefaultConverters() {
|
||||
super.addDefaultConverters();
|
||||
StringToDate dateConverter = new StringToDate();
|
||||
dateConverter.setPattern("MM-dd-yyyy");
|
||||
addConverter("shortDate", dateConverter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import javax.persistence.Transient;
|
||||
import org.springframework.binding.message.MessageBuilder;
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
import org.springframework.binding.validation.ValidationContext;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* A Hotel Booking made by a User.
|
||||
@@ -32,8 +33,10 @@ public class Booking implements Serializable {
|
||||
|
||||
private Hotel hotel;
|
||||
|
||||
@DateTimeFormat(pattern = "MM-dd-yyyy")
|
||||
private Date checkinDate;
|
||||
|
||||
@DateTimeFormat(pattern = "MM-dd-yyyy")
|
||||
private Date checkoutDate;
|
||||
|
||||
private String creditCard;
|
||||
@@ -73,7 +76,7 @@ public class Booking implements Serializable {
|
||||
if (checkinDate == null || checkoutDate == null) {
|
||||
return 0;
|
||||
} else {
|
||||
return (int) (checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24;
|
||||
return (int) ((checkoutDate.getTime() - checkinDate.getTime()) / 1000 / 60 / 60 / 24);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
</webflow:flow-registry>
|
||||
|
||||
<!-- Plugs in a custom creator for Web Flow views -->
|
||||
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" conversion-service="conversionService" development="true" />
|
||||
|
||||
<webflow:flow-builder-services id="flowBuilderServices" view-factory-creator="mvcViewFactoryCreator" development="true" />
|
||||
|
||||
<!-- Configures Web Flow to use Tiles to create views for rendering; Tiles allows for applying consistent layouts to your views -->
|
||||
<bean id="mvcViewFactoryCreator" class="org.springframework.webflow.mvc.builder.MvcViewFactoryCreator">
|
||||
<property name="viewResolvers" ref="tilesViewResolver"/>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="
|
||||
http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:mvc="http://www.springframework.org/schema/mvc"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
|
||||
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">
|
||||
|
||||
<!-- Maps request paths to flows in the flowRegistry; e.g. a path of /hotels/booking looks for a flow with id "hotels/booking" -->
|
||||
<bean class="org.springframework.webflow.mvc.servlet.FlowHandlerMapping">
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
<input name="hotelId" required="true" />
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails" model="booking">
|
||||
<binder>
|
||||
<binding property="checkinDate" converter="shortDate" required="true" />
|
||||
<binding property="checkoutDate" converter="shortDate" required="true" />
|
||||
<binding property="checkinDate" required="true" />
|
||||
<binding property="checkoutDate" required="true" />
|
||||
<binding property="beds" required="true" />
|
||||
<binding property="smoking" required="true" />
|
||||
<binding property="creditCard" required="true" />
|
||||
|
||||
@@ -34,11 +34,12 @@
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->compile"/>
|
||||
<dependency org="org.jboss.el" name="com.springsource.org.jboss.el" rev="2.0.0.GA" conf="compile->compile"/>
|
||||
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
|
||||
@@ -58,9 +58,9 @@
|
||||
<version>1.8.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.el</groupId>
|
||||
<artifactId>com.springsource.org.jboss.el</artifactId>
|
||||
<version>2.0.0.GA</version>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -82,6 +82,11 @@
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.jdbc</artifactId>
|
||||
|
||||
@@ -21,7 +21,6 @@
|
||||
|
||||
<dependencies>
|
||||
<!-- core dependencies -->
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->compile"/>
|
||||
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="compile->compile"/>
|
||||
<dependency org="javax.portlet" name="com.springsource.javax.portlet" rev="2.0.0" conf="provided->compile"/>
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.4.0" conf="provided->compile"/>
|
||||
@@ -34,11 +33,12 @@
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->compile"/>
|
||||
<dependency org="org.jboss.el" name="com.springsource.org.jboss.el" rev="2.0.0.GA" conf="compile->compile"/>
|
||||
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
|
||||
@@ -48,9 +48,9 @@
|
||||
<version>1.8.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.el</groupId>
|
||||
<artifactId>com.springsource.org.jboss.el</artifactId>
|
||||
<version>2.0.0.GA</version>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -72,6 +72,11 @@
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.jdbc</artifactId>
|
||||
@@ -119,12 +124,6 @@
|
||||
<version>2.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.el</groupId>
|
||||
<artifactId>com.springsource.javax.el</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>com.springsource.javax.servlet</artifactId>
|
||||
|
||||
@@ -16,6 +16,8 @@ import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
|
||||
/**
|
||||
* A Hotel Booking made by a User.
|
||||
*/
|
||||
@@ -27,8 +29,10 @@ public class Booking implements Serializable {
|
||||
|
||||
private Hotel hotel;
|
||||
|
||||
@DateTimeFormat(pattern = "MM-dd-yyyy")
|
||||
private Date checkinDate;
|
||||
|
||||
@DateTimeFormat(pattern = "MM-dd-yyyy")
|
||||
private Date checkoutDate;
|
||||
|
||||
private String creditCard;
|
||||
|
||||
@@ -21,32 +21,33 @@
|
||||
|
||||
<dependencies>
|
||||
<!-- core dependencies -->
|
||||
<dependency org="com.sun.facelets" name="com.springsource.com.sun.facelets" rev="1.1.14" conf="compile->compile"/>
|
||||
<dependency org="com.sun.faces" name="com.springsource.com.sun.faces" rev="1.2.0.09" conf="compile->compile" />
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->compile"/>
|
||||
<dependency org="javax.faces" name="com.springsource.javax.faces" rev="1.2.0.09" conf="compile->compile" />
|
||||
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="compile->compile"/>
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.4.0" conf="provided->compile"/>
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet.jsp.jstl" rev="1.1.2" conf="compile->compile"/>
|
||||
<dependency org="javax.transaction" name="com.springsource.javax.transaction" rev="1.1.0" conf="compile->compile"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="compile->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate" rev="3.2.6.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->compile"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->compile"/>
|
||||
<dependency org="org.jboss.el" name="com.springsource.org.jboss.el" rev="2.0.0.GA" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.web" rev="3.0.2.RELEASE" conf="compile->compile"/>
|
||||
<dependency org="com.sun.facelets" name="com.springsource.com.sun.facelets" rev="1.1.14" conf="compile->runtime"/>
|
||||
<dependency org="javax.el" name="com.springsource.javax.el" rev="1.0.0" conf="provided->runtime"/>
|
||||
<dependency org="com.sun.faces" name="com.springsource.com.sun.faces" rev="1.2.0.09" conf="compile->runtime" />
|
||||
<dependency org="javax.faces" name="com.springsource.javax.faces" rev="1.2.0.09" conf="compile->runtime" />
|
||||
<dependency org="javax.persistence" name="com.springsource.javax.persistence" rev="1.0.0" conf="compile->runtime"/>
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet" rev="2.4.0" conf="provided->runtime"/>
|
||||
<dependency org="javax.servlet" name="com.springsource.javax.servlet.jsp.jstl" rev="1.1.2" conf="compile->runtime"/>
|
||||
<dependency org="javax.transaction" name="com.springsource.javax.transaction" rev="1.1.0" conf="compile->runtime"/>
|
||||
<dependency org="org.apache.log4j" name="com.springsource.org.apache.log4j" rev="1.2.15" conf="compile->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate" rev="3.2.6.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.annotations" rev="3.3.0.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hibernate" name="com.springsource.org.hibernate.ejb" rev="3.3.1.ga" conf="compile->runtime"/>
|
||||
<dependency org="org.hsqldb" name="com.springsource.org.hsqldb" rev="1.8.0.9" conf="compile->runtime"/>
|
||||
<dependency org="org.joda" name="com.springsource.org.joda.time" rev="1.6.0" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.aop" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.beans" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.context" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.core" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.expression" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.jdbc" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.orm" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.transaction" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.web" rev="3.0.2.RELEASE" conf="compile->runtime"/>
|
||||
|
||||
<!-- test-time only dependencies -->
|
||||
<dependency org="org.junit" name="com.springsource.junit" rev="3.8.2" conf="test->compile"/>
|
||||
<dependency org="org.springframework" name="org.springframework.test" rev="3.0.2.RELEASE" conf="test->compile"/>
|
||||
<dependency org="org.junit" name="com.springsource.junit" rev="3.8.2" conf="test->runtime"/>
|
||||
<dependency org="org.springframework" name="org.springframework.test" rev="3.0.2.RELEASE" conf="test->runtime"/>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
@@ -63,9 +63,9 @@
|
||||
<version>1.8.0.9</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jboss.el</groupId>
|
||||
<artifactId>com.springsource.org.jboss.el</artifactId>
|
||||
<version>2.0.0.GA</version>
|
||||
<groupId>joda-time</groupId>
|
||||
<artifactId>joda-time</artifactId>
|
||||
<version>1.6</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
@@ -87,6 +87,11 @@
|
||||
<artifactId>org.springframework.core</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.expression</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>org.springframework.jdbc</artifactId>
|
||||
|
||||
@@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright 2004-2008 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.action;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
/**
|
||||
* Specifies how an action result value should be exposed to an executing flow. The return value is exposed as an
|
||||
* attribute in a configured scope.
|
||||
*
|
||||
* @see EvaluateAction
|
||||
*
|
||||
* @author Keith Donald
|
||||
*/
|
||||
public class ActionResultExposer implements Serializable {
|
||||
|
||||
/**
|
||||
* The expression to set the result to.
|
||||
*/
|
||||
private Expression resultExpression;
|
||||
|
||||
/**
|
||||
* The desired type to expose the result as
|
||||
*/
|
||||
private Class expectedResultType;
|
||||
|
||||
/**
|
||||
* The {@link ConversionService} to use to convert the result to the desired type
|
||||
*/
|
||||
private ConversionService conversionService;
|
||||
|
||||
/**
|
||||
* Creates a action result exposer
|
||||
* @param resultExpression the result expression
|
||||
* @param expectedResultType the expected result type
|
||||
*/
|
||||
public ActionResultExposer(Expression resultExpression, Class expectedResultType,
|
||||
ConversionService conversionService) {
|
||||
Assert.notNull(resultExpression, "The result expression is required");
|
||||
if (expectedResultType != null) {
|
||||
Assert.notNull(conversionService, "A conversionService is required with an expectedResultType");
|
||||
}
|
||||
this.resultExpression = resultExpression;
|
||||
this.expectedResultType = expectedResultType;
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns name of the attribute to index the return value with.
|
||||
*/
|
||||
public Expression getNameExpression() {
|
||||
return resultExpression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the desired result type to be exposed
|
||||
*/
|
||||
public Class getExpectedResultType() {
|
||||
return expectedResultType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Expose given bean method return value in given flow execution request context.
|
||||
* @param result the return value
|
||||
* @param context the request context
|
||||
*/
|
||||
public void exposeResult(Object result, RequestContext context) {
|
||||
resultExpression.setValue(context, applyTypeConversionIfNecessary(result));
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply type conversion on the supplied value if necessary.
|
||||
* @param value the raw value to be converted
|
||||
*/
|
||||
private Object applyTypeConversionIfNecessary(Object value) {
|
||||
if (value == null || expectedResultType == null) {
|
||||
return value;
|
||||
} else {
|
||||
return conversionService.getConversionExecutor(value.getClass(), expectedResultType).execute(value);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("result", resultExpression).append("resultType", expectedResultType)
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
* {@link Event}.
|
||||
*
|
||||
* @see Expression
|
||||
* @see ActionResultExposer
|
||||
* @see ResultEventFactory
|
||||
*
|
||||
* @author Keith Donald
|
||||
@@ -44,9 +43,9 @@ public class EvaluateAction extends AbstractAction {
|
||||
private Expression expression;
|
||||
|
||||
/**
|
||||
* The helper that will expose the expression evaluation result. Optional.
|
||||
* The expression to evaluate to set the result of the action. Optional.
|
||||
*/
|
||||
private ActionResultExposer evaluationResultExposer;
|
||||
private Expression resultExpression;
|
||||
|
||||
/**
|
||||
* The selector for the factory that will create the action result event callers can respond to.
|
||||
@@ -56,10 +55,10 @@ public class EvaluateAction extends AbstractAction {
|
||||
/**
|
||||
* Create a new evaluate action.
|
||||
* @param expression the expression to evaluate (required)
|
||||
* @param evaluationResultExposer the strategy for how the expression result will be exposed to the flow (optional)
|
||||
* @param resultExpression the expression to evaluate the result (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, ActionResultExposer evaluationResultExposer) {
|
||||
init(expression, evaluationResultExposer, null);
|
||||
public EvaluateAction(Expression expression, Expression resultExpression) {
|
||||
init(expression, resultExpression, null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,9 +67,8 @@ public class EvaluateAction extends AbstractAction {
|
||||
* @param evaluationResultExposer the strategy for how the expression result will be exposed to the flow (optional)
|
||||
* @param resultEventFactory the factory that will map the evaluation result to a Web Flow event (optional)
|
||||
*/
|
||||
public EvaluateAction(Expression expression, ActionResultExposer evaluationResultExposer,
|
||||
ResultEventFactory resultEventFactory) {
|
||||
init(expression, evaluationResultExposer, resultEventFactory);
|
||||
public EvaluateAction(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
init(expression, resultExpression, resultEventFactory);
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
@@ -78,25 +76,24 @@ public class EvaluateAction extends AbstractAction {
|
||||
if (result instanceof Action) {
|
||||
return ActionExecutor.execute((Action) result, context);
|
||||
} else {
|
||||
if (evaluationResultExposer != null) {
|
||||
evaluationResultExposer.exposeResult(result, context);
|
||||
if (resultExpression != null) {
|
||||
resultExpression.setValue(context, result);
|
||||
}
|
||||
return resultEventFactory.createResultEvent(this, result, context);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("expression", expression).append("resultExposer",
|
||||
evaluationResultExposer).toString();
|
||||
return new ToStringCreator(this).append("expression", expression).append("resultExpression", resultExpression)
|
||||
.toString();
|
||||
}
|
||||
|
||||
// internal helpers
|
||||
|
||||
private void init(Expression expression, ActionResultExposer evaluationResultExposer,
|
||||
ResultEventFactory resultEventFactory) {
|
||||
private void init(Expression expression, Expression resultExpression, ResultEventFactory resultEventFactory) {
|
||||
Assert.notNull(expression, "The expression this action should evaluate is required");
|
||||
this.expression = expression;
|
||||
this.evaluationResultExposer = evaluationResultExposer;
|
||||
this.resultExpression = resultExpression;
|
||||
this.resultEventFactory = resultEventFactory != null ? resultEventFactory : new DefaultResultEventFactory();
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.webflow.action;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -40,58 +39,26 @@ public class SetAction extends AbstractAction {
|
||||
*/
|
||||
private Expression valueExpression;
|
||||
|
||||
/**
|
||||
* The expected value type.
|
||||
*/
|
||||
private Class expectedType;
|
||||
|
||||
/**
|
||||
* The service to perform the type conversion if the actual value type does not match the expected.
|
||||
*/
|
||||
private ConversionService conversionService;
|
||||
|
||||
/**
|
||||
* Creates a new set attribute action.
|
||||
* @param nameExpression the name of the property to set (required)
|
||||
* @param valueExpression the expression to obtain the new property value (required)
|
||||
* @param expectedType the expected value type
|
||||
* @param conversionService the service to perform the type conversion if the actual value type does not match the
|
||||
* expected
|
||||
* @param valueExpression the expression to obtain the new property value (required) expected
|
||||
*/
|
||||
public SetAction(Expression nameExpression, Expression valueExpression, Class expectedType,
|
||||
ConversionService conversionService) {
|
||||
public SetAction(Expression nameExpression, Expression valueExpression) {
|
||||
Assert.notNull(nameExpression, "The name expression is required");
|
||||
Assert.notNull(valueExpression, "The value expression is required");
|
||||
if (expectedType != null) {
|
||||
Assert.notNull(conversionService, "The conversion service is required if the expectedType is provided");
|
||||
}
|
||||
this.nameExpression = nameExpression;
|
||||
this.valueExpression = valueExpression;
|
||||
this.expectedType = expectedType;
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
protected Event doExecute(RequestContext context) throws Exception {
|
||||
Object value = valueExpression.getValue(context);
|
||||
nameExpression.setValue(context, applyTypeConversionIfNecessary(value));
|
||||
nameExpression.setValue(context, value);
|
||||
return success();
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply type conversion on the supplied value if necessary.
|
||||
* @param value the raw value to be converted
|
||||
*/
|
||||
private Object applyTypeConversionIfNecessary(Object value) {
|
||||
if (value == null || expectedType == null) {
|
||||
return value;
|
||||
} else {
|
||||
return conversionService.getConversionExecutor(value.getClass(), expectedType).execute(value);
|
||||
}
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return new ToStringCreator(this).append("name", nameExpression).append("value", valueExpression).append("type",
|
||||
expectedType).toString();
|
||||
return new ToStringCreator(this).append("name", nameExpression).append("value", valueExpression).toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.webflow.config;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.config.RuntimeBeanReference;
|
||||
import org.springframework.beans.factory.parsing.BeanComponentDefinition;
|
||||
import org.springframework.beans.factory.parsing.CompositeComponentDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
@@ -88,6 +89,7 @@ class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefiniti
|
||||
.genericBeanDefinition(WEB_FLOW_SPRING_EL_EXPRESSION_PARSER_CLASS_NAME);
|
||||
webFlowElExpressionParserBuilder
|
||||
.addConstructorArgValue(springElExpressionParserBuilder.getBeanDefinition());
|
||||
webFlowElExpressionParserBuilder.addConstructorArgReference(getConversionService(definitionBuilder));
|
||||
expressionParser = registerInfrastructureComponent(element, context, webFlowElExpressionParserBuilder);
|
||||
}
|
||||
definitionBuilder.addPropertyReference(EXPRESSION_PARSER_PROPERTY, expressionParser);
|
||||
@@ -110,6 +112,12 @@ class FlowBuilderServicesBeanDefinitionParser extends AbstractSingleBeanDefiniti
|
||||
}
|
||||
}
|
||||
|
||||
private String getConversionService(BeanDefinitionBuilder definitionBuilder) {
|
||||
RuntimeBeanReference conversionServiceReference = (RuntimeBeanReference) definitionBuilder.getBeanDefinition()
|
||||
.getPropertyValues().getPropertyValue(CONVERSION_SERVICE_PROPERTY).getValue();
|
||||
return conversionServiceReference.getBeanName();
|
||||
}
|
||||
|
||||
private String registerInfrastructureComponent(Element element, ParserContext context,
|
||||
BeanDefinitionBuilder componentBuilder) {
|
||||
String beanName = context.getReaderContext().generateBeanName(componentBuilder.getRawBeanDefinition());
|
||||
|
||||
@@ -50,6 +50,22 @@ public class BinderConfiguration {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the converterId for the binding with the specified name. Returns null if either a binding or a converterId
|
||||
* for the given name is not found.
|
||||
*
|
||||
* @param name the name of the binding.
|
||||
* @return the binding
|
||||
*/
|
||||
public String getConverterId(String name) {
|
||||
Binding binding = getBinding(name);
|
||||
if (binding != null) {
|
||||
return binding.getConverter();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A binding that provides the information needed to connect an element of the view to a property of the model.
|
||||
*
|
||||
|
||||
@@ -48,7 +48,6 @@ import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.request.RequestScope;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.webflow.action.ActionResultExposer;
|
||||
import org.springframework.webflow.action.EvaluateAction;
|
||||
import org.springframework.webflow.action.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
@@ -342,7 +341,7 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
|
||||
flowContext.getBeanFactory().registerScope("conversation", new ConversationScope());
|
||||
Resource flowResource = flowModelHolder.getFlowModelResource();
|
||||
flowContext.setResourceLoader(new FlowRelativeResourceLoader(flowResource));
|
||||
if (JdkVersion.isAtLeastJava15()) {
|
||||
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_15) {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
|
||||
}
|
||||
new XmlBeanDefinitionReader(flowContext).loadBeanDefinitions(resources);
|
||||
@@ -852,25 +851,18 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
|
||||
}
|
||||
|
||||
private Action parseEvaluateAction(EvaluateModel evaluate) {
|
||||
String expressionString = evaluate.getExpression();
|
||||
Expression expression = getLocalContext().getExpressionParser().parseExpression(expressionString,
|
||||
new FluentParserContext().evaluate(RequestContext.class));
|
||||
return new EvaluateAction(expression, parseEvaluationActionResultExposer(evaluate));
|
||||
}
|
||||
|
||||
private ActionResultExposer parseEvaluationActionResultExposer(EvaluateModel evaluate) {
|
||||
if (StringUtils.hasText(evaluate.getResult())) {
|
||||
Expression resultExpression = getLocalContext().getExpressionParser().parseExpression(evaluate.getResult(),
|
||||
new FluentParserContext().evaluate(RequestContext.class));
|
||||
Class expectedResultType = null;
|
||||
if (StringUtils.hasText(evaluate.getResultType())) {
|
||||
expectedResultType = toClass(evaluate.getResultType());
|
||||
}
|
||||
return new ActionResultExposer(resultExpression, expectedResultType, getLocalContext()
|
||||
.getConversionService());
|
||||
} else {
|
||||
return null;
|
||||
FluentParserContext evaluateExpressionParserContext = new FluentParserContext().evaluate(RequestContext.class);
|
||||
if (StringUtils.hasText(evaluate.getResultType())) {
|
||||
evaluateExpressionParserContext.expectResult(toClass(evaluate.getResultType()));
|
||||
}
|
||||
Expression evaluateExpression = getLocalContext().getExpressionParser().parseExpression(
|
||||
evaluate.getExpression(), evaluateExpressionParserContext);
|
||||
Expression resultExpression = null;
|
||||
if (StringUtils.hasText(evaluate.getResult())) {
|
||||
resultExpression = getLocalContext().getExpressionParser().parseExpression(evaluate.getResult(),
|
||||
new FluentParserContext().evaluate(RequestContext.class));
|
||||
}
|
||||
return new EvaluateAction(evaluateExpression, resultExpression);
|
||||
}
|
||||
|
||||
private Action parseRenderAction(RenderModel render) {
|
||||
@@ -889,13 +881,13 @@ public class FlowModelFlowBuilder extends AbstractFlowBuilder {
|
||||
private Action parseSetAction(SetModel set) {
|
||||
Expression nameExpression = getLocalContext().getExpressionParser().parseExpression(set.getName(),
|
||||
new FluentParserContext().evaluate(RequestContext.class));
|
||||
Expression valueExpression = getLocalContext().getExpressionParser().parseExpression(set.getValue(),
|
||||
new FluentParserContext().evaluate(RequestContext.class));
|
||||
Class expectedType = null;
|
||||
FluentParserContext valueParserContext = new FluentParserContext().evaluate(RequestContext.class);
|
||||
if (StringUtils.hasText(set.getType())) {
|
||||
expectedType = toClass(set.getType());
|
||||
valueParserContext.expectResult(toClass(set.getType()));
|
||||
}
|
||||
return new SetAction(nameExpression, valueExpression, expectedType, getLocalContext().getConversionService());
|
||||
Expression valueExpression = getLocalContext().getExpressionParser().parseExpression(set.getValue(),
|
||||
valueParserContext);
|
||||
return new SetAction(nameExpression, valueExpression);
|
||||
}
|
||||
|
||||
private MutableAttributeMap parseMetaAttributes(List attributeModels) {
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.webflow.engine.builder.support;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.binding.convert.ConversionException;
|
||||
import org.springframework.binding.convert.ConversionExecutionException;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
@@ -113,7 +111,8 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
|
||||
* @return the flow builder conversion service
|
||||
*/
|
||||
protected ConversionService createConversionService() {
|
||||
GenericConversionService service = new GenericConversionService();
|
||||
GenericConversionService service = new GenericConversionService(getFlowBuilderServices().getConversionService()
|
||||
.getDelegateConversionService());
|
||||
service.addConverter(new TextToTransitionCriteria(this));
|
||||
service.addConverter(new TextToTargetStateResolver(this));
|
||||
service.setParent(new ParentConversionServiceProxy());
|
||||
@@ -145,10 +144,6 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
|
||||
return getFlowBuilderServices().getConversionService().getConversionExecutor(sourceClass, targetClass);
|
||||
}
|
||||
|
||||
public Set getConversionExecutors(Class sourceClass) {
|
||||
return getFlowBuilderServices().getConversionService().getConversionExecutors(sourceClass);
|
||||
}
|
||||
|
||||
public ConversionExecutor getConversionExecutor(String id, Class sourceClass, Class targetClass)
|
||||
throws ConversionExecutorNotFoundException {
|
||||
return getFlowBuilderServices().getConversionService().getConversionExecutor(id, sourceClass, targetClass);
|
||||
@@ -158,6 +153,10 @@ public class FlowBuilderContextImpl implements FlowBuilderContext {
|
||||
return getFlowBuilderServices().getConversionService().getClassForAlias(name);
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
return getFlowBuilderServices().getConversionService().getDelegateConversionService();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package org.springframework.webflow.expression.spel;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
|
||||
@@ -28,6 +29,15 @@ public class WebFlowSpringELExpressionParser extends SpringELExpressionParser {
|
||||
|
||||
public WebFlowSpringELExpressionParser(SpelExpressionParser expressionParser) {
|
||||
super(expressionParser);
|
||||
addDefaultPropertyAccessors();
|
||||
}
|
||||
|
||||
public WebFlowSpringELExpressionParser(SpelExpressionParser expressionParser, ConversionService conversionService) {
|
||||
super(expressionParser, conversionService);
|
||||
addDefaultPropertyAccessors();
|
||||
}
|
||||
|
||||
private void addDefaultPropertyAccessors() {
|
||||
addPropertyAccessor(new MessageSourcePropertyAccessor());
|
||||
addPropertyAccessor(new FlowVariablePropertyAccessor());
|
||||
addPropertyAccessor(new MapAdaptablePropertyAccessor());
|
||||
|
||||
@@ -22,8 +22,9 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
import org.springframework.beans.PropertyAccessorFactory;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.binding.convert.ConversionExecutor;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
@@ -35,6 +36,7 @@ import org.springframework.binding.message.Message;
|
||||
import org.springframework.binding.message.MessageContext;
|
||||
import org.springframework.binding.message.MessageCriteria;
|
||||
import org.springframework.binding.message.Severity;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.validation.AbstractErrors;
|
||||
import org.springframework.validation.BindingResult;
|
||||
@@ -42,7 +44,6 @@ import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration;
|
||||
import org.springframework.webflow.engine.builder.BinderConfiguration.Binding;
|
||||
|
||||
/**
|
||||
* Makes the properties of the "model" object available to Spring views during rendering. Also makes data binding (aka
|
||||
@@ -126,7 +127,7 @@ public class BindingModel extends AbstractErrors implements BindingResult {
|
||||
}
|
||||
|
||||
public Class getFieldType(String field) {
|
||||
return parseFieldExpression(fixedField(field)).getValueType(boundObject);
|
||||
return parseFieldExpression(fixedField(field), false).getValueType(boundObject);
|
||||
}
|
||||
|
||||
public Object getFieldValue(String field) {
|
||||
@@ -138,7 +139,7 @@ public class BindingModel extends AbstractErrors implements BindingResult {
|
||||
return fieldError.getOriginalValue();
|
||||
}
|
||||
}
|
||||
return getFormattedValue(parseFieldExpression(field));
|
||||
return getFormattedValue(field);
|
||||
}
|
||||
|
||||
// not typically used by mvc views, but implemented to be on the safe side
|
||||
@@ -172,32 +173,14 @@ public class BindingModel extends AbstractErrors implements BindingResult {
|
||||
}
|
||||
|
||||
public Object getRawFieldValue(String field) {
|
||||
return parseFieldExpression(fixedField(field)).getValue(boundObject);
|
||||
return parseFieldExpression(fixedField(field), false).getValue(boundObject);
|
||||
}
|
||||
|
||||
public PropertyEditor findEditor(String field, Class valueType) {
|
||||
if (conversionService != null) {
|
||||
String converterId = null;
|
||||
if (field != null) {
|
||||
field = fixedField(field);
|
||||
if (binderConfiguration != null) {
|
||||
Binding binding = binderConfiguration.getBinding(field);
|
||||
if (binding != null) {
|
||||
converterId = binding.getConverter();
|
||||
}
|
||||
}
|
||||
if (valueType == null) {
|
||||
valueType = parseFieldExpression(field).getValueType(boundObject);
|
||||
}
|
||||
}
|
||||
if (valueType != null) {
|
||||
return new ConversionExecutorPropertyEditor(conversionService, valueType, converterId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
if (field != null) {
|
||||
field = fixedField(field);
|
||||
}
|
||||
return findSpringConvertingPropertyEditor(field, valueType);
|
||||
}
|
||||
|
||||
// never expected to be called by mvc views
|
||||
@@ -228,39 +211,69 @@ public class BindingModel extends AbstractErrors implements BindingResult {
|
||||
|
||||
// internal helpers
|
||||
|
||||
private Expression parseFieldExpression(String field) {
|
||||
return expressionParser.parseExpression(field, new FluentParserContext().evaluate(boundObject.getClass()));
|
||||
}
|
||||
|
||||
private Object getFormattedValue(Expression fieldExpression) {
|
||||
ConversionExecutor converter = getConverter(fieldExpression);
|
||||
if (converter != null) {
|
||||
return converter.execute(fieldExpression.getValue(boundObject));
|
||||
} else {
|
||||
return fieldExpression.getValue(boundObject);
|
||||
private Expression parseFieldExpression(String field, boolean useResultTypeHint) {
|
||||
FluentParserContext parserContext = new FluentParserContext().evaluate(boundObject.getClass());
|
||||
if (useResultTypeHint) {
|
||||
parserContext.expectResult(String.class);
|
||||
}
|
||||
return expressionParser.parseExpression(field, parserContext);
|
||||
}
|
||||
|
||||
private ConversionExecutor getConverter(Expression fieldExpression) {
|
||||
if (conversionService != null) {
|
||||
Class valueType = fieldExpression.getValueType(boundObject);
|
||||
// special handling for array, collection, map types
|
||||
// necessary as getFieldValue is called by form tags for non-formattable properties, too
|
||||
// TODO - investigate how to improve this in Spring MVC
|
||||
if (valueType == null || valueType.isArray() || Collection.class.isAssignableFrom(valueType)
|
||||
|| Map.class.isAssignableFrom(valueType)) {
|
||||
return null;
|
||||
}
|
||||
if (binderConfiguration != null) {
|
||||
Binding binding = binderConfiguration.getBinding(fieldExpression.getExpressionString());
|
||||
if (binding != null) {
|
||||
String converterId = binding.getConverter();
|
||||
if (converterId != null) {
|
||||
return conversionService.getConversionExecutor(converterId, valueType, String.class);
|
||||
}
|
||||
private Object getFormattedValue(String field) {
|
||||
Expression fieldExpression = parseFieldExpression(field, true);
|
||||
Class valueType = fieldExpression.getValueType(boundObject);
|
||||
if (isCustomConverterConfigured(field) || avoidConversion(valueType)) {
|
||||
fieldExpression = parseFieldExpression(fieldExpression.getExpressionString(), false);
|
||||
}
|
||||
Object value = fieldExpression.getValue(boundObject);
|
||||
if ((value instanceof String) == false) {
|
||||
if (avoidConversion(valueType) == false) {
|
||||
PropertyEditor editor = findSpringConvertingPropertyEditor(field, valueType);
|
||||
if (editor != null) {
|
||||
editor.setValue(value);
|
||||
value = editor.getAsText();
|
||||
}
|
||||
}
|
||||
return conversionService.getConversionExecutor(valueType, String.class);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
private boolean isCustomConverterConfigured(String field) {
|
||||
if (binderConfiguration == null) {
|
||||
return false;
|
||||
}
|
||||
return (binderConfiguration.getConverterId(field) != null);
|
||||
}
|
||||
|
||||
private boolean avoidConversion(Class valueType) {
|
||||
// special handling for array, collection, map types
|
||||
// necessary as getFieldValue is called by form tags for non-formattable properties, too
|
||||
// TODO - investigate how to improve this in Spring MVC
|
||||
if (valueType == null || valueType.isArray() || Collection.class.isAssignableFrom(valueType)
|
||||
|| Map.class.isAssignableFrom(valueType)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private PropertyEditor findSpringConvertingPropertyEditor(String field, Class valueType) {
|
||||
if (conversionService != null) {
|
||||
String converterId = null;
|
||||
if (field != null) {
|
||||
if (binderConfiguration != null) {
|
||||
converterId = binderConfiguration.getConverterId(field);
|
||||
}
|
||||
if (valueType == null) {
|
||||
valueType = parseFieldExpression(field, false).getValueType(boundObject);
|
||||
}
|
||||
}
|
||||
if (valueType != null) {
|
||||
BeanWrapper accessor = PropertyAccessorFactory.forBeanPropertyAccess(boundObject);
|
||||
TypeDescriptor typeDescriptor = accessor.getPropertyTypeDescriptor(field);
|
||||
return new ConvertingPropertyEditorAdapter(conversionService, converterId, typeDescriptor);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2004-2007 the original author or authors.
|
||||
* Copyright 2004-2010 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -15,40 +15,63 @@
|
||||
*/
|
||||
package org.springframework.webflow.mvc.view;
|
||||
|
||||
import java.beans.PropertyEditor;
|
||||
import java.beans.PropertyEditorSupport;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class ConversionExecutorPropertyEditor extends PropertyEditorSupport {
|
||||
/**
|
||||
* <p>
|
||||
* A {@link PropertyEditor} that delegates to a Spring ConversionService unless a converterId is provided. When a
|
||||
* converterId is provided, conversion will be delegated to the Spring Binding ConversionService instead as Spring's
|
||||
* type conversion system does not support named converters.
|
||||
* </p>
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
*/
|
||||
class ConvertingPropertyEditorAdapter extends PropertyEditorSupport {
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
private Class fieldType;
|
||||
private TypeDescriptor fieldType;
|
||||
|
||||
private String converterId;
|
||||
|
||||
public ConversionExecutorPropertyEditor(ConversionService conversionService, Class fieldType, String converterId) {
|
||||
private boolean canConvertToString;
|
||||
|
||||
public ConvertingPropertyEditorAdapter(ConversionService conversionService, String converterId,
|
||||
TypeDescriptor fieldType) {
|
||||
Assert.notNull(conversionService, "A ConversionService instance is required.");
|
||||
Assert.notNull(fieldType, "The field type is required");
|
||||
this.conversionService = conversionService;
|
||||
this.fieldType = fieldType;
|
||||
this.converterId = converterId;
|
||||
this.canConvertToString = conversionService.getDelegateConversionService().canConvert(this.fieldType,
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
}
|
||||
|
||||
public String getAsText() {
|
||||
if (StringUtils.hasText(converterId)) {
|
||||
return (String) conversionService.executeConversion(converterId, getValue(), String.class);
|
||||
} else {
|
||||
return (String) conversionService.executeConversion(getValue(), String.class);
|
||||
if (canConvertToString) {
|
||||
return (String) conversionService.getDelegateConversionService().convert(getValue(), fieldType,
|
||||
TypeDescriptor.valueOf(String.class));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void setAsText(String text) throws IllegalArgumentException {
|
||||
if (StringUtils.hasText(converterId)) {
|
||||
setValue(conversionService.executeConversion(converterId, text, fieldType));
|
||||
setValue(conversionService.executeConversion(converterId, text, fieldType.getType()));
|
||||
} else {
|
||||
setValue(conversionService.executeConversion(text, fieldType));
|
||||
setValue(conversionService.getDelegateConversionService().convert(text,
|
||||
TypeDescriptor.valueOf(String.class), fieldType));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.springframework.webflow.test;
|
||||
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
@@ -15,10 +16,15 @@ public class TestFlowBuilderServicesFactory {
|
||||
}
|
||||
|
||||
public static FlowBuilderServices getServices() {
|
||||
FlowBuilderServices services = new FlowBuilderServices();
|
||||
FlowBuilderServices services = new FlowBuilderServices() {
|
||||
// The SpEL parser must use the currently configured conversion service.
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
super.setConversionService(conversionService);
|
||||
setExpressionParser(new WebFlowSpringELExpressionParser(new SpelExpressionParser(), conversionService));
|
||||
}
|
||||
};
|
||||
services.setViewFactoryCreator(new MockViewFactoryCreator());
|
||||
services.setConversionService(new DefaultConversionService());
|
||||
services.setExpressionParser(new WebFlowSpringELExpressionParser(new SpelExpressionParser()));
|
||||
services.setApplicationContext(createTestApplicationContext());
|
||||
return services;
|
||||
}
|
||||
@@ -28,4 +34,5 @@ public class TestFlowBuilderServicesFactory {
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
package org.springframework.webflow.action;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.support.StaticExpression;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class ActionResultExposerTests extends TestCase {
|
||||
|
||||
public void testEvaluateExpressionResult() throws Exception {
|
||||
StaticExpression resultExpression = new StaticExpression("");
|
||||
ActionResultExposer exposer = new ActionResultExposer(resultExpression, null, null);
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
exposer.exposeResult("foo", context);
|
||||
assertEquals("foo", resultExpression.getValue(null));
|
||||
}
|
||||
|
||||
public void testEvaluateExpressionNullResult() throws Exception {
|
||||
StaticExpression resultExpression = new StaticExpression("");
|
||||
ActionResultExposer exposer = new ActionResultExposer(resultExpression, null, null);
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
exposer.exposeResult(null, context);
|
||||
assertEquals(null, resultExpression.getValue(null));
|
||||
}
|
||||
|
||||
public void testEvaluateExpressionResultExposerWithTypeConversion() throws Exception {
|
||||
StaticExpression resultExpression = new StaticExpression("");
|
||||
ActionResultExposer exposer = new ActionResultExposer(resultExpression, Integer.class,
|
||||
new DefaultConversionService());
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
exposer.exposeResult("3", context);
|
||||
assertEquals(new Integer(3), resultExpression.getValue(null));
|
||||
}
|
||||
|
||||
public void testEvaluateExpressionResultExposerWithTypeConversionForgotArgument() throws Exception {
|
||||
StaticExpression resultExpression = new StaticExpression("");
|
||||
try {
|
||||
new ActionResultExposer(resultExpression, Integer.class, null);
|
||||
fail("should have failed iae");
|
||||
} catch (IllegalArgumentException e) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -50,8 +50,7 @@ public class EvaluateActionTests extends TestCase {
|
||||
|
||||
public void testEvaluateExpressionResultExposer() throws Exception {
|
||||
StaticExpression resultExpression = new StaticExpression("");
|
||||
EvaluateAction action = new EvaluateAction(new StaticExpression("bar"), new ActionResultExposer(
|
||||
resultExpression, null, null));
|
||||
EvaluateAction action = new EvaluateAction(new StaticExpression("bar"), resultExpression);
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
Event result = action.execute(context);
|
||||
assertEquals("bar", result.getId());
|
||||
|
||||
@@ -2,28 +2,19 @@ package org.springframework.webflow.action;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.expression.support.StaticExpression;
|
||||
import org.springframework.webflow.execution.Event;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class SetActionTests extends TestCase {
|
||||
|
||||
public void testSetAction() throws Exception {
|
||||
StaticExpression name = new StaticExpression("");
|
||||
SetAction action = new SetAction(name, new StaticExpression("bar"), null, null);
|
||||
SetAction action = new SetAction(name, new StaticExpression("bar"));
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
Event result = action.execute(context);
|
||||
assertEquals("success", result.getId());
|
||||
assertEquals("bar", name.getValue(null));
|
||||
}
|
||||
|
||||
public void testSetActionWithTypeConversion() throws Exception {
|
||||
StaticExpression name = new StaticExpression("");
|
||||
SetAction action = new SetAction(name, new StaticExpression("3"), Integer.class, new DefaultConversionService());
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
Event result = action.execute(context);
|
||||
assertEquals("success", result.getId());
|
||||
assertEquals(new Integer(3), name.getValue(null));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
|
||||
assertNotNull(builderServices);
|
||||
assertTrue(builderServices.getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getExpressionParser() instanceof SpringELExpressionParser);
|
||||
assertNotNull(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService());
|
||||
assertTrue(((SpringELExpressionParser) builderServices.getExpressionParser()).getConversionService() instanceof TestConversionService);
|
||||
assertTrue(builderServices.getViewFactoryCreator() instanceof MvcViewFactoryCreator);
|
||||
assertFalse(builderServices.getDevelopment());
|
||||
}
|
||||
@@ -98,6 +98,10 @@ public class FlowBuilderServicesBeanDefinitionParserTests extends TestCase {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
public org.springframework.core.convert.ConversionService getDelegateConversionService() {
|
||||
throw new UnsupportedOperationException("Auto-generated method stub");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import org.springframework.webflow.engine.builder.FlowBuilderException;
|
||||
import org.springframework.webflow.engine.impl.FlowExecutionImplFactory;
|
||||
import org.springframework.webflow.engine.model.AttributeModel;
|
||||
import org.springframework.webflow.engine.model.EndStateModel;
|
||||
import org.springframework.webflow.engine.model.EvaluateModel;
|
||||
import org.springframework.webflow.engine.model.ExceptionHandlerModel;
|
||||
import org.springframework.webflow.engine.model.FlowModel;
|
||||
import org.springframework.webflow.engine.model.InputModel;
|
||||
@@ -27,6 +28,7 @@ import org.springframework.webflow.engine.model.Model;
|
||||
import org.springframework.webflow.engine.model.OutputModel;
|
||||
import org.springframework.webflow.engine.model.PersistenceContextModel;
|
||||
import org.springframework.webflow.engine.model.SecuredModel;
|
||||
import org.springframework.webflow.engine.model.SetModel;
|
||||
import org.springframework.webflow.engine.model.TransitionModel;
|
||||
import org.springframework.webflow.engine.model.VarModel;
|
||||
import org.springframework.webflow.engine.model.ViewStateModel;
|
||||
@@ -36,6 +38,7 @@ import org.springframework.webflow.engine.model.builder.xml.XmlFlowModelBuilderT
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelHolder;
|
||||
import org.springframework.webflow.engine.model.registry.FlowModelRegistryImpl;
|
||||
import org.springframework.webflow.engine.support.ActionExecutingViewFactory;
|
||||
import org.springframework.webflow.execution.AnnotatedAction;
|
||||
import org.springframework.webflow.execution.FlowExecution;
|
||||
import org.springframework.webflow.execution.FlowExecutionException;
|
||||
import org.springframework.webflow.execution.FlowExecutionOutcome;
|
||||
@@ -43,6 +46,7 @@ import org.springframework.webflow.execution.ViewFactory;
|
||||
import org.springframework.webflow.security.SecurityRule;
|
||||
import org.springframework.webflow.test.MockExternalContext;
|
||||
import org.springframework.webflow.test.MockFlowBuilderContext;
|
||||
import org.springframework.webflow.test.MockRequestContext;
|
||||
|
||||
public class FlowModelFlowBuilderTests extends TestCase {
|
||||
private FlowModel model;
|
||||
@@ -306,6 +310,77 @@ public class FlowModelFlowBuilderTests extends TestCase {
|
||||
assertEquals(1, flow.getExceptionHandlerSet().size());
|
||||
}
|
||||
|
||||
public void testSetActionWithResultType() throws Exception {
|
||||
SetModel setModel = new SetModel("flowScope.stringArray", "intArray");
|
||||
setModel.setType("java.lang.String[]");
|
||||
model.setOnStartActions(singleList(setModel));
|
||||
model.setStates(singleList(new ViewStateModel("view")));
|
||||
Flow flow = getFlow(model);
|
||||
AnnotatedAction action = (AnnotatedAction) flow.getStartActionList().get(0);
|
||||
MockRequestContext context = new MockRequestContext(flow);
|
||||
context.getFlowScope().put("intArray", new int[] { 1, 2 });
|
||||
action.execute(context);
|
||||
String[] expected = (String[]) context.getFlowScope().get("stringArray");
|
||||
assertEquals("1", expected[0]);
|
||||
assertEquals("2", expected[1]);
|
||||
}
|
||||
|
||||
public void testSetActionWithImplicitTypeConversion() throws Exception {
|
||||
SetModel setModel = new SetModel("testBean.stringArray", "intArray");
|
||||
model.setOnStartActions(singleList(setModel));
|
||||
ViewStateModel state = new ViewStateModel("view");
|
||||
model.setStates(singleList(state));
|
||||
Flow flow = getFlow(model);
|
||||
AnnotatedAction action = (AnnotatedAction) flow.getStartActionList().get(0);
|
||||
MockRequestContext context = new MockRequestContext(flow);
|
||||
context.getFlowScope().put("testBean", new TestBean());
|
||||
context.getFlowScope().put("intArray", new int[] { 1, 2 });
|
||||
action.execute(context);
|
||||
TestBean expected = (TestBean) context.getFlowScope().get("testBean");
|
||||
assertEquals("1", expected.stringArray[0]);
|
||||
assertEquals("2", expected.stringArray[1]);
|
||||
}
|
||||
|
||||
public void testEvaluateActionWithResultType() throws Exception {
|
||||
EvaluateModel evaluateModel = new EvaluateModel("testBean.getIntegers()");
|
||||
evaluateModel.setResult("flowScope.stringArray");
|
||||
evaluateModel.setResultType("java.lang.String[]");
|
||||
model.setOnStartActions(singleList(evaluateModel));
|
||||
model.setStates(singleList(new ViewStateModel("view")));
|
||||
Flow flow = getFlow(model);
|
||||
AnnotatedAction action = (AnnotatedAction) flow.getStartActionList().get(0);
|
||||
MockRequestContext context = new MockRequestContext(flow);
|
||||
context.getFlowScope().put("testBean", new TestBean());
|
||||
action.execute(context);
|
||||
String[] expected = (String[]) context.getFlowScope().get("stringArray");
|
||||
assertEquals("1", expected[0]);
|
||||
assertEquals("2", expected[1]);
|
||||
}
|
||||
|
||||
public void testEvaluateActionWithELExpression() throws Exception {
|
||||
EvaluateModel evaluateModel = new EvaluateModel("testBean.getIntegers()");
|
||||
evaluateModel.setResult("flowScope.stringArray");
|
||||
evaluateModel.setResultType("java.lang.String[]");
|
||||
model.setOnStartActions(singleList(evaluateModel));
|
||||
model.setStates(singleList(new ViewStateModel("view")));
|
||||
Flow flow = getFlow(model);
|
||||
AnnotatedAction action = (AnnotatedAction) flow.getStartActionList().get(0);
|
||||
MockRequestContext context = new MockRequestContext(flow);
|
||||
context.getFlowScope().put("testBean", new TestBean());
|
||||
action.execute(context);
|
||||
String[] expected = (String[]) context.getFlowScope().get("stringArray");
|
||||
assertEquals("1", expected[0]);
|
||||
assertEquals("2", expected[1]);
|
||||
}
|
||||
|
||||
private static class TestBean {
|
||||
public String[] stringArray;
|
||||
|
||||
public int[] getIntegers() {
|
||||
return new int[] { 1, 2 };
|
||||
}
|
||||
}
|
||||
|
||||
private Flow getFlow(FlowModel model) {
|
||||
FlowModelHolder holder = new StaticFlowModelHolder(model);
|
||||
FlowModelFlowBuilder builder = new FlowModelFlowBuilder(holder);
|
||||
|
||||
@@ -66,12 +66,6 @@ public abstract class AbstractBindingModelTests extends TestCase {
|
||||
assertEquals(new Integer(3), model.getRawFieldValue("datum2"));
|
||||
}
|
||||
|
||||
public void testGetFieldValueNonStringNoConversionService() {
|
||||
model = new BindingModel("testBean", testBean, getExpressionParser(), null, messages);
|
||||
testBean.datum2 = 3;
|
||||
assertEquals(new Integer(3), model.getFieldValue("datum2"));
|
||||
}
|
||||
|
||||
public void testGetFieldValueConvertedWithCustomConverter() {
|
||||
testBean.datum2 = 3;
|
||||
conversionService.addConverter("customConverter", new StringToObject(Integer.class) {
|
||||
|
||||
@@ -6,7 +6,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.security.Principal;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
@@ -19,14 +18,13 @@ import junit.framework.TestCase;
|
||||
|
||||
import org.springframework.binding.convert.converters.StringToDate;
|
||||
import org.springframework.binding.convert.service.DefaultConversionService;
|
||||
import org.springframework.binding.convert.service.GenericConversionService;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.spel.SpringELExpressionParser;
|
||||
import org.springframework.binding.expression.support.StaticExpression;
|
||||
import org.springframework.binding.validation.ValidationContext;
|
||||
import org.springframework.expression.spel.standard.SpelExpressionParser;
|
||||
import org.springframework.format.datetime.DateFormatter;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
import org.springframework.mock.web.MockHttpServletResponse;
|
||||
import org.springframework.mock.web.MockMultipartFile;
|
||||
@@ -393,8 +391,8 @@ public class MvcViewTests extends TestCase {
|
||||
assertEquals(context2.getFlowScope().get("bindBean"), model.get("bindBean"));
|
||||
BindingModel bm = (BindingModel) model.get(BindingResult.MODEL_KEY_PREFIX + "bindBean");
|
||||
assertNotNull(bm);
|
||||
assertEquals(new Integer(3), bm.getFieldValue("integerProperty"));
|
||||
assertEquals(new SimpleDateFormat("MM-dd-yyyy").parse("01-01-2008"), bm.getFieldValue("dateProperty"));
|
||||
assertEquals("3", bm.getFieldValue("integerProperty"));
|
||||
assertEquals("2008-01-01", bm.getFieldValue("dateProperty"));
|
||||
}
|
||||
|
||||
private Object saveAndRestoreViewActionState(Object viewActionState) throws Exception {
|
||||
@@ -630,11 +628,12 @@ public class MvcViewTests extends TestCase {
|
||||
}
|
||||
|
||||
private SpringELExpressionParser createExpressionParser() {
|
||||
SpringELExpressionParser expressionParser = new WebFlowSpringELExpressionParser(new SpelExpressionParser());
|
||||
FormattingConversionService conversionService = (FormattingConversionService) expressionParser
|
||||
.getConversionService();
|
||||
conversionService.addFormatterForFieldType(Date.class, new DateFormatter("yyyy-MM-dd"));
|
||||
return expressionParser;
|
||||
StringToDate c = new StringToDate();
|
||||
c.setPattern("yyyy-MM-dd");
|
||||
SpringELExpressionParser parser = new WebFlowSpringELExpressionParser(new SpelExpressionParser());
|
||||
GenericConversionService cs = (GenericConversionService) parser.getConversionService();
|
||||
cs.addConverter(c);
|
||||
return parser;
|
||||
}
|
||||
|
||||
private class MockMvcView extends AbstractMvcView {
|
||||
|
||||
@@ -16,4 +16,13 @@ public class SpringBeanBindingModelTests extends AbstractBindingModelTests {
|
||||
PropertyEditor editor = model.findEditor("emptyMap['foo']", null);
|
||||
assertNull(editor);
|
||||
}
|
||||
|
||||
// BeanWrapper-based EL does not accept result type hints.
|
||||
// Hence it requires a conversion service.
|
||||
public void testGetFieldValueNonStringNoConversionService() {
|
||||
model = new BindingModel("testBean", testBean, getExpressionParser(), null, messages);
|
||||
testBean.datum2 = 3;
|
||||
assertEquals(new Integer(3), model.getFieldValue("datum2"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user