3

I am exporting data from BigQuery table into Google Cloud Storage and I am able to do this successfully by using Application Default Credentials. I have set the environment variable GOOGLE_APPLICATION_CREDENTIALS in bash_profile(This environment variable points to my Service account JSON file) and this is how I am able to retrieve BigQuery Service(I am using Scala(Java API is used)).

val bigquery: BigQuery = BigQueryOptions.getDefaultInstance().getService()

Now, I am trying to find a way to retrieve the BigQuery service by passing the service account JSON file programmatically instead of using the environment variable(i.e. GOOGLE_APPLICATION_CREDENTIALS)

val inputStream = this.getClass.getResourceAsStream("/GCCredentials.json")
val credentials = GoogleCredentials.fromStream(inputStream)
val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).build().getService    

But this code do not work and I am getting the following exception

Exception in thread "main" java.lang.NullPointerException
    at com.google.api.client.repackaged.com.google.common.base.Preconditions.checkNotNull(Preconditions.java:213)
    at com.google.api.client.util.Preconditions.checkNotNull(Preconditions.java:127)

What am I missing in my code?

1 Answer 1

4

TL;DR - You're missing FileInputStream.

Longer Version

Try this:

val fileInputStream = new FileInputStream("/GCCredentials.json")
var credentials = GoogleCredentials.fromStream(fileInputStream)
val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).build().getService()

Use FileInputStream to read the contents of your service account json file and pass the FileInputStream object to GoogleCredentials to build the credentials.

Alternatively (just for added information), you can use ServiceAccountCredentials instead of GoogleCredentials if you know that the format of the json file is in the service account credentials format.

GoogleCredentials is a base class to read OAuth2 credentials for use with any Google APIs, whereas ServiceAccountCredentials is specific to service accounts. Using either of them will work with your case.

Specifying project to use

You will most likely have to specify the project ID to use (if your environment does not provide this information). The library will attempt to guess the project ID to use if you do not set one explicitly.

You can specify the project ID using one of these environment variables:

  • GOOGLE_CLOUD_PROJECT
  • GCLOUD_PROJECT

If these are not specified, it looks at your currently active gcloud configuration to detect the project to use.

You can also set this in code explicitly (like you described in your comments) as follows:

val bigquery = BigQueryOptions.newBuilder().setCredentials(credentials).setProjectId("MY_PROJECT_ID").build().getService()
6
  • Looks like the code initially worked because it is taking the environment variable GOOGLE_APPLICATION_CREDENTIALS. Now I am getting this error Exception in thread "main" java.lang.IllegalArgumentException: A project ID is required for this service but could not be determined from the builder or the environment. Please set a project ID using the builder.... Although the file has project id
    – Raj
    Commented Jul 23, 2017 at 3:56
  • Looks like I have to specify the project ID by calling BigQueryOptions.newBuilder().setCredentials(credentials).setProjectId(projectID).build().getService(). The code works now. But would have been better if the project ID has been read by the API out of box
    – Raj
    Commented Jul 23, 2017 at 3:58
  • @Raj - Does your service account json file contain the project_id field?
    – Tuxdude
    Commented Jul 23, 2017 at 4:07
  • it does have the field project_id
    – Raj
    Commented Jul 23, 2017 at 5:32
  • 1
    @Raj - Just realized that it picks up a default project based on your currently active local gcloud configuration if it exists, if you do not specify one in BigQueryOptions.Builder. If no projectId has been specified and one does not exist in your current environment, I see the same error you mentioned. Alternatively the project can be specified instead using GCLOUD_PROJECT environment variable.
    – Tuxdude
    Commented Jul 23, 2017 at 6:12

Not the answer you're looking for? Browse other questions tagged or ask your own question.