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

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

Marek Pilecký created WICKET-5787:
-------------------------------------

             Summary: 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ý
            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)