quarkus-google-cloud-services
quarkus-google-cloud-services copied to clipboard
Spanner does not work against emulator host
The current state of the Google Cloud Spanner Quarkus extension does not work at all using the Spanner emulator. The reason is actually pretty simple: it requires valid credentials and there is no way around it, even the documented approach does not work.
A way to make it work properly with an emulator is pretty simple, and does not require the hack from the docs described in the link above.
The current code is pretty straight forward, but makes using an emulator practically impossible, because it has a hard dependency via @Inject GoogleCredentials googleCredentials;
.
A way around that and the hack is to programmatically request the GoogleCredentialy
and only bark, it the emulator host is not present, like in this piece of code:
@ApplicationScope
public class SpannerProducer {
@Inject
GcpConfigHolder gcpConfigHolder;
@Inject
SpannerConfiguration spannerConfiguration;
@Produces
@Singleton
@Default
public Spanner storage() throws IOException {
GoogleCredentials googleCredentials = null;
Exception googleCredentialsException = null;
try {
googleCredentials = Arc.container().instance(GoogleCredentials.class).get();
} catch (Exception e) {
googleCredentialsException = e;
}
GcpBootstrapConfiguration gcpConfiguration = gcpConfigHolder.getBootstrapConfig();
SpannerOptions.Builder builder =
SpannerOptions.newBuilder().setProjectId(gcpConfiguration.projectId.orElse(null));
if (!spannerConfiguration.emulatorHost().isPresent()) {
builder.setEmulatorHost(spannerConfiguration.emulatorHost().get());
} else {
if (googleCredentials == null) {
if (googleCredentialsException != null) {
throw new RuntimeException("No GoogleCredentials available", googleCredentialsException);
} else {
throw new RuntimeException("No GoogleCredentials available");
}
}
builder.setCredentials(googleCredentials);
}
return builder.build().getService();
}
In fact it can be done more elegantly by injecting an Instance<GoogleCredentials>
and use instance.isAvailable(). There is multiple places where this can be done as this issue exists in multiple extensions.