googleapis / google-api-java-client-services

Generated Java code for Google APIs
Apache License 2.0
619 stars 353 forks source link

Native compilation with GraalVM #23642

Open ValTheBoss opened 1 week ago

ValTheBoss commented 1 week ago

There is an issue when using native compilation with GraalVM. I'm trying to use the Admin SDK API Client Library for directory operations.

Environment details

Steps to reproduce

Fresh Spring Boot 3.3.4 project.

Maven configuration

<dependency>
  <groupId>com.google.apis</groupId>
  <artifactId>google-api-services-admin-directory</artifactId>
  <version>directory_v1-rev20240924-2.0.0</version>
</dependency>
...
<plugin>
  <groupId>org.graalvm.buildtools</groupId>
  <artifactId>native-maven-plugin</artifactId>
</plugin>

Build Directory service

private Directory buildDirectoryService(@Nonnull final String gcpKey, @Nonnull final String serviceAccountUser) throws IOException, GeneralSecurityException {
    final ServiceAccountCredentials sourceCredentials =
        ServiceAccountCredentials.fromStream(...)
        .toBuilder()
        .setServiceAccountUser(serviceAccountUser)
        .setScopes(ImmutableSet.of(
            DirectoryScopes.ADMIN_DIRECTORY_GROUP_READONLY,
            DirectoryScopes.ADMIN_DIRECTORY_USER_READONLY
        ))
        .build();

    return new Directory.Builder(Utils.getDefaultTransport(), Utils.getDefaultJsonFactory(), new HttpCredentialsAdapter(sourceCredentials))
        .setApplicationName("MY_APP")
        .build();
  }

Add reflection hints for ErrorInfo.class

@Configuration
@ImportRuntimeHints(NativeImageHints.class)
class NativeImageHints implements RuntimeHintsRegistrar {
  @Override
  public void registerHints(RuntimeHints hints, ClassLoader classLoader) {
    hints.reflection().registerType(ErrorInfo.class, (type) -> type.withConstructor(Collections.emptyList(), ExecutableMode.INVOKE));
  }
}

Directory api call

final Users batch = directory
            .users()
            .list()
            .setMaxResults(100)
            .setDomain("my-domain.com")
            .execute();

Build and run image

mvn clean spring-boot:build-image -e --no-transfer-progress -P native -D skipTests=true
docker run -p 8080:8080 my-app:0.0.1-SNAPSHOT

Result of directory execute()

2024-10-14T12:44:13.891Z  INFO 1 --- [my-app] [nio-8080-exec-1] c.google.api.client.http.HttpTransport   : {
  "error": {
    "code": 400,
    "message": "Bad Request",
    "errors": [
      {
        "message": "Bad Request",
        "domain": "global",
        "reason": "badRequest"
      }
    ]
  }
}

Reason If I launch the app in DEBUG logging mode, I can see that the URL for the API query is not properly prepared :

curl -v --compressed 
-H 'Accept-Encoding: gzip' 
-H 'Authorization: <Not Logged>' 
-H 'User-Agent: MY_APP Google-API-Java-Client/2.7.0 Google-HTTP-Java-Client/1.45.0 (gzip)' 
-H 'x-goog-api-client: gl-java/21.0.4-graalvm gdcl/2.7.0 linux/6.8.0' -- 'https://admin.googleapis.com/admin/directory/v1/users'

instead of

curl -v --compressed 
-H 'Accept-Encoding: gzip' 
-H 'Authorization: <Not Logged>' 
-H 'User-Agent: MY_APP Google-API-Java-Client/2.7.0 Google-HTTP-Java-Client/1.45.0 (gzip)' 
-H 'x-goog-api-client: gl-java/21.0.4-graalvm gdcl/2.7.0 linux/6.8.0' -- 'https://admin.googleapis.com/admin/directory/v1/users?domain=my-domain.com&maxResults=100'
Phakrada666 commented 1 day ago
<dependency>
  <groupId>com.google.apis</groupId>
  <artifactId>google-api-services-admin-directory</artifactId>
  <version>directory_v1-rev20240924-2.0.0</version>
</dependency>
...
<plugin>
  <groupId>org.graalvm.buildtools</groupId>
  <artifactId>native-maven-plugin</artifactId>
</plugin>
diegomarquezp commented 1 day ago

Thanks for reporting this @ValTheBoss. It's certainly strange that the parameters don't get sent in the native image. Do you have by any chance the reproducer project handy so we can look into it? Also, for faster response times, please refer to our support hub.

@Phakrada666, looks like you are sharing the dependencies listed in the bug as well. Are you also running into the same issue?

Phakrada666 commented 1 day ago
2024-10-14T12:44:13.891Z  INFO 1 --- [my-app] [nio-8080-exec-1] c.google.api.client.http.HttpTransport   : {
  "error": {
    "code": 400,
    "message": "Bad Request",
    "errors": [
      {
        "message": "Bad Request",
        "domain": "global",
        "reason": "badRequest"
      }
    ]
  }
}