1
votes

I am trying to publish to Google Pub/Sub topic using the following:

ProjectTopicName topicName = ProjectTopicName.of("my-project-id", "my-topic-id");
Publisher publisher = null;

try {
  // Create a publisher instance with default settings bound to the topic
  publisher = Publisher.newBuilder(topicName).build();

  List<String> messages = Arrays.asList("first message", "second message");

  for (final String message : messages) {
    ByteString data = ByteString.copyFromUtf8(message);
    PubsubMessage pubsubMessage = PubsubMessage.newBuilder().setData(data).build();

    // Once published, returns a server-assigned message id (unique within the topic)
    ApiFuture<String> future = publisher.publish(pubsubMessage);

    // Add an asynchronous callback to handle success / failure
    ApiFutures.addCallback(
        future,
        new ApiFutureCallback<String>() {

          @Override
          public void onFailure(Throwable throwable) {
            if (throwable instanceof ApiException) {
              ApiException apiException = ((ApiException) throwable);
              // details on the API exception
              System.out.println(apiException.getStatusCode().getCode());
              System.out.println(apiException.isRetryable());
            }
            System.out.println("Error publishing message : " + message);
          }

          @Override
          public void onSuccess(String messageId) {
            // Once published, returns server-assigned message ids (unique within the topic)
            System.out.println(messageId);
          }
        },
        MoreExecutors.directExecutor());
  }
} finally {
  if (publisher != null) {
    // When finished with the publisher, shutdown to free up resources.
    publisher.shutdown();
    publisher.awaitTermination(1, TimeUnit.MINUTES);
  }
}

I have changed the default values you see here to the particulars of the account I am hitting.

The environment variable points to the JSON file containing the pub/sub authentication credentials:

GOOGLE_APPLICATION_CREDENTIALS

was set using:

export GOOGLE_APPLICATION_CREDENTIALS=path/to/file.json

and verified with echo $GOOGLE_APPLICATION_CREDENTIALS - after a reboot.

But I am still encountering:

The Application Default Credentials are not available. They are available
if running in Google Compute Engine. Otherwise, the environment variable 
GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining 
the credentials. See https://developers.google.com/accounts/docs/application-
default-credentials for more information.

I believe this is related to the default environment that the application is running in, or rather what GCP object thinks the context is -runningOnComputeEngine:

com.google.auth.oauth2.ComputeEngineCredentials runningOnComputeEngine
INFO: Failed to detect whether we are running on Google Compute Engine.

also, a dialog displayed:

Unable to launch App Engine Server
Cannot determine server execution context

and there are no Google Cloud Platform settings in project (Eclipse 2019-3):

GCP Eclipse Settings

This is not an App Engine application.

How to set the environment that GCP objects point to -> Non App Engine.

For reference:

1
Did you use export when you set the variable, as in export GOOGLE_APPLICATION_CREDENTIALS=something? If not, the value will be set in your shell, but not in the child process.Charles Engelke
@CharlesEngelke Yes I did.Roy Hinkley
can you try to run this command to set the default credentials "gcloud auth application-default login"Christopher
@Christopher I do not have that tool present on my system.Roy Hinkley
Hi Roy, you should install the SDK[1] for MacOS before either setting the environment variable GOOGLE_APPLICATION_CREDENTIALS or running the command "gcloud auth application-default login" [1] cloud.google.com/sdkChristopher

1 Answers

0
votes

Google's documentation on this is terrible - it does not mention this anywhere.

The answer is to use:

// create a credentials provider
CredentialsProvider credentialsProvider = FixedCredentialsProvider.create(ServiceAccountCredentials.fromStream(new FileInputStream(Constants.PUB_SUB_KEY)));

// apply credentials provider when creating publisher
publisher = Publisher.newBuilder(topicName).setCredentialsProvider(credentialsProvider).build();

The Environment variable usage is either deprecated or the documentation is flat out wrong, or I'm missing something,... which is entirely possible given the poor documentation.