Uploaded image for project: 'Groovy'
  1. Groovy
  2. GROOVY-8313

NullPointerException in TypeResolver when using generic array return type

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: Major
    • Resolution: Fixed
    • Affects Version/s: None
    • Fix Version/s: 2.4.13
    • Component/s: None
    • Labels:
      None

      Description

      I think this is related to GROOVY-6899. I've been trying to isolate this for some time now: https://github.com/groovy/groovy-eclipse/issues/174. When using a generic array type as a return value, the bridge method is written improperly.

      public interface MultiIndexed<PK, SK> {
        PK getPrimaryKey();
        SK[] getSecondaryKeys();
      }
      
      class MIData implements MultiIndexed<Integer, String> {
        final String value
        final Integer primaryKey
        final String[] secondaryKeys
      
        MIData(String val, Integer pk, String... sk) {
          this.value = val
          this.primaryKey = pk
          this.secondaryKeys = sk
        }
      }
      

      javap on MiData.class shows public final SK[] getSecondaryKeys();. The equivalent Java class shows a different signature for the bridge method: public java.lang.Object[] getSecondaryKeys();.

      This causes an NPE under Introspector when bean info is trying to be resolved.

      java.lang.NullPointerException
          at com.sun.beans.TypeResolver.resolve(TypeResolver.java:203)
          at com.sun.beans.TypeResolver.resolve(TypeResolver.java:162)
          at com.sun.beans.TypeResolver.resolveInClass(TypeResolver.java:81)
          at java.beans.FeatureDescriptor.getReturnType(FeatureDescriptor.java:370)
          at java.beans.Introspector.getTargetEventInfo(Introspector.java:1052)
          at java.beans.Introspector.getBeanInfo(Introspector.java:427)
          at java.beans.Introspector.getBeanInfo(Introspector.java:173)
          at groovy.lang.MetaClassImpl$15.run(MetaClassImpl.java:3289)
          at java.security.AccessController.doPrivileged(Native Method)
          at groovy.lang.MetaClassImpl.addProperties(MetaClassImpl.java:3287)
          at groovy.lang.MetaClassImpl.initialize(MetaClassImpl.java:3263)
          at org.codehaus.groovy.reflection.ClassInfo.getMetaClassUnderLock(ClassInfo.java:254)
          at org.codehaus.groovy.reflection.ClassInfo.getMetaClass(ClassInfo.java:285)
          at MiData.$getStaticMetaClass(MiData.groovy)
          at MiData.<init>(MiData.groovy)
      
      class Main {
        static void main(String[] args) {
          def data = new MIData('V', 1, 'B')
          print 'no error'
        }
      }
      

      I think this can be fixed in Verifier.getCovariantImplementation, like this:

              // if we reach this point we have at least one parameter or return type, that
              // is different in its specified form. That means we have to create a bridge method!
              MethodNode newMethod = new MethodNode(
                      oldMethod.getName(),
                      overridingMethod.getModifiers() | ACC_SYNTHETIC | ACC_BRIDGE,
                      // GRECLIPSE edit
                      //oldMethod.getReturnType().getPlainNodeReference(),
                      GenericsUtils.nonGeneric(oldMethod.getReturnType()),
                      // GRECLIPSE end
                      cleanParameters(oldMethod.getParameters()),
                      oldMethod.getExceptions(),
                      null
              );
      

        Attachments

          Activity

            People

            • Assignee:
              paulk Paul King
              Reporter:
              emilles Eric Milles
            • Votes:
              0 Vote for this issue
              Watchers:
              2 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: