You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@wicket.apache.org by "Sven Meier (JIRA)" <ji...@apache.org> on 2014/12/09 14:50:12 UTC

[jira] [Closed] (WICKET-5787) MessageSource in FormComponent does not reflect type of var, when custom converter is used

     [ https://issues.apache.org/jira/browse/WICKET-5787?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Sven Meier closed WICKET-5787.
------------------------------
    Resolution: Invalid
      Assignee: Sven Meier

You have to take the given type into account in getConverter:

@Override
public <C> IConverter<C> getConverter(Class<C> type)
{
  if (type == BigDecimal.class) {
    return (IConverter<C>) converter;
  }
  return super.getConverter(type);
} 

> MessageSource in FormComponent does not reflect type of var, when custom converter is used
> ------------------------------------------------------------------------------------------
>
>                 Key: WICKET-5787
>                 URL: https://issues.apache.org/jira/browse/WICKET-5787
>             Project: Wicket
>          Issue Type: Bug
>          Components: wicket
>    Affects Versions: 6.18.0
>            Reporter: Marek Pilecký
>            Assignee: Sven Meier
>            Priority: Minor
>
> /************************* Problem description *************************/
> When using custom validator together with custom converter, if validation fails, inside FormComponent.MessageSource.substitute() method custom converter is used for every variable given inside ValidationError isntance. If this variable is of another type than custom converter expects, exception is thrown. IE: java.lang.Integer cannot be cast to java.math.BigDecimal 
> /************************* Properties message *************************/
> targetValue.BigDecimalValidator.scaleExceeded='${label}' value '${input}' has more than '${scale}' decimal digits
> /************************* Our custom validator *************************/
> public class BigDecimalPrecisionValidator implements IValidator<BigDecimal> {
> 	private static final long serialVersionUID = 1L;
> 	private final int precision;
> 	private final int scale;
> 	public BigDecimalPrecisionValidator(int precision, int scale) {
> 		super();
> 		this.precision = precision;
> 		this.scale = scale;
> 	}
> 	@Override
> 	public void validate(IValidatable<BigDecimal> validatable) {
> 		
> 		if ( //some logic here ) {
> 			error(validatable, "scaleExceeded");
> 		}
> 	}
> 	private void error(IValidatable<BigDecimal> validatable, String key) {
> 		ValidationError error = new ValidationError(this);
> 		error.addKey(getClass().getSimpleName() + "." + key);
> 		error.setVariable("scale", scale)); // <- here starts trouble, scale is int
> 		error.setVariable("precision", precision);
> 		error.setVariable("value", validatable.getValue());
> 		validatable.error(error);
> 	}
> }
> /************************* Our custom BigDecimalField component *************************/
> public class BigDecimalField extends TextField<BigDecimal> {
> 	private static final long serialVersionUID = 1L;
> 	private BigDecimalConverter converter;
> 	public BigDecimalField(String id, IModel<BigDecimal> model, int scale) {
> 		super(id, model, BigDecimal.class);
> 		this.converter = new CustomBigDecimalConverter(scale);
> 	}
> 	@Override
> 	public <C> IConverter<C> getConverter(Class<C> type) {
> 		return (IConverter<C>) converter;
> 	}
> 	class CustomBigDecimalConverter extends BigDecimalConverter {
> 		private static final long serialVersionUID = 1L;
> 		private Integer scale;
> 		protected CustomBigDecimalConverter() {
> 			super();
> 		}
> 		protected CustomBigDecimalConverter(Integer scale) {
> 			super();
> 			this.scale = scale;
> 		}
> 		@Override
> 		public BigDecimal convertToObject(String value, Locale locale) {
> 			return super.convertToObject(value.replaceAll(",", "."), locale);
> 		}
> 		@Override
> 		public String convertToString(BigDecimal value, Locale locale) { // <- method expects BigDecimal, but int is given, exception is thrown here
> 			if (scale != null) {
> 				value.setScale(scale, RoundingMode.CEILING);
> 			}
> 			return value.toString();
> 		}
> 	}
> }
> /************************* Creation of component *************************/
> final BigDecimalField valueField = new BigDecimalField("value", (IModel<BigDecimal>)item.getDefaultModel(), 2);
> valueField.add(new BigDecimalPrecisionValidator(11, 1));
> /************************** Value given to component *************************/
> 8.88
> - precision is 1, so validation using my BigDecimalPrecisionValidator fails.
> /************************** Stack Trace *************************/
> org.apache.wicket.WicketRuntimeException: Exception 'java.lang.Integer cannot be cast to java.math.BigDecimal' occurred during validation com.example.project.name.wicket.validation.validator.BigDecimalPrecisionValidator on component 15:valuesForm:ncbsTable:dataRows:1:row:values:0:value
> 	at org.apache.wicket.markup.html.form.FormComponent.validateValidators(FormComponent.java:1535)
> 	at org.apache.wicket.markup.html.form.FormComponent.validate(FormComponent.java:1146)
> 	at org.apache.wicket.markup.html.form.Form$18.validate(Form.java:1926)
> 	at org.apache.wicket.markup.html.form.Form$ValidationVisitor.component(Form.java:176)
> 	at org.apache.wicket.markup.html.form.Form$ValidationVisitor.component(Form.java:160)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:274)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrderHelper(Visits.java:262)
> 	at org.apache.wicket.util.visit.Visits.visitPostOrder(Visits.java:245)
> 	at org.apache.wicket.markup.html.form.FormComponent.visitFormComponentsPostOrder(FormComponent.java:389)
> 	at org.apache.wicket.markup.html.form.Form.visitFormComponentsPostOrder(Form.java:1128)
> 	at org.apache.wicket.markup.html.form.Form.validateComponents(Form.java:1918)
> 	at org.apache.wicket.markup.html.form.Form.validate(Form.java:1860)
> 	at org.apache.wicket.markup.html.form.Form.process(Form.java:921)
> 	at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:784)
> 	at org.apache.wicket.ajax.form.AjaxFormSubmitBehavior.onEvent(AjaxFormSubmitBehavior.java:159)
> 	at org.apache.wicket.ajax.AjaxEventBehavior.respond(AjaxEventBehavior.java:124)
> 	at org.apache.wicket.ajax.AbstractDefaultAjaxBehavior.onRequest(AbstractDefaultAjaxBehavior.java:633)
> 	at sun.reflect.GeneratedMethodAccessor159.invoke(Unknown Source)
> 	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
> 	at java.lang.reflect.Method.invoke(Method.java:597)
> 	at org.apache.wicket.RequestListenerInterface.internalInvoke(RequestListenerInterface.java:258)
> 	at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:241)
> 	at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.invokeListener(ListenerInterfaceRequestHandler.java:250)
> 	at org.apache.wicket.core.request.handler.ListenerInterfaceRequestHandler.respond(ListenerInterfaceRequestHandler.java:236)
> 	at org.apache.wicket.request.cycle.RequestCycle$HandlerExecutor.respond(RequestCycle.java:862)
> 	at org.apache.wicket.request.RequestHandlerStack.execute(RequestHandlerStack.java:64)
> 	at org.apache.wicket.request.cycle.RequestCycle.execute(RequestCycle.java:261)
> 	at org.apache.wicket.request.cycle.RequestCycle.processRequest(RequestCycle.java:218)
> 	at org.apache.wicket.request.cycle.RequestCycle.processRequestAndDetach(RequestCycle.java:289)
> 	at org.apache.wicket.protocol.http.WicketFilter.processRequestCycle(WicketFilter.java:259)
> 	at org.apache.wicket.protocol.http.WicketFilter.processRequest(WicketFilter.java:201)
> 	at org.apache.wicket.protocol.http.WicketServlet.doPost(WicketServlet.java:159)
> 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:646)
> 	at javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
> 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:303)
> 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
> 	at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:150)
> 	at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
> 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
> 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
> 	at com.example.project.name.wicket.RelativeURLFilter.doFilter(RelativeURLFilter.java:48)
> 	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:241)
> 	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:208)
> 	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:220)
> 	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:122)
> 	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:610)
> 	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
> 	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:103)
> 	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:950)
> 	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:116)
> 	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
> 	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1070)
> 	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:611)
> 	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:316)
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
> 	at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
> 	at java.lang.Thread.run(Thread.java:662)
> Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.math.BigDecimal
> 	at com.example.project.name.wicket.component.BigDecimalField$CustomBigDecimalConverter.convertToString(BigDecimalField.java:1)
> 	at org.apache.wicket.util.convert.converter.AbstractNumberConverter.convertToString(AbstractNumberConverter.java:31)
> 	at org.apache.wicket.markup.html.form.FormComponent$MessageSource$1.getValue(FormComponent.java:238)
> 	at org.apache.wicket.util.string.interpolator.VariableInterpolator.toString(VariableInterpolator.java:148)
> 	at org.apache.wicket.markup.html.form.FormComponent$MessageSource.substitute(FormComponent.java:208)
> 	at org.apache.wicket.markup.html.form.FormComponent$MessageSource.getMessage(FormComponent.java:171)
> 	at org.apache.wicket.validation.ValidationError.getErrorMessage(ValidationError.java:248)
> 	at org.apache.wicket.markup.html.form.FormComponent.error(FormComponent.java:664)
> 	at org.apache.wicket.markup.html.form.FormComponent$ValidatableAdapter.error(FormComponent.java:325)
> 	at com.example.project.name.wicket.validation.validator.BigDecimalPrecisionValidator.error(BigDecimalPrecisionValidator.java:58)
> 	at com.example.project.name.wicket.validation.validator.BigDecimalPrecisionValidator.validate(BigDecimalPrecisionValidator.java:45)
> 	at org.apache.wicket.markup.html.form.FormComponent.validateValidators(FormComponent.java:1524)
> 	... 63 more
> /************************** Workaround *************************/
> Pass variable into ValidationError of same type as custom Converter is typed.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)