Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using header as an API method parameter produces "Missing name information for parameter" error #1847

Closed
nilyin opened this issue Jun 6, 2023 · 10 comments

Comments

@nilyin
Copy link

nilyin commented Jun 6, 2023

Hi, I am am using GraphQLClientAPI in my Quarkus app to access AWS Appsync service. Particularly, I am setting a request Header as API method parameter as stated here in documentation @ https://smallrye.io/smallrye-graphql/2.2.0/typesafe-client-headers/ as this interface:

@GraphQLClientApi(configKey = "appsync")
public interface IGraphQLClientAPI {
    EcoComponentsList listComponents(String version, @Header(name = "Authorization") String accessToken); 
}

and then using this interface in my GraphQLClient.java class like this:

 @Inject
 IGraphQLClientAPI graphQlClient;

public List<EcoComponent> listComponents(String versionName) {

        String accessToken = sessionManager.getProperty("accessToken");

            List<EcoComponent> result = graphQlClient.listComponents(versionName, accessToken).ecoComponentList().stream()
                    .filter(comp -> comp.versions() != null && comp.versions().size()>0 )
                    .filter(comp -> comp.versions().stream()
                                    .anyMatch(ver -> ver.name() == versionName)
                    )
                    .collect(Collectors.toList());
            return result;
        }

when I run my app I get the following Unknown name / Unknown Source error:

java.lang.RuntimeException: Missing name information for parameter 'arg1' in me.peerf.IGraphQLClientAPI#listComponents.
You can either annotate all parameters with @Name, or compile your source code with the -parameters options, so the parameter names are compiled into the class file and available at runtime.

        at io.smallrye.graphql.client.impl.typesafe.reflection.ParameterInfo.getName(ParameterInfo.java:131)
        at io.smallrye.graphql.client.impl.typesafe.HeaderBuilder.toHeaderName(HeaderBuilder.java:124)
        at io.smallrye.graphql.client.impl.typesafe.HeaderBuilder.resolve(HeaderBuilder.java:120)
        at io.smallrye.graphql.client.impl.typesafe.HeaderBuilder.lambda$build$1(HeaderBuilder.java:58)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183)
        at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:177)
        at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1654)
        at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:484)
        at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:474)
        at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:150)
        at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:173)
        at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
        at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:497)
        at io.smallrye.graphql.client.impl.typesafe.HeaderBuilder.build(HeaderBuilder.java:58)
        at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientProxy.invoke(VertxTypesafeGraphQLClientProxy.java:130)
        at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientBuilder.invoke(VertxTypesafeGraphQLClientBuilder.java:190)
        at io.smallrye.graphql.client.vertx.typesafe.VertxTypesafeGraphQLClientBuilder.lambda$build$0(VertxTypesafeGraphQLClientBuilder.java:150)
        at com.sun.proxy.$Proxy44.listComponents(Unknown Source)
        at me.peerf.IGraphQLClientAPI_9fe4c5ba9e82c9a0fbefec158e044b6c7bbd88d0_Synthetic_ClientProxy.listComponents(Unknown Source)
        at me.peerf.GraphQLClient.listComponents(GraphQLClient.java:56)


it looks like the second (header) parameter in function graphQlClient.listComponents(versionName, accessToken) is not recognized... What am I doing wrong?

  1. also I have related question#2: the same documentation link above says I may use specifically '@AuthrizationHeader' for auth, but when I replace basic @Header annotation in parameter definition with @AuthrizationHeader:
EcoComponentsList listComponents(String version, @AuthorizationHeader String accessToken);

I am receiving "'@AuthorizationHeader' not applicable to parameter" error. How can I apply this type of header in case of dynamic header valuer parametrization?

@jmartisk
Copy link
Member

jmartisk commented Jun 7, 2023

It's exactly what the exception says - you have to compile your application with the -parameters argument to the javac compiler.
The only way around this is to annotate all parameters with the @Name so that the library can deduce the parameter name from it.
Also see #1714 for a very similar issue.

I am receiving "'@AuthorizationHeader' not applicable to parameter" error.

This annotation can only be applied on a method (then only that operation will use the header) or class (then all operations in that API will use it).

How can I apply this type of header in case of dynamic header valuer parametrization?

I think that @AuthorizationHeader doesn't allow dynamic changes. For that you need to either use the plain @Header, or use the TypesafeGraphQLClientBuilder to build your client dynamically, and then close and re-build it with a different header when the value needs to change.

@nilyin
Copy link
Author

nilyin commented Jun 7, 2023

@jmartisk hi, thanks for your answers. the 2nd answer on @AuthorizationHeader is fully addressed and clear.

Regarding the @name annotation, can you elaborate a bit more and give additional insight, such as:

  • which package's @name to use
  • where exactly to use it and how (may be link to examples available?)

for information: I used @name from "org.eclipse.microprofile.graphql" package and the only place I was allowed to put it was my wrapper-function of GraphQLClient.java class as shown below:

 @Inject
 IGraphQLClientAPI graphQlClient;

public List<EcoComponent> listComponents(@Name("versionName") String versionName) {

        String accessToken = sessionManager.getProperty("accessToken");

            List<EcoComponent> result = graphQlClient.listComponents(versionName, accessToken).ecoComponentList().stream()
                    .filter(comp -> comp.versions() != null && comp.versions().size()>0 )
                    .filter(comp -> comp.versions().stream()
                                    .anyMatch(ver -> ver.name() == versionName)
                    )
                    .collect(Collectors.toList());
            return result;
        }

this way it works, and I've moved further, but I still want to understand the reason why function parameters naming and ordering doesn't simply work in the declared method:

@GraphQLClientApi(configKey = "appsync")
public interface IGraphQLClientAPI {
    EcoComponentsList listComponents(String version, @Header(name = "Authorization") String accessToken); 
}

