mardi 4 décembre 2018

Unable to find public method via getMethod()

Supposedly this is not a new problem however I am having trouble finding the solution, because most answers to this refer to the method in question not being public.

Context

There is a package named reflection, where annotations as well as a UITester class are defined, the latter uses a class-annotation and a method-annotation. A different package named gui contains a class MinimalUI which then tests access to UITester, its methods and the respective annotation values. However I am running into a NoSuchMethodException.

Code

FunctionAnnotation

The annotation is used to lock/unlock methods.

package reflection;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;

@Retention( RetentionPolicy.RUNTIME )
@Target( {ElementType.METHOD} )
public @interface FunctionAnnotation
{
    boolean locked();
}

SampleAnnotation

Simple annotation to set some basic class properties.

package reflection;

import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;

@Retention( RetentionPolicy.RUNTIME )
public

@interface SampleAnnotation
{
    String name();
    String value();
    boolean output(); 
}

UITester

This is the annotated class. The class declaration itself is annotated and so is one method of the class, so both annotations previously shown are used.

package reflection;

@SampleAnnotation( name = "default", value = "[MINIMAL UI ANNOTATION] Testing.", output = true )
public class UITester
{
    public UITester()
    {
        System.out.println( "[UI TESTER] Created." );
    }

    public void print( String value )
    {
        System.out.println( "[UI TESTER] Printing: " + value );
    }

    @FunctionAnnotation( locked = false )
    public void printIfAvailable( String value )
    {
         System.out.println( "[UI TESTER] Printing (available): " + value );
    }
}

MinimalUI

Finally there is a minimal UI class that implements the Gui interface, declared in the same package. I am posting just the relevant test method, because otherwise this sample will become a bit large. The following code is method MinimalUI#testUI. It needs to read the annotations set for UITester and behave in accordance with the results. The implementation is minimalistic and lacks safeguards, which is fine, because this is a sandbox project where I am testing patterns to be transferred to production. The code:

@Override
public void testUI()
{
    UITester tester = new UITester();
    Annotation annotation = UITester.class.getAnnotation( SampleAnnotation.class );

    if ( annotation instanceof SampleAnnotation )
    {
        String value = ( (SampleAnnotation) annotation ).value();

        tester.print( value );

        try
        {
            Method possiblyLockedMethod = UITester.class.getMethod( "printIfAvailable" );
            Annotation methodLockCheck = possiblyLockedMethod.getAnnotation( FunctionAnnotation.class );

            if ( !( ( FunctionAnnotation) methodLockCheck ).locked() ) tester.printIfAvailable( value );
        }
        catch( NoSuchMethodException e ) 
        { 
            System.out.println( "[MINIMAL UI][ERROR] Cannot find method to be retrieved. Reflection failed. " + e.getMessage() );
        }
        catch( Exception e )
        {
            System.out.println( "[MINIMAL UI][ERROR] Exception during UI testing via reflection: " + e.getMessage() + " Exception: " + e.toString() );
        }
    } 
    else
    {
        System.out.println( "[MINIMAL UI][ERROR] Reflection error. Unable to read annotation!" );
    }
}

Question

Running MinimalUI#testUI results in a NoSuchMethodException being thrown, so far I do not understand why. The exact line throwing the exception is Method possiblyLockedMethod = UITester.class.getMethod( "printIfAvailable" );.

  • Do annotations somehow influence the behavior of getMethod? Possibly class declaration is changed somehow?
  • Method printIfAvailable is declared public, so then why is it not found? Do annotations somehow influence the public status?
  • Both annotations are annoted with @Retention( RetentionPolicy.RUNTIME ), is it possible that this prevents the function from being defined as the class is loaded or anything of the sort?

I assume it is something simple I am missing. Currently there were no typos I was able to find, so what is going on there?





Aucun commentaire:

Enregistrer un commentaire