Uploaded image for project: 'Wicket'
  1. Wicket
  2. WICKET-1483

Unusual ClassCastException (SimpleAttributeModifier to IBehaviorListener) processing onError.

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Resolved
    • Minor
    • Resolution: Fixed
    • 1.3.0-final, 1.3.1, 1.3.2
    • 1.3.6, 1.4-RC2
    • wicket
    • None
    • Microsoft Windows XP [Version 5.1.2600] (Server & Client)

    Description

      Build the application from the four class files and one html file below. Run class Start as an application. Go to your browser, to this URL:

      http://localhost:4280/behaviorbug/

      Type some text into the text field. After six characters, it will throw a ClassCastException.

      Source:

      package com.bugs.behaviorBug;

      import org.apache.wicket.ajax.AjaxRequestTarget;
      import org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
      import org.apache.wicket.behavior.SimpleAttributeModifier;
      import org.apache.wicket.markup.html.form.TextField;
      import org.apache.wicket.model.IModel;

      public class BehaviorBug extends TextField {

      public BehaviorBug(String id, IModel model)

      { super( id, model ); init(); }

      private int kc = 0;
      private int cc = 0;
      private final SimpleAttributeModifier blackBorder = new SimpleAttributeModifier(
      "border-color", "black" );
      private final SimpleAttributeModifier redBorder = new SimpleAttributeModifier(
      "border-color", "red" );
      private SimpleAttributeModifier currentBorder = null;

      private void init() {
      setBorder( this.blackBorder );
      AjaxFormComponentUpdatingBehavior changeWarningBehavior = new AjaxFormComponentUpdatingBehavior(
      "onchange" ) {

      @Override
      protected void onUpdate(AjaxRequestTarget target)

      { System.err.println( "WarningTextField onUpdate onChange " + BehaviorBug.this.cc++ ); reColor(); }

      };

      // I'm trying to do something tricky here. I want it to validate after every
      // keystroke, so the user can get instant feedback on when the data is good.
      AjaxFormComponentUpdatingBehavior keyUpWarningBehavior = new AjaxFormComponentUpdatingBehavior(
      "onkeyup" ) {

      @Override
      protected void onUpdate(AjaxRequestTarget target)

      { System.err.println( "WarningTextField onUpdate onKeyUp " + BehaviorBug.this.kc++ ); reColor(); // Thread.dumpStack(); }

      // The implementation of AjaxFormComponentUpdatingBehavior only calls
      // onUpdate
      // when the field is valid. Since it won't update when the field is
      // invalid, I
      // can't get my instant feedback unless I call onUpdate() when there's an
      // error.
      // Since I can't override onEvent() (It's final), I override onError to
      // force
      // an update even when the field is invalid. This should be safe, since
      // onError()
      // is only called on invalid data with a null exception, in which case it
      // does
      // nothing.
      // This, however, seems to be what causes the bug. I have no idea why this
      // would cause the bug.
      @Override
      protected void onError(AjaxRequestTarget target, RuntimeException e)

      { // Called on validation error with a null e. super.onError( target, e ); // Throws e, if it's not null. Does nothing // otherwise. onUpdate( target ); }

      };
      add( changeWarningBehavior );
      add( keyUpWarningBehavior );
      }

      private void reColor() {
      if ( isValid() )

      { setBorder( BehaviorBug.this.blackBorder ); }

      else

      { setBorder( BehaviorBug.this.redBorder ); }

      }

      private void setBorder(SimpleAttributeModifier border) {
      if ( this.currentBorder != null && this.currentBorder != border )

      { remove( this.currentBorder ); }

      this.currentBorder = border;
      add( this.currentBorder );
      }
      }

      package com.bugs.behaviorBug;

      import org.apache.wicket.Application;
      import org.apache.wicket.Page;
      import org.apache.wicket.Request;
      import org.apache.wicket.Response;
      import org.apache.wicket.Session;
      import org.apache.wicket.protocol.http.WebApplication;
      import org.apache.wicket.protocol.http.WebSession;

      /**

      • @author Miguel Muñoz
      • @version $Id$
      • */
        public class BehaviorBugApplication extends WebApplication {

      /**

      • Constructor
        */
        public BehaviorBugApplication() { // empty }

        @Override
        protected void init() { // empty }

      @Override
      public Class<? extends Page> getHomePage()

      { return Index.class; }

      /*

      • (non-Javadoc)
      • @see org.apache.wicket.protocol.http.WebApplication#newSession(org.apache.wicket.Request,
      • org.apache.wicket.Response)
        */
        @Override
        public Session newSession(Request request, Response response) { return new BugSession( this, request ); }

      public class BugSession extends WebSession {
      public BugSession(Application application, Request request)

      { super(request); setApplication( application ); }

      }
      }

      package com.bugs.behaviorBug;

      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;
      import org.apache.wicket.validation.IValidator;
      import org.apache.wicket.validation.validator.StringValidator;

      /**

      • @author Miguel Muñoz
      • @version $Id$
      • */
        public class Index extends WebPage {

      /**

      • */
        public Index()

        { Form form = new Form("form"); TextField textField = new BehaviorBug("testfield", new Model()); IValidator lengthValidator = new StringValidator.MaximumLengthValidator(4); textField.add( lengthValidator ); form.add( textField ); add(form); }

      }

      package com.bugs.behaviorBug;

      import org.mortbay.jetty.Connector;
      import org.mortbay.jetty.Server;
      import org.mortbay.jetty.nio.SelectChannelConnector;
      import org.mortbay.jetty.webapp.WebAppContext;

      /**

      • @author Miguel Muñoz
      • @version $Id$
      • */
        public class Start {
        private static final int defaultPort = 4280;
        /**

      • @param args
        */
        public static void main(String[] args) {
        int port = defaultPort;
        if (args.length != 0)
        Unknown macro: { try { port = Integer.valueOf( args[0] ); } catch ( NumberFormatException e ) { System.err.println("Unable to parse port parameter \"" + args[0] + "\" as an integer."); System.err.println("Using default value of x " + defaultPort); } }

        Server server = new Server();
        SelectChannelConnector connector = new SelectChannelConnector();
        connector.setPort( port );
        server.setConnectors( new Connector[]

        { connector }

        );

      WebAppContext web = new WebAppContext();
      // web.setContextPath( "/workspace/WicketTutorial" );
      web.setContextPath( "/behaviorbug" );
      System.out.println( "CP: " + web.getContextPath() );
      web.setWar( "src/main/webapp" + port );
      server.addHandler( web );

      try

      { server.start(); // Who was the bozo who declared this to throw Exception? server.join(); }

      catch ( Exception e )

      { e.printStackTrace(); System.exit( 1 ); }

      }
      }

      <html>
      <head>
      <title>Behavior Bug</title>
      <link href="style.css" rel="stylesheet" />
      </head>
      <body>
      <div id="container">
      <div id="header">Behavior Bug</div>
      <div id="content">
      Type some text into the field below. After six characters, you'll get a stack trace.
      <form wicket:id="form">
      <input type="text" wicket:id="testfield" name="txt" width="35" size="25" /><p>
      submit: <input type="submit" value="That's all, Folks!"/></p>
      </form>
      End of form.
      </div>
      </div>
      Test of Build Process.
      </body>
      </html>

      Attachments

        1. wicket.behavior.patch
          8 kB
          Igor Vaynberg

        Issue Links

          Activity

            People

              ivaynberg Igor Vaynberg
              mmunoz Miguel Munoz
              Votes:
              0 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:

                Time Tracking

                  Estimated:
                  Original Estimate - 2h
                  2h
                  Remaining:
                  Remaining Estimate - 2h
                  2h
                  Logged:
                  Time Spent - Not Specified
                  Not Specified