@jmartisk
Copy link
Member

jmartisk commented Jun 7, 2023

You'll need to put @org.eclipse.microprofile.graphql.Name on all parameters, so

    EcoComponentsList listComponents(@Name("version") String version, @Name("accessToken") @Header(name = "Authorization") String accessToken); 

The annotation on the accessToken parameter seems unnecessary to me though, if it still throws that error after you annotate version then it's probably a bug, can you confirm that?

In any case, the safest and recommended way forward would be to use -parameters when compiling. Then you won't need any additional annotations.

@nilyin
Copy link
Author

nilyin commented Jun 7, 2023

@jmartisk hi, the example with @name annotation for all parameters as shown in your example above works ok. The code without annotation for @Header parameter as shown below still produces error:

EcoComponentsList listComponents(@Name("version") String version, @Header(name = "Authorization") String accessToken); 

so I suppose, it has to be fixed.

for your information I am using:
quarkus 2.16.6.Final
java 11.0.2 2019-01-15 LTS

Thank you very much for your answers. I am unblocked now. It would be also great to add this information on both headers usage (with examples) into the project's documentation page mentioned in my post.

@jmartisk
Copy link
Member

jmartisk commented Jun 8, 2023

I'll try to add a little fix that will let you use a @Header parameter without adding @Name to it, because the name isn't actually needed for anything in such case.
But I won't add it as an example into the documentation, rather I'll make it clear that it is a requirement to compile with the -parameters flag. The fact that we made it work in some cases without that flag is basically just a little hack and shouldn't be relied upon.

@jmartisk
Copy link
Member

jmartisk commented Jun 8, 2023

Hmm, hold on, what version of SmallRye GraphQL are you using?
I'm actually trying to reproduce your problem and I can't, this was probably already fixed by via #1715
The first fixed version is 2.1.0.
Your stack trace also seems to suggest that you're using an older version where this PR isn't incorporated.

@jmartisk
Copy link
Member

jmartisk commented Jun 8, 2023

I see, you're using Quarkus 2.16.6, then I'm really surprised that you're not using the -parameters flag, that is present by default on all Quarkus projects generated by the CLI or code.quarkus.io. With that, you wouldn't have hit this problem at all. You just need to add this under <plugins>:

<plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>${compiler-plugin.version}</version>
        <configuration>
          <compilerArgs>
            <arg>-parameters</arg>
          </compilerArgs>
        </configuration>
      </plugin>

@nilyin
Copy link
Author

nilyin commented Jun 8, 2023

Hi, by steps:

  1. I did generate template of my quarkus project from code.quarkus.io, but commented -parameters for some reason. After uncommenting it I confirm that @Header annotation works without extra @name.

So actually the initial problem can be considered as fixed.

  1. Regarding my version of SmallRye GraphQL : I am using the following dependency:
    <dependency>
      <groupId>io.quarkus</groupId>
      <artifactId>quarkus-smallrye-graphql-client</artifactId>
    </dependency>
  1. I've just checked my dependency tree and found that above dependency/package (in quarkus 2.16.6) uses:
 +- io.smallrye:smallrye-graphql-client:jar:1.9.5:compile

What is recommended way to update smallrye:smallrye-graphql-client version?

if I replace my pom.xml quarkus-smallrye-graphql-client for

<dependency>
    <groupId>io.smallrye</groupId>
    <artifactId>smallrye-graphql-client</artifactId>
    <version>2.2.0</version>
</dependency>

it breaks my project build

if I replace the pom.xml dependency for

<dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-smallrye-graphql-client</artifactId>
    <version>3.1.1.Final</version>
</dependency>

it also breaks my build with following error:

2023-06-08 16:16:56,373 ERROR [io.qua.dep.dev.IsolatedDevModeMain] (main) Failed to start quarkus: java.lang.RuntimeException: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
        [error]: Build step io.quarkus.smallrye.graphql.client.deployment.SmallRyeGraphQLClientProcessor#initializeClientSupport threw an exception: java.lang.NoClassDefFoundError: jakarta/inject/Singleton
        at io.quarkus.smallrye.graphql.client.deployment.SmallRyeGraphQLClientProcessor.initializeClientSupport(SmallRyeGraphQLClientProcessor.java:189)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:566)
        at io.quarkus.deployment.ExtensionLoader$3.execute(ExtensionLoader.java:909)
        at io.quarkus.builder.BuildContext.run(BuildContext.java:281)
        at org.jboss.threads.ContextHandler$1.runWith(ContextHandler.java:18)
        at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2449)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1478)
        at java.base/java.lang.Thread.run(Thread.java:834)
        at org.jboss.threads.JBossThread.run(JBossThread.java:501)
Caused by: java.lang.ClassNotFoundException: jakarta.inject.Singleton
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:516)
        at io.quarkus.bootstrap.classloading.QuarkusClassLoader.loadClass(QuarkusClassLoader.java:466)
        ... 12 more

        

may be its for quarkus v3+ only...
so, how to upgrade SmallRye-GraphQL in quarkus 2.16.6 Final ?

@jmartisk
Copy link
Member

jmartisk commented Jun 8, 2023

I don't think you can separately upgrade the client library version (without nasty hacks that probably wouldn't work anyway), you always get the one that comes with the particular Quarkus version.
So you will either have to upgrade to Quarkus 3.x or we would have to backport the fix and release a micro update that gets pulled into Quarkus 2.16.x. But given that you can fix your problem by adding -parameters, it doesn't seem worth the hassle.

@nilyin
Copy link
Author

nilyin commented Jun 8, 2023

Yes, I agree. Thanks again. I am closing the issue, as my problem is solved and the related understanding is obtained.

@nilyin nilyin closed this as completed Jun 8, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants