mardi 20 juillet 2021

Quarkus native get the value of an annotation

I am trying to acces the value inside of an annotation when I compile my code to quarkus native using the command ./mvnw package -Pnative. I am trying to use Cucumber cli to execute to execute my code like this: Main.run("-g", "com.hellocucumber", "file:/hellocucumber.feature"). I have made some modifications to the source code to get it to work with Quarkus native compilation. My main problem is that there's this block of code Method expressionMethod = annotation.getClass().getMethod("value"); inside of the io.cucumber.java.GlueAdaptor which fails with the error java.lang.IllegalStateException: java.lang.NoSuchMethodException: io.cucumber.java.en.Given$$ProxyImpl.value() because we are trying to access the value of the annotation defined in the StepDefinition class. Here is my step definition class, as well as my feature file.

public class StepDefinitions {
    @Given("today is Sunday")
    public void today_is_Sunday() {
        //Print a message
    }

    @When("I ask whether it's Friday yet")
    public void i_ask_whether_it_s_Friday_yet() {
        //Print a message
    }
    
    @Then("I should be told {string}")
    public void i_should_be_told(String expectedAnswer) {
        //Print a message
    }
 
 }

Scenario: Sunday isn't Friday
    Given today is Sunday
    When I ask whether it's Friday yet
    Then I should be told Nope

I have tried to add the annotation classes (io.cucumber.java.en.Given, io.cucumber.java.en.And, etc) to the reflect.json and provide it to the native compilation as follows: quarkus.native.additional-build-args=-H:DynamicProxyConfigurationResources=reflect-config.json, this doesn't seem to work. I have also moved all the code I modified into an extension and tried to modify the annotations like this:

@BuildStep
    void addProxies(CombinedIndexBuildItem combinedIndexBuildItem,
                    BuildProducer<NativeImageProxyDefinitionBuildItem> proxies) {
        proxies.produce(new NativeImageProxyDefinitionBuildItem(StepDefinitionAnnotation.class.getName()));
        proxies.produce(new NativeImageProxyDefinitionBuildItem(Given.class.getName()));
        proxies.produce(new NativeImageProxyDefinitionBuildItem(When.class.getName()));
        proxies.produce(new NativeImageProxyDefinitionBuildItem(Then.class.getName()));
        proxies.produce(new NativeImageProxyDefinitionBuildItem(And.class.getName()));
        proxies.produce(new NativeImageProxyDefinitionBuildItem(But.class.getName()));
    }

This didn't work either, so finally I tried this:

@BuildStep
void transformAnnotations(BuildProducer<AnnotationsTransformerBuildItem> transformers) {


    transformers.produce(new AnnotationsTransformerBuildItem(new AnnotationsTransformer() {
        @Override
        public boolean appliesTo(AnnotationTarget.Kind kind) {
            return kind == AnnotationTarget.Kind.METHOD;
        }

        @Override
        public void transform(TransformationContext ctx) {
            AnnotationTarget target = ctx.getTarget();
            MethodInfo methodInfo = target.asMethod();
            ClassInfo classInfo = methodInfo.declaringClass();

            AnnotationInstance annotation = methodInfo.annotation(GIVEN_ANNOTATION);
            if (annotation == null) {
                return;
            }
             ctx.transform()
                    .add(create(
                            CDI_NAMED_ANNOTATION,
                            annotation.target(),
                            List.of(AnnotationValue.createStringValue("value", annotation.value().toString()))))
                    .done();
        }
    }));
}

This didn't work either. When I try to print out the method annotations, I only see the annotation class name, no values. When i execute this block of code:

Method[] method = StepDefinitions.class.getMethods();
    for (int j = 0; j < method.length; j++) {
        LOGGER.info("Method annotations: {}", method[j].getAnnotations().length);
        Annotation[] annos = method[j].getAnnotations();
        for (int i = 0; i < annos.length; i++) {
            LOGGER.info("Annotation: {}", annos[i]);
        }
    }

In quarkus dev mode, it prints:

  • Method annotations: 1
  • Annotation: @io.cucumber.java.en.Given(value="today is Sunday")

In quarkus native it prints this:

  • Method annotations: 1
  • Annotation: @io.cucumber.java.en.Given

At this point I have run out ideas on what to try, I am new to the quarkus ecosystem and I'm not sure if this is the right path to take or if there are better alternatives, I am open to any and all suggestions.





Aucun commentaire:

Enregistrer un commentaire