bind target initial commit
sample polishing
This commit is contained in:
@@ -135,11 +135,11 @@ public class GenericConversionService implements ConversionService {
|
||||
if (this.sourceClassConverters == null || this.sourceClassConverters.isEmpty()) {
|
||||
throw new IllegalStateException("No converters have been added to this service's registry");
|
||||
}
|
||||
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
|
||||
targetClass = convertToWrapperClassIfNecessary(targetClass);
|
||||
if (targetClass.isAssignableFrom(sourceClass)) {
|
||||
return new ConversionExecutorImpl(sourceClass, targetClass, new NoOpConverter(sourceClass, targetClass));
|
||||
}
|
||||
sourceClass = convertToWrapperClassIfNecessary(sourceClass);
|
||||
targetClass = convertToWrapperClassIfNecessary(targetClass);
|
||||
Map sourceTargetConverters = findConvertersForSource(sourceClass);
|
||||
Converter converter = findTargetConverter(sourceTargetConverters, targetClass);
|
||||
if (converter != null) {
|
||||
|
||||
@@ -56,16 +56,6 @@ public class Mapping {
|
||||
*/
|
||||
private boolean required;
|
||||
|
||||
/**
|
||||
* Creates a new mapping.
|
||||
* @param sourceExpression the source expression
|
||||
* @param targetExpression the target expression
|
||||
* @param typeConverter a type converter
|
||||
*/
|
||||
public Mapping(Expression sourceExpression, Expression targetExpression, ConversionExecutor typeConverter) {
|
||||
this(sourceExpression, targetExpression, typeConverter, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new mapping.
|
||||
* @param sourceExpression the source expression
|
||||
@@ -94,7 +84,7 @@ public class Mapping {
|
||||
Assert.notNull(target, "The target to map to is required");
|
||||
Assert.notNull(context, "The mapping context is required");
|
||||
Object sourceValue = sourceExpression.getValue(source);
|
||||
if (required && sourceValue == null || isEmptyString(sourceValue)) {
|
||||
if (required && (sourceValue == null || isEmptyString(sourceValue))) {
|
||||
String defaultText = "'" + targetExpression.getExpressionString() + "' is required";
|
||||
MessageResolver message = new MessageBuilder().error().source(targetExpression.getExpressionString())
|
||||
.codes(createMessageCodes("required", target, targetExpression)).defaultText(defaultText).build();
|
||||
@@ -106,6 +96,7 @@ public class Mapping {
|
||||
try {
|
||||
targetValue = typeConverter.execute(sourceValue);
|
||||
} catch (ConversionException e) {
|
||||
e.printStackTrace();
|
||||
String defaultText = "The '" + targetExpression.getExpressionString() + "' value is the wrong type";
|
||||
MessageResolver message = new MessageBuilder().error().source(targetExpression.getExpressionString())
|
||||
.codes(createMessageCodes("typeMismatch", target, targetExpression)).defaultText(defaultText)
|
||||
|
||||
@@ -29,16 +29,18 @@ public interface BookingService {
|
||||
*/
|
||||
public Hotel findHotelById(Long id);
|
||||
|
||||
/**
|
||||
* Create a new, transient hotel booking instance for the given user.
|
||||
* @param hotelId the hotelId
|
||||
* @param userName the user name
|
||||
* @return the new transient booking instance
|
||||
*/
|
||||
public Booking createBooking(Long hotelId, String userName);
|
||||
|
||||
/**
|
||||
* Cancel an existing booking.
|
||||
* @param id the booking id
|
||||
*/
|
||||
public void cancelBooking(Booking booking);
|
||||
|
||||
/**
|
||||
* Lookup a user based on their username
|
||||
* @param username the user's username
|
||||
* @return the user
|
||||
*/
|
||||
public User findUser(String username);
|
||||
}
|
||||
|
||||
@@ -40,8 +40,7 @@ public class JpaBookingService implements BookingService {
|
||||
@Transactional(readOnly = true)
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Hotel> findHotels(SearchCriteria criteria) {
|
||||
String pattern = !StringUtils.hasText(criteria.getSearchString()) ? "'%'" : "'%"
|
||||
+ criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
|
||||
String pattern = getSearchPattern(criteria);
|
||||
return em.createQuery(
|
||||
"select h from Hotel h where lower(h.name) like " + pattern + " or lower(h.city) like " + pattern
|
||||
+ " or lower(h.zip) like " + pattern + " or lower(h.address) like " + pattern).setMaxResults(
|
||||
@@ -54,9 +53,10 @@ public class JpaBookingService implements BookingService {
|
||||
}
|
||||
|
||||
@Transactional(readOnly = true)
|
||||
public User findUser(String username) {
|
||||
return (User) em.createQuery("select u from User u where u.username = :username").setParameter("username",
|
||||
username).getSingleResult();
|
||||
public Booking createBooking(Long hotelId, String username) {
|
||||
Hotel hotel = em.find(Hotel.class, hotelId);
|
||||
User user = findUser(username);
|
||||
return new Booking(hotel, user);
|
||||
}
|
||||
|
||||
// read-write transactional methods
|
||||
@@ -71,11 +71,16 @@ public class JpaBookingService implements BookingService {
|
||||
// helpers
|
||||
|
||||
private String getSearchPattern(SearchCriteria criteria) {
|
||||
if (criteria.getSearchString().length() > 0) {
|
||||
return "'%'" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
|
||||
if (StringUtils.hasText(criteria.getSearchString())) {
|
||||
return "'%" + criteria.getSearchString().toLowerCase().replace('*', '%') + "%'";
|
||||
} else {
|
||||
return "'%";
|
||||
return "'%'";
|
||||
}
|
||||
}
|
||||
|
||||
private User findUser(String username) {
|
||||
return (User) em.createQuery("select u from User u where u.username = :username").setParameter("username",
|
||||
username).getSingleResult();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,12 +7,10 @@
|
||||
|
||||
<persistence-context/>
|
||||
|
||||
<input name="id" value="flowScope.id"/>
|
||||
<input name="hotelId" value="flowScope.hotelId"/>
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.findHotelById(id)" result="flowScope.hotel" />
|
||||
<evaluate expression="hotel.createBooking(bookingService.findUser(currentUser.name))" result="flowScope.booking" />
|
||||
<evaluate expression="entityManager.persist(booking)" />
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails">
|
||||
@@ -23,7 +21,9 @@
|
||||
</view-state>
|
||||
|
||||
<view-state id="reviewBooking">
|
||||
<transition on="confirm" to="bookingConfirmed" />
|
||||
<transition on="confirm" to="bookingConfirmed">
|
||||
<evaluate expression="entityManager.persist(booking)" />
|
||||
</transition>
|
||||
<transition on="revise" to="enterBookingDetails" />
|
||||
<transition on="cancel" to="bookingCancelled" />
|
||||
</view-state>
|
||||
|
||||
@@ -15,28 +15,28 @@
|
||||
<fieldset>
|
||||
<div class="field">
|
||||
<div class="label">Name:</div>
|
||||
<div class="output">#{hotel.name}</div>
|
||||
<div class="output">#{booking.hotel.name}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Address:</div>
|
||||
<div class="output">#{hotel.address}</div>
|
||||
<div class="output">#{booking.hotel.address}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">City, State:</div>
|
||||
<div class="output">#{hotel.city}, #{hotel.state}</div>
|
||||
<div class="output">#{booking.hotel.city}, #{booking.hotel.state}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Zip:</div>
|
||||
<div class="output">#{hotel.zip}</div>
|
||||
<div class="output">#{booking.hotel.zip}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Country:</div>
|
||||
<div class="output">#{hotel.country}</div>
|
||||
<div class="output">#{booking.hotel.country}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Nightly rate:</div>
|
||||
<div class="output">
|
||||
<h:outputText value="#{hotel.price}">
|
||||
<h:outputText value="#{booking.hotel.price}">
|
||||
<f:convertNumber type="currency" currencySymbol="$"/>
|
||||
</h:outputText>
|
||||
</div>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</view-state>
|
||||
|
||||
<subflow-state id="bookHotel" subflow="booking">
|
||||
<input name="id" value="hotels.selectedRow.id" />
|
||||
<input name="hotelId" value="hotels.selectedRow.id" />
|
||||
<transition on="bookingConfirmed" to="finish" />
|
||||
<transition on="bookingCancelled" to="enterSearchCriteria" />
|
||||
</subflow-state>
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
package org.springframework.webflow.samples.booking;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.beans.PropertyEditorRegistrar;
|
||||
import org.springframework.beans.PropertyEditorRegistry;
|
||||
import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
|
||||
public class PropertyEditors implements PropertyEditorRegistrar {
|
||||
|
||||
public void registerCustomEditors(PropertyEditorRegistry registry) {
|
||||
registry.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat("yyyy-MM-dd"), true));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -8,27 +8,20 @@
|
||||
|
||||
<persistence-context/>
|
||||
|
||||
<input name="id" value="flowScope.id" />
|
||||
<input name="hotelId" value="flowScope.hotelId" />
|
||||
|
||||
<on-start>
|
||||
<evaluate expression="bookingService.findHotelById(flowScope.id)" result="flowScope.hotel" />
|
||||
<evaluate expression="hotel.createBooking(bookingService.findUser(currentUser.name))" result="flowScope.booking" />
|
||||
<evaluate expression="bookingService.createBooking(hotelId, currentUser.name)" result="flowScope.booking" />
|
||||
</on-start>
|
||||
|
||||
<view-state id="enterBookingDetails">
|
||||
<on-render>
|
||||
<evaluate expression="bookingActions.setupForm"/>
|
||||
</on-render>
|
||||
<transition on="proceed" to="reviewBooking">
|
||||
<evaluate expression="bookingActions.bindAndValidate" />
|
||||
<bind target="booking" />
|
||||
</transition>
|
||||
<transition on="cancel" to="cancel" />
|
||||
</view-state>
|
||||
|
||||
<view-state id="reviewBooking">
|
||||
<on-render>
|
||||
<evaluate expression="bookingActions.setupForm"/>
|
||||
</on-render>
|
||||
<transition on="confirm" to="bookingConfirmed">
|
||||
<evaluate expression="entityManager.persist(booking)" />
|
||||
</transition>
|
||||
|
||||
@@ -16,28 +16,28 @@
|
||||
<fieldset>
|
||||
<div class="field">
|
||||
<div class="label">Name:</div>
|
||||
<div class="output">${hotel.name}</div>
|
||||
<div class="output">${booking.hotel.name}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Address:</div>
|
||||
<div class="output">${hotel.address}</div>
|
||||
<div class="output">${booking.hotel.address}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">City, State:</div>
|
||||
<div class="output">${hotel.city}, ${hotel.state}</div>
|
||||
<div class="output">${booking.hotel.city}, ${booking.hotel.state}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Zip:</div>
|
||||
<div class="output">${hotel.zip}</div>
|
||||
<div class="output">${booking.hotel.zip}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Country:</div>
|
||||
<div class="output">${hotel.country}</div>
|
||||
<div class="output">${booking.hotel.country}</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="label">Nightly rate:</div>
|
||||
<div class="output">
|
||||
<spring:bind path="hotel.price">${status.value}</spring:bind>
|
||||
<spring:bind path="booking.hotel.price">${status.value}</spring:bind>
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
|
||||
@@ -10,37 +10,29 @@
|
||||
<on-render>
|
||||
<evaluate expression="bookingService.findBookings(currentUser.name)" result="requestScope.bookings" />
|
||||
</on-render>
|
||||
<transition on="findHotels" to="findHotels">
|
||||
<evaluate expression="mainActions.bindAndValidate" />
|
||||
<transition on="findHotels">
|
||||
<bind target="searchCriteria" />
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels" />
|
||||
</transition>
|
||||
<transition on="selectHotel" to="reviewHotel">
|
||||
<set name="requestScope.id" value="requestParameters.hotelId" type="long" />
|
||||
<evaluate expression="bookingService.findHotelById(id)" result="flowScope.hotel" />
|
||||
<evaluate expression="bookingService.findHotelById(requestParameters.hotelId)" result="flowScope.hotel" />
|
||||
</transition>
|
||||
<transition on="cancelBooking">
|
||||
<evaluate expression="bookingService.cancelBooking(requestParameters.bookingId)" />
|
||||
</transition>
|
||||
<transition on="cancelBooking" to="cancelBooking" />
|
||||
</view-state>
|
||||
|
||||
<action-state id="findHotels">
|
||||
<evaluate expression="bookingService.findHotels(searchCriteria)" result="flowScope.hotels" />
|
||||
<transition on="success" to="main" />
|
||||
</action-state>
|
||||
|
||||
<view-state id="reviewHotel">
|
||||
<transition on="book" to="bookHotel" />
|
||||
<transition on="cancel" to="main" />
|
||||
</view-state>
|
||||
|
||||
<subflow-state id="bookHotel" subflow="booking">
|
||||
<input name="id" value="flowScope.hotel.id" />
|
||||
<input name="hotelId" value="flowScope.hotel.id" />
|
||||
<transition on="bookingConfirmed" to="finish" />
|
||||
<transition on="cancel" to="main" />
|
||||
</subflow-state>
|
||||
|
||||
<action-state id="cancelBooking">
|
||||
<evaluate expression="bookingService.cancelBooking(requestParameters.bookingId)" />
|
||||
<transition on="success" to="main" />
|
||||
</action-state>
|
||||
|
||||
<end-state id="finish"/>
|
||||
|
||||
</flow>
|
||||
@@ -62,22 +62,6 @@
|
||||
<property name="suffix" value=".jsp" />
|
||||
</bean>
|
||||
|
||||
<!-- Handels form binding for the hotel search -->
|
||||
<bean id="mainActions" class="org.springframework.webflow.action.FormAction">
|
||||
<property name="formObjectClass" value="org.springframework.webflow.samples.booking.SearchCriteria" />
|
||||
</bean>
|
||||
|
||||
<!-- Handels form binding and validation for the hotel booking process -->
|
||||
<bean id="bookingActions" class="org.springframework.webflow.action.FormAction">
|
||||
<property name="formObjectClass" value="org.springframework.webflow.samples.booking.Booking" />
|
||||
<property name="propertyEditorRegistrar">
|
||||
<bean class="org.springframework.webflow.samples.booking.PropertyEditors" />
|
||||
</property>
|
||||
<property name="validator">
|
||||
<bean class="org.springframework.webflow.samples.booking.BookingValidator" />
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The central service of this application that can query hotels and bookings, as well as cancel bookings -->
|
||||
<bean id="bookingService" class="org.springframework.webflow.samples.booking.JpaBookingService" />
|
||||
|
||||
|
||||
@@ -2,8 +2,11 @@ package org.springframework.webflow.action;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.binding.convert.ConversionService;
|
||||
import org.springframework.binding.convert.support.RuntimeBindingConversionExecutor;
|
||||
import org.springframework.binding.expression.EvaluationException;
|
||||
import org.springframework.binding.expression.Expression;
|
||||
import org.springframework.binding.expression.ExpressionParser;
|
||||
import org.springframework.binding.expression.support.ParserContextImpl;
|
||||
@@ -17,6 +20,8 @@ import org.springframework.webflow.execution.RequestContext;
|
||||
|
||||
public class BindAction extends AbstractAction {
|
||||
|
||||
private static Log logger = LogFactory.getLog(BindAction.class);
|
||||
|
||||
private Expression target;
|
||||
|
||||
private ExpressionParser expressionParser;
|
||||
@@ -37,15 +42,26 @@ public class BindAction extends AbstractAction {
|
||||
}
|
||||
DefaultAttributeMapper mapper = new DefaultAttributeMapper();
|
||||
AttributeMap eventAttributes = context.getLastEvent().getAttributes();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Binding event '" + context.getLastEvent().getId() + "' attributes " + eventAttributes
|
||||
+ " to target " + target);
|
||||
}
|
||||
for (Iterator it = eventAttributes.asMap().keySet().iterator(); it.hasNext();) {
|
||||
String name = (String) it.next();
|
||||
Expression sourceAttribute = expressionParser.parseExpression(name, new ParserContextImpl()
|
||||
.eval(AttributeMap.class));
|
||||
Expression targetAttribute = expressionParser.parseExpression(name, new ParserContextImpl().eval(target
|
||||
.getClass()));
|
||||
Class targetType = targetAttribute.getValueType(target);
|
||||
mapper.addMapping(new Mapping(sourceAttribute, targetAttribute, new RuntimeBindingConversionExecutor(
|
||||
targetType, conversionService), false));
|
||||
Class targetType;
|
||||
try {
|
||||
targetType = targetAttribute.getValueType(target);
|
||||
} catch (EvaluationException e) {
|
||||
targetType = null;
|
||||
}
|
||||
if (targetType != null) {
|
||||
mapper.addMapping(new Mapping(sourceAttribute, targetAttribute, new RuntimeBindingConversionExecutor(
|
||||
targetType, conversionService), false));
|
||||
}
|
||||
}
|
||||
try {
|
||||
mapper.map(context.getLastEvent().getAttributes(), target, new MappingContextImpl(context
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.springframework.binding.mapping.Mapping;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.core.JdkVersion;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceLoader;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
@@ -54,6 +55,7 @@ import org.springframework.util.xml.DomUtils;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
import org.springframework.webflow.action.ActionResultExposer;
|
||||
import org.springframework.webflow.action.BindAction;
|
||||
import org.springframework.webflow.action.EvaluateAction;
|
||||
import org.springframework.webflow.action.ExternalRedirectAction;
|
||||
import org.springframework.webflow.action.FlowDefinitionRedirectAction;
|
||||
@@ -327,7 +329,9 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
}
|
||||
}
|
||||
flowContext.setResourceLoader(new FlowRelativeResourceLoader(resource));
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
|
||||
if (JdkVersion.isAtLeastJava15()) {
|
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(flowContext);
|
||||
}
|
||||
new XmlBeanDefinitionReader(flowContext).loadBeanDefinitions(resources);
|
||||
registerFlowBeans(flowContext.getDefaultListableBeanFactory());
|
||||
flowContext.refresh();
|
||||
@@ -667,7 +671,9 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
if (!(childNode instanceof Element)) {
|
||||
continue;
|
||||
}
|
||||
if (DomUtils.nodeNameEquals(childNode, "evaluate")) {
|
||||
if (DomUtils.nodeNameEquals(childNode, "bind")) {
|
||||
actions.add(parseBindAction((Element) childNode));
|
||||
} else if (DomUtils.nodeNameEquals(childNode, "evaluate")) {
|
||||
actions.add(parseEvaluateAction((Element) childNode));
|
||||
} else if (DomUtils.nodeNameEquals(childNode, "render")) {
|
||||
actions.add(parseRenderAction((Element) childNode));
|
||||
@@ -678,6 +684,13 @@ public class XmlFlowBuilder extends AbstractFlowBuilder implements ResourceHolde
|
||||
return (Action[]) actions.toArray(new Action[actions.size()]);
|
||||
}
|
||||
|
||||
private Action parseBindAction(Element element) {
|
||||
String targetString = element.getAttribute("target");
|
||||
ExpressionParser parser = getExpressionParser();
|
||||
Expression target = parser.parseExpression(targetString, new ParserContextImpl().eval(RequestContext.class));
|
||||
return new BindAction(target, parser, getConversionService());
|
||||
}
|
||||
|
||||
private Action parseEvaluateAction(Element element) {
|
||||
String expressionString = element.getAttribute("expression");
|
||||
Expression expression = getExpressionParser().parseExpression(expressionString,
|
||||
|
||||
@@ -39,10 +39,34 @@ public class BindActionTests extends TestCase {
|
||||
|
||||
BindBean bean = (BindBean) context.getFlowScope().get("bindTarget");
|
||||
assertEquals("foo", bean.getStringProperty());
|
||||
assertEquals(3, bean.getIntegerProperty());
|
||||
assertEquals(new Integer(3), bean.getIntegerProperty());
|
||||
}
|
||||
|
||||
public void testBindWithErrors() throws Exception {
|
||||
public void testBindNonexistantProperties() throws Exception {
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
context.getFlowScope().put("bindTarget", new BindBean());
|
||||
|
||||
Expression target = expressionParser.parseExpression("bindTarget", new ParserContextImpl()
|
||||
.eval(RequestContext.class));
|
||||
action = new BindAction(target, expressionParser, conversionService);
|
||||
|
||||
LocalAttributeMap eventData = new LocalAttributeMap();
|
||||
eventData.put("stringProperty", "foo");
|
||||
eventData.put("bogusProperty", "bar");
|
||||
eventData.put("integerProperty", "3");
|
||||
Event event = new Event(this, "submit", eventData);
|
||||
context.setLastEvent(event);
|
||||
|
||||
Event result = action.execute(context);
|
||||
assertEquals("success", result.getId());
|
||||
|
||||
BindBean bean = (BindBean) context.getFlowScope().get("bindTarget");
|
||||
assertEquals("foo", bean.getStringProperty());
|
||||
assertEquals(new Integer(3), bean.getIntegerProperty());
|
||||
assertEquals(0, context.getMessageContext().getMessages().length);
|
||||
}
|
||||
|
||||
public void testBindWithTypeConversionErrors() throws Exception {
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
context.getFlowScope().put("bindTarget", new BindBean());
|
||||
|
||||
@@ -61,7 +85,7 @@ public class BindActionTests extends TestCase {
|
||||
|
||||
BindBean bean = (BindBean) context.getFlowScope().get("bindTarget");
|
||||
assertEquals("foo", bean.getStringProperty());
|
||||
assertEquals(0, bean.getIntegerProperty());
|
||||
assertEquals(new Integer(3), bean.getIntegerProperty());
|
||||
assertEquals(1, context.getMessageContext().getMessages().length);
|
||||
assertEquals("integerProperty", context.getMessageContext().getMessages()[0].getSource());
|
||||
assertEquals(Severity.ERROR, context.getMessageContext().getMessages()[0].getSeverity());
|
||||
@@ -69,9 +93,33 @@ public class BindActionTests extends TestCase {
|
||||
.getText());
|
||||
}
|
||||
|
||||
public void testBindWithEmptyAttributes() throws Exception {
|
||||
MockRequestContext context = new MockRequestContext();
|
||||
context.getFlowScope().put("bindTarget", new BindBean());
|
||||
|
||||
Expression target = expressionParser.parseExpression("bindTarget", new ParserContextImpl()
|
||||
.eval(RequestContext.class));
|
||||
action = new BindAction(target, expressionParser, conversionService);
|
||||
|
||||
LocalAttributeMap eventData = new LocalAttributeMap();
|
||||
eventData.put("stringProperty", "");
|
||||
eventData.put("integerProperty", null);
|
||||
Event event = new Event(this, "submit", eventData);
|
||||
context.setLastEvent(event);
|
||||
|
||||
Event result = action.execute(context);
|
||||
System.out.println(context.getMessageContext());
|
||||
assertEquals("success", result.getId());
|
||||
|
||||
BindBean bean = (BindBean) context.getFlowScope().get("bindTarget");
|
||||
assertEquals("", bean.getStringProperty());
|
||||
assertEquals(null, bean.getIntegerProperty());
|
||||
assertEquals(0, context.getMessageContext().getMessages().length);
|
||||
}
|
||||
|
||||
public static class BindBean {
|
||||
private String stringProperty;
|
||||
private int integerProperty;
|
||||
private Integer integerProperty = new Integer(3);
|
||||
|
||||
public String getStringProperty() {
|
||||
return stringProperty;
|
||||
@@ -81,11 +129,11 @@ public class BindActionTests extends TestCase {
|
||||
this.stringProperty = stringProperty;
|
||||
}
|
||||
|
||||
public int getIntegerProperty() {
|
||||
public Integer getIntegerProperty() {
|
||||
return integerProperty;
|
||||
}
|
||||
|
||||
public void setIntegerProperty(int integerProperty) {
|
||||
public void setIntegerProperty(Integer integerProperty) {
|
||||
this.integerProperty = integerProperty;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user