Tapestry
  1. Tapestry
  2. TAPESTRY-1511

VerifyError when using inner classes inside components

    Details

    • Type: Bug Bug
    • Status: Closed
    • Priority: Critical Critical
    • Resolution: Fixed
    • Affects Version/s: 5.0
    • Fix Version/s: 5.0.5
    • Component/s: tapestry-core
    • Labels:
      None

      Description

      I'm thinking this is a bug inside Javassist, something about how it deals with synthetic accessors (used with inner classes). It doesn't happen all the time.

      When it does occur, I create a package private accessor method, and make use of that instead of a direct field access. The compiler generates different code that doesn't trigger this bug.

      java.lang.VerifyError
      (class: org/apache/tapestry/corelib/components/Select, method: access$1 signature: (Lorg/apache/tapestry/corelib/components/Select;)Ljava/lang/Object Unable to pop operand off an empty stack

      Stack trace

      • java.lang.Class.getDeclaredConstructors0(Native Method)
      • java.lang.Class.privateGetDeclaredConstructors(Class.java:2328)
      • java.lang.Class.getConstructors(Class.java:1446)
      • org.apache.tapestry.internal.services.ReflectiveInstantiator.findConstructor(ReflectiveInstantiator.java:65)
      • org.apache.tapestry.internal.services.ReflectiveInstantiator.<init>(ReflectiveInstantiator.java:53)
      • org.apache.tapestry.internal.services.InternalClassTransformationImpl.createInstantiator(InternalClassTransformationImpl.java:1227)
      • org.apache.tapestry.internal.services.ComponentClassTransformerImpl.createInstantiator(ComponentClassTransformerImpl.java:151)
      • org.apache.tapestry.internal.services.ComponentInstantiatorSourceImpl.findInstantiator(ComponentInstantiatorSourceImpl.java:242)
      • org.apache.tapestry.internal.services.PageElementFactoryImpl.newComponentElement(PageElementFactoryImpl.java:269)
      • org.apache.tapestry.internal.services.PageLoaderProcessor.startComponent(PageLoaderProcessor.java:624)
      • org.apache.tapestry.internal.services.PageLoaderProcessor.loadTemplateForComponent(PageLoaderProcessor.java:496)

      $ javap -c -classpath bin -verbose -private org.apache.tapestry.corelib.components.Select
      Compiled from "Select.java"
      public final class org.apache.tapestry.corelib.components.Select extends org.apache.tapestry.corelib.base.AbstractField
      SourceFile: "Select.java"
      InnerClass:
      #221= #195 of #1; //Renderer=class org/apache/tapestry/corelib/components/Select$Renderer of class org/apache/tapestry/corelib/components/Select
      #39; //class org/apache/tapestry/corelib/components/Select$1
      minor version: 0
      major version: 49
      Constant pool:
      const #1 = class #2; // org/apache/tapestry/corelib/components/Select
      const #2 = Asciz org/apache/tapestry/corelib/components/Select;
      const #3 = class #4; // org/apache/tapestry/corelib/base/AbstractField
      const #4 = Asciz org/apache/tapestry/corelib/base/AbstractField;
      const #5 = Asciz _encoder;
      const #6 = Asciz Lorg/apache/tapestry/ValueEncoder;;
      const #7 = Asciz RuntimeVisibleAnnotations;
      const #8 = Asciz Lorg/apache/tapestry/annotations/Parameter;;
      const #9 = Asciz _fieldValidatorDefaultSource;
      const #10 = Asciz Lorg/apache/tapestry/services/FieldValidatorDefaultSource;;
      const #11 = Asciz Lorg/apache/tapestry/annotations/Inject;;
      const #12 = Asciz _locale;
      const #13 = Asciz Ljava/util/Locale;;
      const #14 = Asciz _model;
      const #15 = Asciz Lorg/apache/tapestry/SelectModel;;
      const #16 = Asciz required;
      const #17 = int 1;
      const #18 = Asciz _request;
      const #19 = Asciz Lorg/apache/tapestry/services/Request;;
      const #20 = Asciz _resources;
      const #21 = Asciz Lorg/apache/tapestry/ComponentResources;;
      const #22 = Asciz _tracker;
      const #23 = Asciz Lorg/apache/tapestry/ValidationTracker;;
      const #24 = Asciz Lorg/apache/tapestry/annotations/Environmental;;
      const #25 = Asciz _validate;
      const #26 = Asciz Lorg/apache/tapestry/FieldValidator;;
      const #27 = Asciz Signature;
      const #28 = Asciz Lorg/apache/tapestry/FieldValidator<Ljava/lang/Object;>;;
      const #29 = Asciz defaultPrefix;
      const #30 = Asciz validate;
      const #31 = Asciz _value;
      const #32 = Asciz Ljava/lang/Object;;
      const #33 = Asciz principal;
      const #34 = Asciz <init>;
      const #35 = Asciz ()V;
      const #36 = Asciz Code;
      const #37 = Method #3.#38; // org/apache/tapestry/corelib/base/AbstractField."<init>")V
      const #38 = NameAndType #34:#35;// "<init>")V
      const #39 = class #40; // org/apache/tapestry/corelib/components/Select$1
      const #40 = Asciz org/apache/tapestry/corelib/components/Select$1;
      const #41 = Method #39.#42; // org/apache/tapestry/corelib/components/Select$1."<init>":(Lorg/apache/tapestry/corelib/components/Select;)V
      const #42 = NameAndType #34:#43;// "<init>":(Lorg/apache/tapestry/corelib/components/Select;)V
      const #43 = Asciz (Lorg/apache/tapestry/corelib/components/Select;)V;
      const #44 = Field #1.#45; // org/apache/tapestry/corelib/components/Select._encoder:Lorg/apache/tapestry/ValueEncoder;
      const #45 = NameAndType #5:#6;// _encoder:Lorg/apache/tapestry/ValueEncoder;
      const #46 = Field #1.#47; // org/apache/tapestry/corelib/components/Select.NOOP_VALIDATOR:Lorg/apache/tapestry/FieldValidator;
      const #47 = NameAndType #48:#26;// NOOP_VALIDATOR:Lorg/apache/tapestry/FieldValidator;
      const #48 = Asciz NOOP_VALIDATOR;
      const #49 = Field #1.#50; // org/apache/tapestry/corelib/components/Select._validate:Lorg/apache/tapestry/FieldValidator;
      const #50 = NameAndType #25:#26;// _validate:Lorg/apache/tapestry/FieldValidator;
      const #51 = Asciz LineNumberTable;
      const #52 = Asciz LocalVariableTable;
      const #53 = Asciz this;
      const #54 = Asciz Lorg/apache/tapestry/corelib/components/Select;;
      const #55 = Asciz processSubmission;
      const #56 = Asciz (Lorg/apache/tapestry/services/FormSupport;Ljava/lang/String;)V;
      const #57 = Field #1.#58; // org/apache/tapestry/corelib/components/Select._request:Lorg/apache/tapestry/services/Request;
      const #58 = NameAndType #18:#19;// _request:Lorg/apache/tapestry/services/Request;
      const #59 = InterfaceMethod #60.#62; // org/apache/tapestry/services/Request.getParameter:(Ljava/lang/String;)Ljava/lang/String;
      const #60 = class #61; // org/apache/tapestry/services/Request
      const #61 = Asciz org/apache/tapestry/services/Request;
      const #62 = NameAndType #63:#64;// getParameter:(Ljava/lang/String;)Ljava/lang/String;
      const #63 = Asciz getParameter;
      const #64 = Asciz (Ljava/lang/String;)Ljava/lang/String;;
      const #65 = InterfaceMethod #66.#68; // org/apache/tapestry/ValueEncoder.toValue:(Ljava/lang/String;)Ljava/lang/Object;
      const #66 = class #67; // org/apache/tapestry/ValueEncoder
      const #67 = Asciz org/apache/tapestry/ValueEncoder;
      const #68 = NameAndType #69:#70;// toValue:(Ljava/lang/String;)Ljava/lang/Object;
      const #69 = Asciz toValue;
      const #70 = Asciz (Ljava/lang/String;)Ljava/lang/Object;;
      const #71 = InterfaceMethod #72.#74; // org/apache/tapestry/FieldValidator.validate:(Ljava/lang/Object;)V
      const #72 = class #73; // org/apache/tapestry/FieldValidator
      const #73 = Asciz org/apache/tapestry/FieldValidator;
      const #74 = NameAndType #30:#75;// validate:(Ljava/lang/Object;)V
      const #75 = Asciz (Ljava/lang/Object;)V;
      const #76 = Field #1.#77; // org/apache/tapestry/corelib/components/Select._value:Ljava/lang/Object;
      const #77 = NameAndType #31:#32;// _value:Ljava/lang/Object;
      const #78 = Field #1.#79; // org/apache/tapestry/corelib/components/Select._tracker:Lorg/apache/tapestry/ValidationTracker;
      const #79 = NameAndType #22:#23;// _tracker:Lorg/apache/tapestry/ValidationTracker;
      const #80 = Method #81.#83; // org/apache/tapestry/ValidationException.getMessage)Ljava/lang/String;
      const #81 = class #82; // org/apache/tapestry/ValidationException
      const #82 = Asciz org/apache/tapestry/ValidationException;
      const #83 = NameAndType #84:#85;// getMessage)Ljava/lang/String;
      const #84 = Asciz getMessage;
      const #85 = Asciz ()Ljava/lang/String;;
      const #86 = InterfaceMethod #87.#89; // org/apache/tapestry/ValidationTracker.recordError:(Lorg/apache/tapestry/Field;Ljava/lang/String;)V
      const #87 = class #88; // org/apache/tapestry/ValidationTracker
      const #88 = Asciz org/apache/tapestry/ValidationTracker;
      const #89 = NameAndType #90:#91;// recordError:(Lorg/apache/tapestry/Field;Ljava/lang/String;)V
      const #90 = Asciz recordError;
      const #91 = Asciz (Lorg/apache/tapestry/Field;Ljava/lang/String;)V;
      const #92 = Asciz formSupport;
      const #93 = Asciz Lorg/apache/tapestry/services/FormSupport;;
      const #94 = Asciz elementName;
      const #95 = Asciz Ljava/lang/String;;
      const #96 = Asciz primaryKey;
      const #97 = Asciz selectedValue;
      const #98 = Asciz ex;
      const #99 = Asciz Lorg/apache/tapestry/ValidationException;;
      const #100 = Asciz afterRender;
      const #101 = Asciz (Lorg/apache/tapestry/MarkupWriter;)V;
      const #102 = InterfaceMethod #103.#105; // org/apache/tapestry/MarkupWriter.end)Lorg/apache/tapestry/dom/Element;
      const #103 = class #104; // org/apache/tapestry/MarkupWriter
      const #104 = Asciz org/apache/tapestry/MarkupWriter;
      const #105 = NameAndType #106:#107;// end)Lorg/apache/tapestry/dom/Element;
      const #106 = Asciz end;
      const #107 = Asciz ()Lorg/apache/tapestry/dom/Element;;
      const #108 = Asciz writer;
      const #109 = Asciz Lorg/apache/tapestry/MarkupWriter;;
      const #110 = Asciz beginRender;
      const #111 = String #112; // select
      const #112 = Asciz select;
      const #113 = class #114; // java/lang/Object
      const #114 = Asciz java/lang/Object;
      const #115 = String #116; // name
      const #116 = Asciz name;
      const #117 = Method #1.#118; // org/apache/tapestry/corelib/components/Select.getElementName)Ljava/lang/String;
      const #118 = NameAndType #119:#85;// getElementName)Ljava/lang/String;
      const #119 = Asciz getElementName;
      const #120 = String #121; // id
      const #121 = Asciz id;
      const #122 = Method #1.#123; // org/apache/tapestry/corelib/components/Select.getClientId)Ljava/lang/String;
      const #123 = NameAndType #124:#85;// getClientId)Ljava/lang/String;
      const #124 = Asciz getClientId;
      const #125 = InterfaceMethod #103.#126; // org/apache/tapestry/MarkupWriter.element:(Ljava/lang/String;[Ljava/lang/Object;)Lorg/apache/tapestry/dom/Element;
      const #126 = NameAndType #127:#128;// element:(Ljava/lang/String;[Ljava/lang/Object;)Lorg/apache/tapestry/dom/Element;
      const #127 = Asciz element;
      const #128 = Asciz (Ljava/lang/String;[Ljava/lang/Object;)Lorg/apache/tapestry/dom/Element;;
      const #129 = Asciz defaultEncoder;
      const #130 = Asciz ()Lorg/apache/tapestry/ValueEncoder;;
      const #131 = Field #1.#132; // org/apache/tapestry/corelib/components/Select._resources:Lorg/apache/tapestry/ComponentResources;
      const #132 = NameAndType #20:#21;// _resources:Lorg/apache/tapestry/ComponentResources;
      const #133 = String #134; // value
      const #134 = Asciz value;
      const #135 = InterfaceMethod #136.#138; // org/apache/tapestry/ComponentResources.getBoundType:(Ljava/lang/String;)Ljava/lang/Class;
      const #136 = class #137; // org/apache/tapestry/ComponentResources
      const #137 = Asciz org/apache/tapestry/ComponentResources;
      const #138 = NameAndType #139:#140;// getBoundType:(Ljava/lang/String;)Ljava/lang/Class;
      const #139 = Asciz getBoundType;
      const #140 = Asciz (Ljava/lang/String;)Ljava/lang/Class;;
      const #141 = class #142; // java/lang/Enum
      const #142 = Asciz java/lang/Enum;
      const #143 = Method #144.#146; // java/lang/Class.isAssignableFrom:(Ljava/lang/Class;)Z
      const #144 = class #145; // java/lang/Class
      const #145 = Asciz java/lang/Class;
      const #146 = NameAndType #147:#148;// isAssignableFrom:(Ljava/lang/Class;)Z
      const #147 = Asciz isAssignableFrom;
      const #148 = Asciz (Ljava/lang/Class;)Z;
      const #149 = class #150; // org/apache/tapestry/util/EnumValueEncoder
      const #150 = Asciz org/apache/tapestry/util/EnumValueEncoder;
      const #151 = Method #149.#152; // org/apache/tapestry/util/EnumValueEncoder."<init>":(Ljava/lang/Class;)V
      const #152 = NameAndType #34:#153;// "<init>":(Ljava/lang/Class;)V
      const #153 = Asciz (Ljava/lang/Class;)V;
      const #154 = Asciz valueType;
      const #155 = Asciz Ljava/lang/Class;;
      const #156 = Asciz defaultModel;
      const #157 = Asciz ()Lorg/apache/tapestry/SelectModel;;
      const #158 = class #159; // org/apache/tapestry/util/EnumSelectModel
      const #159 = Asciz org/apache/tapestry/util/EnumSelectModel;
      const #160 = InterfaceMethod #136.#161; // org/apache/tapestry/ComponentResources.getContainerMessages)Lorg/apache/tapestry/ioc/Messages;
      const #161 = NameAndType #162:#163;// getContainerMessages)Lorg/apache/tapestry/ioc/Messages;
      const #162 = Asciz getContainerMessages;
      const #163 = Asciz ()Lorg/apache/tapestry/ioc/Messages;;
      const #164 = Method #158.#165; // org/apache/tapestry/util/EnumSelectModel."<init>":(Ljava/lang/Class;Lorg/apache/tapestry/ioc/Messages;)V
      const #165 = NameAndType #34:#166;// "<init>":(Ljava/lang/Class;Lorg/apache/tapestry/ioc/Messages;)V
      const #166 = Asciz (Ljava/lang/Class;Lorg/apache/tapestry/ioc/Messages;)V;
      const #167 = Asciz defaultValidate;
      const #168 = Asciz ()Lorg/apache/tapestry/FieldValidator;;
      const #169 = Field #1.#170; // org/apache/tapestry/corelib/components/Select._fieldValidatorDefaultSource:Lorg/apache/tapestry/services/FieldValidatorDefaultSource;
      const #170 = NameAndType #9:#10;// _fieldValidatorDefaultSource:Lorg/apache/tapestry/services/FieldValidatorDefaultSource;
      const #171 = InterfaceMethod #136.#172; // org/apache/tapestry/ComponentResources.getId)Ljava/lang/String;
      const #172 = NameAndType #173:#85;// getId)Ljava/lang/String;
      const #173 = Asciz getId;
      const #174 = Field #1.#175; // org/apache/tapestry/corelib/components/Select._locale:Ljava/util/Locale;
      const #175 = NameAndType #12:#13;// _locale:Ljava/util/Locale;
      const #176 = InterfaceMethod #136.#177; // org/apache/tapestry/ComponentResources.getAnnotationProvider:(Ljava/lang/String;)Lorg/apache/tapestry/ioc/AnnotationProvider;
      const #177 = NameAndType #178:#179;// getAnnotationProvider:(Ljava/lang/String;)Lorg/apache/tapestry/ioc/AnnotationProvider;
      const #178 = Asciz getAnnotationProvider;
      const #179 = Asciz (Ljava/lang/String;)Lorg/apache/tapestry/ioc/AnnotationProvider;;
      const #180 = InterfaceMethod #181.#183; // org/apache/tapestry/services/FieldValidatorDefaultSource.createDefaultValidator:(Lorg/apache/tapestry/Field;Ljava/lang/String;Lorg/apache/tapestry/ioc/Messages;Ljava/util/Locale;Ljava/lang/Class;Lorg/apache/tapestry/ioc/AnnotationProvider;)Lorg/apache/tapestry/FieldValidator;
      const #181 = class #182; // org/apache/tapestry/services/FieldValidatorDefaultSource
      const #182 = Asciz org/apache/tapestry/services/FieldValidatorDefaultSource;
      const #183 = NameAndType #184:#185;// createDefaultValidator:(Lorg/apache/tapestry/Field;Ljava/lang/String;Lorg/apache/tapestry/ioc/Messages;Ljava/util/Locale;Ljava/lang/Class;Lorg/apache/tapestry/ioc/AnnotationProvider;)Lorg/apache/tapestry/FieldValidator;
      const #184 = Asciz createDefaultValidator;
      const #185 = Asciz (Lorg/apache/tapestry/Field;Ljava/lang/String;Lorg/apache/tapestry/ioc/Messages;Ljava/util/Locale;Ljava/lang/Class;Lorg/apache/tapestry/ioc/AnnotationProvider;)Lorg/apache/tapestry/FieldValidator;;
      const #186 = Asciz type;
      const #187 = Asciz defaultValue;
      const #188 = Asciz ()Lorg/apache/tapestry/Binding;;
      const #189 = Method #1.#190; // org/apache/tapestry/corelib/components/Select.createDefaultParameterBinding:(Ljava/lang/String;)Lorg/apache/tapestry/Binding;
      const #190 = NameAndType #191:#192;// createDefaultParameterBinding:(Ljava/lang/String;)Lorg/apache/tapestry/Binding;
      const #191 = Asciz createDefaultParameterBinding;
      const #192 = Asciz (Ljava/lang/String;)Lorg/apache/tapestry/Binding;;
      const #193 = Asciz options;
      const #194 = Asciz Lorg/apache/tapestry/annotations/BeforeRenderTemplate;;
      const #195 = class #196; // org/apache/tapestry/corelib/components/Select$Renderer
      const #196 = Asciz org/apache/tapestry/corelib/components/Select$Renderer;
      const #197 = Method #195.#198; // org/apache/tapestry/corelib/components/Select$Renderer."<init>":(Lorg/apache/tapestry/corelib/components/Select;Lorg/apache/tapestry/MarkupWriter;)V
      const #198 = NameAndType #34:#199;// "<init>":(Lorg/apache/tapestry/corelib/components/Select;Lorg/apache/tapestry/MarkupWriter;)V
      const #199 = Asciz (Lorg/apache/tapestry/corelib/components/Select;Lorg/apache/tapestry/MarkupWriter;)V;
      const #200 = Field #1.#201; // org/apache/tapestry/corelib/components/Select._model:Lorg/apache/tapestry/SelectModel;
      const #201 = NameAndType #14:#15;// _model:Lorg/apache/tapestry/SelectModel;
      const #202 = InterfaceMethod #203.#205; // org/apache/tapestry/SelectModel.visit:(Lorg/apache/tapestry/SelectModelVisitor;)V
      const #203 = class #204; // org/apache/tapestry/SelectModel
      const #204 = Asciz org/apache/tapestry/SelectModel;
      const #205 = NameAndType #206:#207;// visit:(Lorg/apache/tapestry/SelectModelVisitor;)V
      const #206 = Asciz visit;
      const #207 = Asciz (Lorg/apache/tapestry/SelectModelVisitor;)V;
      const #208 = Asciz renderer;
      const #209 = Asciz Lorg/apache/tapestry/SelectModelVisitor;;
      const #210 = Asciz setModel;
      const #211 = Asciz (Lorg/apache/tapestry/SelectModel;)V;
      const #212 = Asciz model;
      const #213 = Asciz setValue;
      const #214 = Asciz access$0;
      const #215 = Asciz (Lorg/apache/tapestry/corelib/components/Select;)Lorg/apache/tapestry/ValueEncoder;;
      const #216 = Asciz access$1;
      const #217 = Asciz (Lorg/apache/tapestry/corelib/components/Select;)Ljava/lang/Object;;
      const #218 = Asciz SourceFile;
      const #219 = Asciz Select.java;
      const #220 = Asciz InnerClasses;
      const #221 = Asciz Renderer;

      { private org.apache.tapestry.ValueEncoder _encoder; RuntimeVisibleAnnotations: length = 0x6 00 01 00 08 00 00 private org.apache.tapestry.services.FieldValidatorDefaultSource _fieldValidatorDefaultSource; RuntimeVisibleAnnotations: length = 0x6 00 01 00 0B 00 00 private java.util.Locale _locale; RuntimeVisibleAnnotations: length = 0x6 00 01 00 0B 00 00 private org.apache.tapestry.SelectModel _model; RuntimeVisibleAnnotations: length = 0xB 00 01 00 08 00 01 00 10 5A 00 11 private org.apache.tapestry.services.Request _request; RuntimeVisibleAnnotations: length = 0x6 00 01 00 0B 00 00 private org.apache.tapestry.ComponentResources _resources; RuntimeVisibleAnnotations: length = 0x6 00 01 00 0B 00 00 private org.apache.tapestry.ValidationTracker _tracker; RuntimeVisibleAnnotations: length = 0x6 00 01 00 18 00 00 private org.apache.tapestry.FieldValidator _validate; Signature: length = 0x2 00 1C RuntimeVisibleAnnotations: length = 0xB 00 01 00 08 00 01 00 1D 73 00 1E private java.lang.Object _value; RuntimeVisibleAnnotations: length = 0x10 00 01 00 08 00 02 00 10 5A 00 11 00 21 5A 00 11 public org.apache.tapestry.corelib.components.Select(); Code: Stack=4, Locals=1, Args_size=1 0: aload_0 1: invokespecial #37; //Method org/apache/tapestry/corelib/base/AbstractField."<init>":()V 4: aload_0 5: new #39; //class org/apache/tapestry/corelib/components/Select$1 8: dup 9: aload_0 10: invokespecial #41; //Method org/apache/tapestry/corelib/components/Select$1."<init>":(Lorg/apache/tapestry/corelib/components/Select;)V 13: putfield #44; //Field _encoder:Lorg/apache/tapestry/ValueEncoder; 16: aload_0 17: getstatic #46; //Field NOOP_VALIDATOR:Lorg/apache/tapestry/FieldValidator; 20: putfield #49; //Field _validate:Lorg/apache/tapestry/FieldValidator; 23: return LineNumberTable: line 45: 0 line 68: 4 line 111: 16 line 45: 23 LocalVariableTable: Start Length Slot Name Signature 0 24 0 this Lorg/apache/tapestry/corelib/components/Select; protected void processSubmission(org.apache.tapestry.services.FormSupport, java.lang.String); Code: Stack=3, Locals=6, Args_size=3 0: aload_0 1: getfield #57; //Field _request:Lorg/apache/tapestry/services/Request; 4: aload_2 5: invokeinterface #59, 2; //InterfaceMethod org/apache/tapestry/services/Request.getParameter:(Ljava/lang/String;)Ljava/lang/String; 10: astore_3 11: aload_0 12: getfield #44; //Field _encoder:Lorg/apache/tapestry/ValueEncoder; 15: aload_3 16: invokeinterface #65, 2; //InterfaceMethod org/apache/tapestry/ValueEncoder.toValue:(Ljava/lang/String;)Ljava/lang/Object; 21: astore 4 23: aload_0 24: getfield #49; //Field _validate:Lorg/apache/tapestry/FieldValidator; 27: aload 4 29: invokeinterface #71, 2; //InterfaceMethod org/apache/tapestry/FieldValidator.validate:(Ljava/lang/Object;)V 34: aload_0 35: aload 4 37: putfield #76; //Field _value:Ljava/lang/Object; 40: goto 61 43: astore 5 45: aload_0 46: getfield #78; //Field _tracker:Lorg/apache/tapestry/ValidationTracker; 49: aload_0 50: aload 5 52: invokevirtual #80; //Method org/apache/tapestry/ValidationException.getMessage:()Ljava/lang/String; 55: invokeinterface #86, 3; //InterfaceMethod org/apache/tapestry/ValidationTracker.recordError:(Lorg/apache/tapestry/Field;Ljava/lang/String;)V 60: return 61: return Exception table: from to target type 23 40 43 Class org/apache/tapestry/ValidationException LineNumberTable: line 120: 0 line 122: 11 line 126: 23 line 128: 34 line 130: 43 line 132: 45 line 133: 60 line 135: 61 LocalVariableTable: Start Length Slot Name Signature 0 62 0 this Lorg/apache/tapestry/corelib/components/Select; 0 62 1 formSupport Lorg/apache/tapestry/services/FormSupport; 0 62 2 elementName Ljava/lang/String; 11 51 3 primaryKey Ljava/lang/String; 23 39 4 selectedValue Ljava/lang/Object; 45 16 5 ex Lorg/apache/tapestry/ValidationException; void afterRender(org.apache.tapestry.MarkupWriter); Code: Stack=1, Locals=2, Args_size=2 0: aload_1 1: invokeinterface #102, 1; //InterfaceMethod org/apache/tapestry/MarkupWriter.end:()Lorg/apache/tapestry/dom/Element; 6: pop 7: return LineNumberTable: line 139: 0 line 140: 7 LocalVariableTable: Start Length Slot Name Signature 0 8 0 this Lorg/apache/tapestry/corelib/components/Select; 0 8 1 writer Lorg/apache/tapestry/MarkupWriter; void beginRender(org.apache.tapestry.MarkupWriter); Code: Stack=6, Locals=2, Args_size=2 0: aload_1 1: ldc #111; //String select 3: iconst_4 4: anewarray #113; //class java/lang/Object 7: dup 8: iconst_0 9: ldc #115; //String name 11: aastore 12: dup 13: iconst_1 14: aload_0 15: invokevirtual #117; //Method getElementName:()Ljava/lang/String; 18: aastore 19: dup 20: iconst_2 21: ldc #120; //String id 23: aastore 24: dup 25: iconst_3 26: aload_0 27: invokevirtual #122; //Method getClientId:()Ljava/lang/String; 30: aastore 31: invokeinterface #125, 3; //InterfaceMethod org/apache/tapestry/MarkupWriter.element:(Ljava/lang/String;[Ljava/lang/Object;)Lorg/apache/tapestry/dom/Element; 36: pop 37: return LineNumberTable: line 144: 0 line 147: 37 LocalVariableTable: Start Length Slot Name Signature 0 38 0 this Lorg/apache/tapestry/corelib/components/Select; 0 38 1 writer Lorg/apache/tapestry/MarkupWriter; org.apache.tapestry.ValueEncoder defaultEncoder(); Code: Stack=3, Locals=2, Args_size=1 0: aload_0 1: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 4: ldc #133; //String value 6: invokeinterface #135, 2; //InterfaceMethod org/apache/tapestry/ComponentResources.getBoundType:(Ljava/lang/String;)Ljava/lang/Class; 11: astore_1 12: aload_1 13: ifnonnull 18 16: aconst_null 17: areturn 18: ldc #141; //class java/lang/Enum 20: aload_1 21: invokevirtual #143; //Method java/lang/Class.isAssignableFrom:(Ljava/lang/Class;)Z 24: ifeq 36 27: new #149; //class org/apache/tapestry/util/EnumValueEncoder 30: dup 31: aload_1 32: invokespecial #151; //Method org/apache/tapestry/util/EnumValueEncoder."<init>":(Ljava/lang/Class;)V 35: areturn 36: aconst_null 37: areturn LineNumberTable: line 152: 0 line 154: 12 line 156: 18 line 158: 36 LocalVariableTable: Start Length Slot Name Signature 0 38 0 this Lorg/apache/tapestry/corelib/components/Select; 12 26 1 valueType Ljava/lang/Class; org.apache.tapestry.SelectModel defaultModel(); Code: Stack=4, Locals=2, Args_size=1 0: aload_0 1: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 4: ldc #133; //String value 6: invokeinterface #135, 2; //InterfaceMethod org/apache/tapestry/ComponentResources.getBoundType:(Ljava/lang/String;)Ljava/lang/Class; 11: astore_1 12: aload_1 13: ifnonnull 18 16: aconst_null 17: areturn 18: ldc #141; //class java/lang/Enum 20: aload_1 21: invokevirtual #143; //Method java/lang/Class.isAssignableFrom:(Ljava/lang/Class;)Z 24: ifeq 45 27: new #158; //class org/apache/tapestry/util/EnumSelectModel 30: dup 31: aload_1 32: aload_0 33: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 36: invokeinterface #160, 1; //InterfaceMethod org/apache/tapestry/ComponentResources.getContainerMessages:()Lorg/apache/tapestry/ioc/Messages; 41: invokespecial #164; //Method org/apache/tapestry/util/EnumSelectModel."<init>":(Ljava/lang/Class;Lorg/apache/tapestry/ioc/Messages;)V 44: areturn 45: aconst_null 46: areturn LineNumberTable: line 164: 0 line 166: 12 line 168: 18 line 169: 27 line 171: 45 LocalVariableTable: Start Length Slot Name Signature 0 47 0 this Lorg/apache/tapestry/corelib/components/Select; 12 35 1 valueType Ljava/lang/Class; org.apache.tapestry.FieldValidator defaultValidate(); Code: Stack=8, Locals=2, Args_size=1 0: aload_0 1: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 4: ldc #133; //String value 6: invokeinterface #135, 2; //InterfaceMethod org/apache/tapestry/ComponentResources.getBoundType:(Ljava/lang/String;)Ljava/lang/Class; 11: astore_1 12: aload_1 13: ifnonnull 18 16: aconst_null 17: areturn 18: aload_0 19: getfield #169; //Field _fieldValidatorDefaultSource:Lorg/apache/tapestry/services/FieldValidatorDefaultSource; 22: aload_0 23: aload_0 24: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 27: invokeinterface #171, 1; //InterfaceMethod org/apache/tapestry/ComponentResources.getId:()Ljava/lang/String; 32: aload_0 33: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 36: invokeinterface #160, 1; //InterfaceMethod org/apache/tapestry/ComponentResources.getContainerMessages:()Lorg/apache/tapestry/ioc/Messages; 41: aload_0 42: getfield #174; //Field _locale:Ljava/util/Locale; 45: aload_1 46: aload_0 47: getfield #131; //Field _resources:Lorg/apache/tapestry/ComponentResources; 50: ldc #133; //String value 52: invokeinterface #176, 2; //InterfaceMethod org/apache/tapestry/ComponentResources.getAnnotationProvider:(Ljava/lang/String;)Lorg/apache/tapestry/ioc/AnnotationProvider; 57: invokeinterface #180, 7; //InterfaceMethod org/apache/tapestry/services/FieldValidatorDefaultSource.createDefaultValidator:(Lorg/apache/tapestry/Field;Ljava/lang/String;Lorg/apache/tapestry/ioc/Messages;Ljava/util/Locale;Ljava/lang/Class;Lorg/apache/tapestry/ioc/AnnotationProvider;)Lorg/apache/tapestry/FieldValidator; 62: areturn LineNumberTable: line 180: 0 line 182: 12 line 184: 18 line 185: 22 line 186: 23 line 187: 32 line 188: 41 line 189: 45 line 190: 46 line 184: 57 LocalVariableTable: Start Length Slot Name Signature 0 63 0 this Lorg/apache/tapestry/corelib/components/Select; 12 51 1 type Ljava/lang/Class; org.apache.tapestry.Binding defaultValue(); Code: Stack=2, Locals=1, Args_size=1 0: aload_0 1: ldc #133; //String value 3: invokevirtual #189; //Method createDefaultParameterBinding:(Ljava/lang/String;)Lorg/apache/tapestry/Binding; 6: areturn LineNumberTable: line 195: 0 LocalVariableTable: Start Length Slot Name Signature 0 7 0 this Lorg/apache/tapestry/corelib/components/Select; void options(org.apache.tapestry.MarkupWriter); RuntimeVisibleAnnotations: length = 0x6 00 01 00 FFFFFFC2 00 00 Code: Stack=4, Locals=3, Args_size=2 0: new #195; //class org/apache/tapestry/corelib/components/Select$Renderer 3: dup 4: aload_0 5: aload_1 6: invokespecial #197; //Method org/apache/tapestry/corelib/components/Select$Renderer."<init>":(Lorg/apache/tapestry/corelib/components/Select;Lorg/apache/tapestry/MarkupWriter;)V 9: astore_2 10: aload_0 11: getfield #200; //Field _model:Lorg/apache/tapestry/SelectModel; 14: aload_2 15: invokeinterface #202, 2; //InterfaceMethod org/apache/tapestry/SelectModel.visit:(Lorg/apache/tapestry/SelectModelVisitor;)V 20: return LineNumberTable: line 201: 0 line 203: 10 line 204: 20 LocalVariableTable: Start Length Slot Name Signature 0 21 0 this Lorg/apache/tapestry/corelib/components/Select; 0 21 1 writer Lorg/apache/tapestry/MarkupWriter; 10 11 2 renderer Lorg/apache/tapestry/SelectModelVisitor; void setModel(org.apache.tapestry.SelectModel); Code: Stack=2, Locals=2, Args_size=2 0: aload_0 1: aload_1 2: putfield #200; //Field _model:Lorg/apache/tapestry/SelectModel; 5: return LineNumberTable: line 210: 0 line 211: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lorg/apache/tapestry/corelib/components/Select; 0 6 1 model Lorg/apache/tapestry/SelectModel; void setValue(java.lang.Object); Code: Stack=2, Locals=2, Args_size=2 0: aload_0 1: aload_1 2: putfield #76; //Field _value:Ljava/lang/Object; 5: return LineNumberTable: line 215: 0 line 216: 5 LocalVariableTable: Start Length Slot Name Signature 0 6 0 this Lorg/apache/tapestry/corelib/components/Select; 0 6 1 value Ljava/lang/Object; static org.apache.tapestry.ValueEncoder access$0(org.apache.tapestry.corelib.components.Select); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #44; //Field _encoder:Lorg/apache/tapestry/ValueEncoder; 4: areturn LineNumberTable: line 68: 0 static java.lang.Object access$1(org.apache.tapestry.corelib.components.Select); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #76; //Field _value:Ljava/lang/Object; 4: areturn LineNumberTable: line 115: 0 }

      Here's the class transformation that occurred:

      InternalClassTransformation[
      public final org.apache.tapestry.corelib.components.Select extends org.apache.tapestry.corelib.base.AbstractField

      add method: private void _$write_locale_0(java.util.Locale $1)
      throw new java.lang.RuntimeException("Field org.apache.tapestry.corelib.components.Select._locale is read-only.");

      replace write _locale: _$write_locale_0();

      add method: private void _$write_resources_1(org.apache.tapestry.ComponentResources $1)
      throw new java.lang.RuntimeException("Field org.apache.tapestry.corelib.components.Select._resources is read-only.");

      replace write _resources: _$write_resources_1();

      add method: private void _$write_fieldValidatorDefaultSource_0(org.apache.tapestry.services.FieldValidatorDefaultSource $1)
      throw new java.lang.RuntimeException("Field org.apache.tapestry.corelib.components.Select._fieldValidatorDefaultSource is read-only.");

      replace write _fieldValidatorDefaultSource: _$write_fieldValidatorDefaultSource_0();

      add method: private void _$write_request_1(org.apache.tapestry.services.Request $1)
      throw new java.lang.RuntimeException("Field org.apache.tapestry.corelib.components.Select._request is read-only.");

      replace write _request: _$write_request_1();

      add method: private org.apache.tapestry.ValidationTracker _$environment_read_tracker_0()
      return ($r) _$environment.peekRequired($type);

      replace read _tracker: _$environment_read_tracker_0();

      add method: private void _$write_tracker_0(org.apache.tapestry.ValidationTracker $1)
      throw new java.lang.RuntimeException("Field org.apache.tapestry.corelib.components.Select._tracker is read-only.");

      replace write _tracker: _$write_tracker_0();

      remove field _tracker;

      add field: private boolean _$value_cached_1;

      add field: private java.lang.Object _$value_default_2;

      add field: private boolean _$value_invariant_1;

      extend method: public void containingPageDidLoad()
      {
      if (! _$resources.isBound("value"))
      org.apache.tapestry.internal.services.ParameterWorker.bind("value", _$resources, defaultValue());
      _$value_invariant_1 = _$resources.isInvariant("value");
      _$value_default_2 = _value;
      }

      extend method: public void postRenderCleanup()
      if (! _$value_invariant_1)
      {
      _value = _$value_default_2;
      _$value_cached_1 = false;
      }

      add method: private java.lang.Object _$read_parameter_value_1()
      {
      if (_$value_cached_1 || ! _$resources.isLoaded() || ! _$resources.isBound("value")) return _value;
      java.lang.Object result = ($r) ((java.lang.Object) _$resources.readParameter("value", $type));
      if (_$value_invariant_1 || _$resources.isRendering())

      { _value = result; _$value_cached_1 = true; }

      return result;
      }

      replace read _value: _$read_parameter_value_1();

      add method: private void _$update_parameter_value_1(java.lang.Object $1)
      {
      if (! _$resources.isLoaded())

      { _value = $1; return; }

      if (_$resources.isBound("value"))
      _$resources.writeParameter("value", ($w)$1);
      _value = $1;
      _$value_cached_1 = _$resources.isRendering();
      }

      replace write _value: _$update_parameter_value_1();

      add field: private boolean _$encoder_cached;

      add field: private org.apache.tapestry.ValueEncoder _$encoder_default;

      add field: private boolean _$encoder_invariant;

      extend method: public void containingPageDidLoad()
      {
      if (! _$resources.isBound("encoder"))
      org.apache.tapestry.internal.services.ParameterWorker.bind("encoder", _$resources, defaultEncoder());
      _$encoder_invariant = _$resources.isInvariant("encoder");
      _$encoder_default = _encoder;
      }

      extend method: public void postRenderCleanup()
      if (! _$encoder_invariant)
      {
      _encoder = _$encoder_default;
      _$encoder_cached = false;
      }

      add method: private org.apache.tapestry.ValueEncoder _$read_parameter_encoder()
      {
      if (_$encoder_cached || ! _$resources.isLoaded() || ! _$resources.isBound("encoder")) return _encoder;
      org.apache.tapestry.ValueEncoder result = ($r) ((org.apache.tapestry.ValueEncoder) _$resources.readParameter("encoder", $type));
      if (_$encoder_invariant || _$resources.isRendering())

      { _encoder = result; _$encoder_cached = true; }

      return result;
      }

      replace read _encoder: _$read_parameter_encoder();

      add method: private void _$update_parameter_encoder(org.apache.tapestry.ValueEncoder $1)
      {
      if (! _$resources.isLoaded())

      { _encoder = $1; return; }

      if (_$resources.isBound("encoder"))
      _$resources.writeParameter("encoder", ($w)$1);
      _encoder = $1;
      _$encoder_cached = _$resources.isRendering();
      }

      replace write _encoder: _$update_parameter_encoder();

      add field: private boolean _$model_cached;

      add field: private org.apache.tapestry.SelectModel _$model_default;

      add field: private boolean _$model_invariant;

      extend method: public void containingPageDidLoad()
      {
      if (! _$resources.isBound("model"))
      org.apache.tapestry.internal.services.ParameterWorker.bind("model", _$resources, defaultModel());
      _$model_invariant = _$resources.isInvariant("model");
      _$model_default = _model;
      }

      extend method: public void postRenderCleanup()
      if (! _$model_invariant)
      {
      _model = _$model_default;
      _$model_cached = false;
      }

      add method: private org.apache.tapestry.SelectModel _$read_parameter_model()
      {
      if (_$model_cached || ! _$resources.isLoaded() || ! _$resources.isBound("model")) return _model;
      org.apache.tapestry.SelectModel result = ($r) ((org.apache.tapestry.SelectModel) _$resources.readParameter("model", $type));
      if (_$model_invariant || _$resources.isRendering())

      { _model = result; _$model_cached = true; }

      return result;
      }

      replace read _model: _$read_parameter_model();

      add method: private void _$update_parameter_model(org.apache.tapestry.SelectModel $1)
      {
      if (! _$resources.isLoaded())

      { _model = $1; return; }

      if (_$resources.isBound("model"))
      _$resources.writeParameter("model", ($w)$1);
      _model = $1;
      _$model_cached = _$resources.isRendering();
      }

      replace write _model: _$update_parameter_model();

      add field: private boolean _$validate_cached_0;

      add field: private org.apache.tapestry.FieldValidator _$validate_default_0;

      add field: private boolean _$validate_invariant_0;

      extend method: public void containingPageDidLoad()
      {
      if (! _$resources.isBound("validate"))
      org.apache.tapestry.internal.services.ParameterWorker.bind("validate", _$resources, defaultValidate());
      _$validate_invariant_0 = _$resources.isInvariant("validate");
      _$validate_default_0 = _validate;
      }

      extend method: public void postRenderCleanup()
      if (! _$validate_invariant_0)
      {
      _validate = _$validate_default_0;
      _$validate_cached_0 = false;
      }

      add method: private org.apache.tapestry.FieldValidator _$read_parameter_validate_0()
      {
      if (_$validate_cached_0 || ! _$resources.isLoaded() || ! _$resources.isBound("validate")) return _validate;
      org.apache.tapestry.FieldValidator result = ($r) ((org.apache.tapestry.FieldValidator) _$resources.readParameter("validate", $type));
      if (_$validate_invariant_0 || _$resources.isRendering())

      { _validate = result; _$validate_cached_0 = true; }

      return result;
      }

      replace read _validate: _$read_parameter_validate_0();

      add method: private void _$update_parameter_validate_0(org.apache.tapestry.FieldValidator $1)
      {
      if (! _$resources.isLoaded())

      { _validate = $1; return; }

      if (_$resources.isBound("validate"))
      _$resources.writeParameter("validate", ($w)$1);
      _validate = $1;
      _$validate_cached_0 = _$resources.isRendering();
      }

      replace write _validate: _$update_parameter_validate_0();

      add method: public void beginRender(org.apache.tapestry.MarkupWriter $1, org.apache.tapestry.runtime.Event $2)

      { super.beginRender($$); if ($2.isAborted()) return; beginRender($1); } add method: public void beforeRenderTemplate(org.apache.tapestry.MarkupWriter $1, org.apache.tapestry.runtime.Event $2) { super.beforeRenderTemplate($$); if ($2.isAborted()) return; options($1); } add method: public void afterRender(org.apache.tapestry.MarkupWriter $1, org.apache.tapestry.runtime.Event $2) { afterRender($1); super.afterRender($$); } convert default constructor: initializer_4(); add constructor: org.apache.tapestry.corelib.components.Select(org.apache.tapestry.internal.InternalComponentResources $1, org.apache.tapestry.services.DefaultComponentParameterBindingSource $2, org.apache.tapestry.services.Environment $3, org.apache.tapestry.services.BindingSource $4, org.apache.tapestry.services.FieldValidatorDefaultSource $5, org.apache.tapestry.services.Request $6) { super($1, $2, $3, $4); _locale = _$resources.getLocale(); _resources = _$resources; _fieldValidatorDefaultSource = $5; _request = $6; initializer_4(); }

      ]

        Activity

        Hide
        Howard M. Lewis Ship added a comment -

        Turns out Javassist is smart enough to handle this pretty well, if you meet it half-way.

        If you explicitly mention $0 as part of the replaced field's method body, it works, even inside a synthetic accessor. I suspect there's a kludge deep inside Javassist to support this, but I'm fine with that.

        Show
        Howard M. Lewis Ship added a comment - Turns out Javassist is smart enough to handle this pretty well, if you meet it half-way. If you explicitly mention $0 as part of the replaced field's method body, it works, even inside a synthetic accessor. I suspect there's a kludge deep inside Javassist to support this, but I'm fine with that.
        Hide
        Howard M. Lewis Ship added a comment -

        Possibly Javassist doesn't handle a static method accessing a private instance variable correctly, when it converts field access into a method invocation. That's what these access methods have in common.

        Show
        Howard M. Lewis Ship added a comment - Possibly Javassist doesn't handle a static method accessing a private instance variable correctly, when it converts field access into a method invocation. That's what these access methods have in common.
        Hide
        Howard M. Lewis Ship added a comment -

        ... but that's just a workaround and shouldn't be necessary.

        And it turns out even a private accessor method is sufficient.

        Show
        Howard M. Lewis Ship added a comment - ... but that's just a workaround and shouldn't be necessary. And it turns out even a private accessor method is sufficient.
        Hide
        Howard M. Lewis Ship added a comment -

        Fixed this by converting:

        public final class Select extends AbstractField
        {
        private class Renderer extends SelectModelRenderer
        {

        public Renderer(MarkupWriter writer)

        { super(writer, _encoder); }

        @Override
        protected boolean isOptionSelected(OptionModel optionModel)

        { Object value = optionModel.getValue(); return value == _value || (value != null && value.equals(_value)); }

        }

        . . .
        }

        to:

        public final class Select extends AbstractField
        {
        private class Renderer extends SelectModelRenderer
        {

        public Renderer(MarkupWriter writer)

        { super(writer, getEncoder()); }

        @Override
        protected boolean isOptionSelected(OptionModel optionModel)

        { Object value = optionModel.getValue(); return isOptionValueSelected(value); }

        }

        private boolean isOptionValueSelected(Object value)

        { return value == _value || (value != null && value.equals(_value)); }

        private ValueEncoder getEncoder()

        { return _encoder; }

        . . .
        }

        Show
        Howard M. Lewis Ship added a comment - Fixed this by converting: public final class Select extends AbstractField { private class Renderer extends SelectModelRenderer { public Renderer(MarkupWriter writer) { super(writer, _encoder); } @Override protected boolean isOptionSelected(OptionModel optionModel) { Object value = optionModel.getValue(); return value == _value || (value != null && value.equals(_value)); } } . . . } to: public final class Select extends AbstractField { private class Renderer extends SelectModelRenderer { public Renderer(MarkupWriter writer) { super(writer, getEncoder()); } @Override protected boolean isOptionSelected(OptionModel optionModel) { Object value = optionModel.getValue(); return isOptionValueSelected(value); } } private boolean isOptionValueSelected(Object value) { return value == _value || (value != null && value.equals(_value)); } private ValueEncoder getEncoder() { return _encoder; } . . . }

          People

          • Assignee:
            Howard M. Lewis Ship
            Reporter:
            Howard M. Lewis Ship
          • Votes:
            0 Vote for this issue
            Watchers:
            1 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development