auth0 / auth0-java

Java client library for the Auth0 platform
https://auth0.com
MIT License
286 stars 131 forks source link

TokenHolderDeserializer has no default (no arg) constructor #515

Closed ghost closed 1 year ago

ghost commented 1 year ago

Describe the problem you'd like to have solved

I'm deploying a Quarkus native app into GCP Cloud run. I'm using GraalVM, but when auth0 (jackson) is deserializing a HTTP response, I get this error:

Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Class com.auth0.json.auth.TokenHolderDeserializer has no default (no arg) constructor

It seems the same issue as #445.

Describe the ideal solution

Looking at this issue: https://github.com/micronaut-projects/micronaut-core/issues/7649, using @ReflectiveAccess might solve my issue.

jimmyjames commented 1 year ago

👋 hi @jderuere, thanks for raising and providing the info. As noted in https://github.com/auth0/auth0-java/issues/445, TokenHolderDeserializer does have a default constructor, so I'm not sure there's any changes the library could make to address the issue. I'm not super familiar with Micronaut's @ReflectiveAccess, but it seems that may be what's needed in your application as you mentioned.

ghost commented 1 year ago

Hi @jimmyjames, I found out a solution provided by Quarkus to fix this for third party jar:

Just create a class that hold the @RegisterForReflection annotation (example in Kotlin).

import com.auth0.json.auth.TokenHolderDeserializer
import io.quarkus.runtime.annotations.RegisterForReflection

@RegisterForReflection(targets = [TokenHolderDeserializer::class])
class TokenHolderDeserializerConfig

See https://quarkus.io/guides/writing-native-applications-tips#registering-for-reflection

jimmyjames commented 1 year ago

Ah, interesting! Thanks for sharing that info, I'm sure it will be useful for others who encounter the same issue.

Mcfloy commented 1 year ago

For Spring Boot devs here's a equivalent snippet:

@RegisterReflectionForBinding(TokenHolderDeserializer.class)
private TokenHolder requestAccessToken() throws Auth0Exception {
    AuthRequest request = authAPI.requestToken(auth0ConfigProperties.getAudience());
    request.setScope(auth0ConfigProperties.getScopes());
    return request.execute();
}

Note that you can use @RegisterReflectionForBinding on services/components methods and not necessary on configuration beans or classes.

You can use the annotation on your main application to regroup them with other classes (like when using WebClient without any controller)