googleapis / googleapis/google-api-java-client-services

Native compilation with GraalVM

Open
#23,642 5 comments 0 reactions 0 assignees View on GitHub
priority: p3 type: bug
Dominant language
Java
Stars
725
Forks
394
Avg merge
42m
Merged PRs (30d)
257

Description

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

- Admin SDK API Client Library, version _directory_v1-rev20240924-2.0.0_
- Java Temurin 21
- Native compilation of a _Spring Boot 3.3.4_ app using by default at this time :
- paketo-buildpacks/ca-certificates 3.8.6
- paketo-buildpacks/bellsoft-liberica 10.9.0
- paketo-buildpacks/syft 2.1.0
- paketo-buildpacks/executable-jar 6.11.3
- paketo-buildpacks/spring-boot 5.31.2
- paketo-buildpacks/native-image 5.14.4

#### Steps to reproduce

Fresh **Spring Boot 3.3.4** project.

**Maven configuration**
```xml

com.google.apis
google-api-services-admin-directory
directory_v1-rev20240924-2.0.0

...

org.graalvm.buildtools
native-maven-plugin

```

**Build Directory service**

```java
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**
```java
@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**
```java
final Users batch = directory
.users()
.list()
.setMaxResults(100)
.setDomain("my-domain.com")
.execute();
```

**Build and run image**
```shell
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: '
-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: '
-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'
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.