I am learning Wicket by "Enjoying Web Development with Wicket" book.It is written for Wicket 1.4.7
And in an example:
int weight = ((Integer) weightModel.getObject()).intValue();
is used.
When I click Submit button it throws Unexpected RuntimeException first lines:
WicketMessage: Method onFormSubmitted of interface org.apache.wicket.markup.html.form.IFormSubmitListener targeted at component [MarkupContainer [Component id = form]] threw an exception
Root cause:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer*
Probably weightModel.getObject() couldn't be converted to String.
The full exception message is at the bottom.
But after changed the code to:
int weight=Integer.parseInt( (String) weightModel.getObject());
It works fine. It is supposed to work fine. What is the reason for throwing the exception?
The full code:
GetRequest.java
package myapp.postage;
import java.util.HashMap;
import java.util.Map;
import org.apache.wicket.markup.html.WebPage;
import org.apache.wicket.markup.html.form.Form;
import org.apache.wicket.markup.html.form.TextField;
import org.apache.wicket.model.Model;
@SuppressWarnings("unchecked")
public class GetRequest extends WebPage {
private Model weightModel=new Model();
private Model patronCodeModel=new Model();
private Map patronCodeToDiscount;
public GetRequest(){
patronCodeToDiscount=new HashMap();
patronCodeToDiscount.put("p1", new Integer(90));
patronCodeToDiscount.put("p2", new Integer(95));
Form form=new Form("form"){
@Override
protected void onSubmit(){
int weight = ((Integer) weightModel.getObject()).intValue();
Integer discount=(Integer)patronCodeToDiscount.get(patronCodeModel.getObject());
int postagePerKg=10;
int postage=weight*postagePerKg;
if(discount!=null){
postage=postage*discount.intValue()/100;
}
ShowPostage showPostage=new ShowPostage(postage);
setResponsePage(showPostage);
}
};
TextField weight=new TextField("weight",weightModel);
form.add(weight);
TextField patronCode=new TextField("patronCode",patronCodeModel);
form.add(patronCode);
add(form);
}
}
The html file GetRequest.html:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<form wicket:id="form">
<table>
<tr>
<td>Weight</td>
<td><input type="text" wicket:id="weight"/></td>
</tr>
<tr>
<td>Patron code:</td>
<td><input type="text" wicket:id="patronCode"/></td>
</tr>
<tr>
<td></td>
<td><input type="submit"/></td>
</tr>
</table>
</form>
</html>
Exception message: WicketMessage: Method onFormSubmitted of interface org.apache.wicket.markup.html.form.IFormSubmitListener targeted at component [MarkupContainer [Component id = form]] threw an exception
Root cause:
java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer
at myapp.postage.GetRequest$1.onSubmit(GetRequest.java:26)
at org.apache.wicket.markup.html.form.Form.delegateSubmit(Form.java:1538)
at org.apache.wicket.markup.html.form.Form.process(Form.java:934)
at org.apache.wicket.markup.html.form.Form.onFormSubmitted(Form.java:896)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:182)
at org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget.processEvents(ListenerInterfaceRequestTarget.java:73)
at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1250)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
at org.apache.wicket.protocol.http.WicketFilter.doFilter(WicketFilter.java:312)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at com.springsource.insight.collection.tcserver.request.HttpRequestOperationCollectionValve.invoke(HttpRequestOperationCollectionValve.java:60)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:849)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:583)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:379)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
at java.lang.Thread.run(Thread.java:619)
Complete stack:
org.apache.wicket.WicketRuntimeException: Method onFormSubmitted of interface org.apache.wicket.markup.html.form.IFormSubmitListener targeted at component [MarkupContainer [Component id = form]] threw an exception
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:193)
at org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget.processEvents(ListenerInterfaceRequestTarget.java:73)
at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1250)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.apache.wicket.RequestListenerInterface.invoke(RequestListenerInterface.java:182)
at org.apache.wicket.request.target.component.listener.ListenerInterfaceRequestTarget.processEvents(ListenerInterfaceRequestTarget.java:73)
at org.apache.wicket.request.AbstractRequestCycleProcessor.processEvents(AbstractRequestCycleProcessor.java:92)
at org.apache.wicket.RequestCycle.processEventsAndRespond(RequestCycle.java:1250)
at org.apache.wicket.RequestCycle.step(RequestCycle.java:1329)
at org.apache.wicket.RequestCycle.steps(RequestCycle.java:1428)
at org.apache.wicket.RequestCycle.request(RequestCycle.java:545)
at org.apache.wicket.protocol.http.WicketFilter.doGet(WicketFilter.java:479)
If you are Using Wicket 1.4 and above, you should use generics and use them to tell wicket what type you expect. Wicket will do the conversion for you then.
I would suggest the following changes (for the weight, the other field is left as an exercise ;) ):
Add a field to you page that will hold the input of the user:
private Integer weight;
Add getter and setter for this field:
public Integer getWeight() {return weight;}
public void SetWeight(Integer weight) {this.weight = weight;}
Then, replace the code to add the Textfield for weight with:
form.add(new TextField<Integer>("weight"
, new PropertyModel<Integer>(this, "weight"));
With this, Wicket will convert the userinput into an Integer and store it into the field weight. The PropertyModel uses the Page itself to access the field.
Hope that helps.
Hint: in case the user enters something that can not be converted, Wicket will add an error to the Textfield. You should add an Feedbackpanel to your page to see this.
Enjoy