How to do a simple Google Cloud Trace request in Java - java

I am trying to perform a simple push traces operation to my Google Cloud Trace project and I simply can't seem to send data across.
Here is my build.gradle file:
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.oauth-client:google-oauth-client-java6:1.20.0'
compile 'com.google.apis:google-api-services-cloudtrace:v1-rev6-1.22.0'
}
jar {
from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
And the following Java code with dummy info for the project ID and my secrets file:
package test;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.cloudtrace.v1.CloudTrace;
import com.google.api.services.cloudtrace.v1.CloudTraceScopes;
import com.google.api.services.cloudtrace.v1.model.Trace;
import com.google.api.services.cloudtrace.v1.model.TraceSpan;
import com.google.api.services.cloudtrace.v1.model.Traces;
import java.io.FileInputStream;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.time.Instant;
import java.util.Collections;
public class Test {
public static void main(String[] args) throws IOException, GeneralSecurityException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential cred = GoogleCredential
.fromStream(
new FileInputStream("/path/to/secrets.json"),
httpTransport,
jsonFactory)
.createScoped(Collections.singletonList(CloudTraceScopes.TRACE_APPEND));
CloudTrace gceTrace = new CloudTrace.Builder(httpTransport, jsonFactory, cred)
.setApplicationName("Google Cloud Trace test app")
.build();
TraceSpan span1 = new TraceSpan();
span1.setName("test");
span1.setStartTime(Long.toString(Instant.now().toEpochMilli()*1000000)+"Z");
Trace trace = new Trace();
trace.setSpans(Collections.singletonList(span1));
Traces traces = new Traces();
traces.setTraces(Collections.singletonList(trace));
gceTrace.projects().patchTraces("myprojectid", traces).execute();
}
}
I currently get the following error that contains no helpful indication except something seems to be wrong with my startTime value:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid value at 'traces.traces[0].spans[0].start_time' (type.googleapis.com/google.protobuf.Timestamp), Field 'startTime', Invalid time format: Failed to parse input",
"reason" : "badRequest"
} ],
"message" : "Invalid value at 'traces.traces[0].spans[0].start_time' (type.googleapis.com/google.protobuf.Timestamp), Field 'startTime', Invalid time format: Failed to parse input",
"status" : "INVALID_ARGUMENT"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at test.Test.main(Test.java:44)
I have tried to replace the startTime with the following value:
span1.setStartTime("2016-08-04T01:00:00Z");
which gives me:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Request contains an invalid argument.",
"reason" : "badRequest"
} ],
"message" : "Request contains an invalid argument.",
"status" : "INVALID_ARGUMENT"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1065)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at test.Test.main(Test.java:44)
I also tried adding a endTime with:
span1.setEndTime("2016-08-04T01:00:01Z");
which also gives me the same error.
I'm pretty much at a lost at what needs to be done as I cannot find a single working Java example for this.
Thank you in advance for any pointers for a working solution.

Finally figured it out. Here's a working example with mandatory and optional fields pointed out.
build.gradle
apply plugin: 'java'
repositories {
mavenCentral()
}
dependencies {
compile 'com.google.oauth-client:google-oauth-client-java6:1.20.0'
compile 'com.google.apis:google-api-services-cloudtrace:v1-rev6-1.22.0'
}
jar {
from configurations.compile.collect { it.isDirectory() ? it : zipTree(it) }
}
Test.java
package test;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.cloudtrace.v1.CloudTrace;
import com.google.api.services.cloudtrace.v1.CloudTraceScopes;
import com.google.api.services.cloudtrace.v1.model.Trace;
import com.google.api.services.cloudtrace.v1.model.TraceSpan;
import com.google.api.services.cloudtrace.v1.model.Traces;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.GeneralSecurityException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
public class Test {
public static void main(String[] args) throws IOException, GeneralSecurityException {
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
GoogleCredential cred = GoogleCredential
.fromStream(
new FileInputStream("/path/to/secrets.json"),
httpTransport,
jsonFactory)
.createScoped(Collections.singletonList(CloudTraceScopes.TRACE_APPEND));
CloudTrace gceTrace = new CloudTrace.Builder(httpTransport, jsonFactory, cred)
.setApplicationName("Google Cloud Trace test app")
.build();
// They are optional
Map<String, String> labels = new HashMap<>();
labels.put("key1", "val1");
TraceSpan span = new TraceSpan();
span.setSpanId(new BigInteger("1")); // Mandatory
span.setName("test"); // Optional
span.setKind("RPC_SERVER"); // Optional
span.setStartTime("2016-08-04T01:00:00Z"); // Optional
span.setEndTime("2016-08-04T01:00:01Z"); // Optional
span.setLabels(labels); // Optional
Trace trace = new Trace();
trace.setProjectId("myprojectid"); // Mandatory
trace.setTraceId("A096D4956A424EEB98AE7863505B1E1F"); // Mandatory
trace.setSpans(Collections.singletonList(span)); // Mandatory
Traces traces = new Traces();
traces.setTraces(Collections.singletonList(trace)); // Mandatory
gceTrace.projects().patchTraces("myprojectid", traces).execute();
}
}
While some values are optional, like startTime or endTime, it makes sense to put something there.
I managed to put it together thanks to this question showing the expected values and looking at the REST API doc describing each field, especially for cryptic values like Trace ID:
patchTraces()
Trace and TraceSpan

Related

Google form API using service account

I am using Google Forms API to get form responses using service account.
package com.form.api.poc;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Arrays;
import java.util.Objects;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.forms.v1.Forms;
import com.google.api.services.forms.v1.FormsScopes;
import com.google.api.services.forms.v1.model.ListFormResponsesResponse;
import com.google.auth.oauth2.GoogleCredentials;
public class Test1 {
private static final String APPLICATION_NAME = "google-form-api-project";
private static Forms formsService;
static {
try {
JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
formsService = new Forms.Builder(GoogleNetHttpTransport.newTrustedTransport(),
jsonFactory, null)
.setApplicationName(APPLICATION_NAME).build();
} catch (GeneralSecurityException | IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) throws IOException {
ListFormResponsesResponse response = readResponses("form_id_jdnfka_123b34$Q%#nknk", getAccessToken());
System.out.println(response.toPrettyString());
}
public static String getAccessToken() throws IOException {
GoogleCredentials credential = GoogleCredentials.fromStream(Objects.requireNonNull(
Test1.class.getResourceAsStream("/serviceaccount_cred.json"))).createScoped(Arrays.asList(FormsScopes.FORMS_BODY_READONLY));
return credential.refreshAccessToken().getTokenValue();
}
private static ListFormResponsesResponse readResponses(String formId, String token) throws IOException {
return formsService.forms().responses().list(formId).setOauthToken(token).execute();
}
}
But, I am getting following error as a response:
GET https://forms.googleapis.com/v1/forms/form_id_jdnfka_123b34$Q%#nknk/responses?oauth_token=token_id..........
{
"code" : 403,
"details" : [ {
"#type" : "type.googleapis.com/google.rpc.ErrorInfo",
"reason" : "ACCESS_TOKEN_SCOPE_INSUFFICIENT"
} ],
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Request had insufficient authentication scopes.",
"status" : "PERMISSION_DENIED"
}
I have followed the documentation provided at the following pages:
using-service-account
Delegating-domain wide authority
But, not sure, what is wrong, any help would be appreciated.
Thank you in advance!
Two things has to be done here, first, use FormsScopes .FORMS_RESPONSES_READONLY for responses and the service account email address shall have permission on the given form_id.
Yet, not sure, if its the right way to go ahead, maybe if executed locally thats the reason it requires the permission, maybe if the above program once executed in some GC environment, then the permission need not be given explicitly to the service account on the form.

How to build a Compute client using the Google API Services SDK in Java

I'm trying to build a Compute client based on a key .JSON file. I'm looking at the examples found here but they are outdated and not working anymore.
I can't find any example in the current offical docs here.
Here is what I'm currently trying:
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.InstanceList;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
public class Application {
private static final JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
public static void main(String[] args) throws IOException, GeneralSecurityException {
InputStream credentialsJSON = Application.class.getClassLoader().getResourceAsStream("mykey.json");
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential cred = GoogleCredential.fromStream(credentialsJSON ,httpTransport,JSON_FACTORY);
// Create Compute Engine object for listing instances.
Compute compute = new Compute.Builder(httpTransport, JSON_FACTORY, cred.getRequestInitializer())
.setApplicationName("myapplication")
.build();
InstanceList instanceList = compute.instances().list("PROJECT_NAME", "europe-west3-a").execute();
for (Instance instance : instanceList.getItems()) {
System.out.println(instance.getId());
}
}
}
But it throws the following error:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Login Required.",
"reason" : "required"
} ],
"message" : "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"status" : "UNAUTHENTICATED"
}
I don't understand because the file get's parsed correctly. Also the GoogleCredential model I'm using seems to be deprecated.
You need these two dependencies:
<dependencies>
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-compute</artifactId>
<version>v1-rev20200311-1.30.9</version>
</dependency>
<dependency>
<groupId>com.google.auth</groupId>
<artifactId>google-auth-library-oauth2-http</artifactId>
<version>0.20.0</version>
</dependency>
</dependencies>
The google-auth-library-oauth2-http dependency repository can be found here. Switching to this new method worked for me.
And here's the working code:
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpRequestInitializer;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.ComputeScopes;
import com.google.auth.http.HttpCredentialsAdapter;
import com.google.auth.oauth2.GoogleCredentials;
import java.io.IOException;
import java.io.InputStream;
import java.security.GeneralSecurityException;
public class GCPComputeClientHelper {
private static Compute compute = null;
protected GCPComputeClientHelper() {
// Exists only to defeat instantiation
}
public static Compute getComputeInstance() throws GeneralSecurityException, IOException {
if (compute == null) {
compute = build();
}
return compute;
}
private static Compute build() throws GeneralSecurityException, IOException {
// Create http transporter needed for Compute client
HttpTransport HTTP_TRANSPORTER = GoogleNetHttpTransport.newTrustedTransport();
// Read GCP service account credentials JSON key file
InputStream serviceAccountJsonKey = GCPComputeClientHelper.class.getClassLoader().getResourceAsStream("mykeyfile.json");
// Authenticate based on the JSON key file
GoogleCredentials credentials = GoogleCredentials.fromStream(serviceAccountJsonKey);
credentials = credentials.createScoped(ComputeScopes.CLOUD_PLATFORM);
HttpRequestInitializer requestInitializer = new HttpCredentialsAdapter(credentials);
// Create and return GCP Compute client
return new Compute.Builder(HTTP_TRANSPORTER, JacksonFactory.getDefaultInstance(), requestInitializer)
.setApplicationName("myapplication")
.build();
}
}

Insufficient Permission when run youtube retriving comments

This is my whole code. I want to give a video ID which from youtube to get the comments related to this vedio ID. But always show that I have Insufficient Permission.
I have tried to address this, and found youtube .commentThreads().list("snippet").setVideoId("tLTm_POao1c") .setTextFormat("plainText").execute(); is the problem. Specifically, execute() in this line calls "Insufficient Permission".
Why is this?
package com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.util.List;
import com.google.api.client.util.Preconditions;//aiyamaya
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.java6.auth.oauth2.FileCredentialStore;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.json.GoogleJsonResponseException;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
//import com.google.api.services.youtube.YouTube;
import com.google.api.services.youtube.model.ResourceId;
import com.google.api.services.youtube.model.Subscription;
import com.google.api.services.youtube.model.SubscriptionSnippet;
import com.google.common.collect.Lists;
import com.google.api.services.youtube.model.CommentThreadListResponse;
import com.google.api.services.youtube.model.CommentThread;
import com.google.api.services.youtube.model.CommentSnippet;
import com.google.api.services.youtube.YouTube;
import com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample.Auth;
//import com.google.api.services.samples.youtube.cmdline.Auth;
/**
* Demo of subscribing user to a channel using the YouTube Data API (V3) with
* OAuth2 for authorization.
*
* #author Ibrahim Ulukaya
*/
public class AddSubscription {
/** Global instance of the HTTP transport. */
// private static final HttpTransport HTTP_TRANSPORT = new
// NetHttpTransport();
/** Global instance of the JSON factory. */
// private static final JsonFactory JSON_FACTORY = new JacksonFactory();
/** Global instance of Youtube object to make all API requests. */
private static YouTube youtube;
public static void main(String[] args) {
System.setProperty("proxySet", "true");
System.setProperty("proxyHost", "bproxy.rmit.edu.au");
System.setProperty("proxyPort", "8080");
List<String> scopes = Lists
.newArrayList("https://www.googleapis.com/auth/youtube");
try {
// Authorization.
Credential credential = Auth.authorize(scopes, "commentthreads");
// This object is used to make YouTube Data API requests.
youtube = new YouTube.Builder(Auth.HTTP_TRANSPORT,
Auth.JSON_FACTORY, credential).setApplicationName(
"youtube-cmdline-commentthreads-sample").build();
// YouTube object used to make all API requests.
CommentThreadListResponse videoCommentsListResponse = youtube
.commentThreads().list("snippet").setVideoId("tLTm_POao1c")
.setTextFormat("plainText").execute();
List<CommentThread> videoComments = videoCommentsListResponse
.getItems();
} catch (GoogleJsonResponseException e) {
System.err.println("GoogleJsonResponseException code: "
+ e.getDetails().getCode() + " : "
+ e.getDetails().getMessage());
e.printStackTrace();
} catch (IOException e) {
System.err.println("IOException: " + e.getMessage());
e.printStackTrace();
} catch (Throwable t) {
System.err.println("Throwable: " + t.getMessage());
t.printStackTrace();
}
}
/*
* Returns a channel id (String) from user via the terminal.
*/
}
This is the error information:
May 22, 2015 8:19:15 AM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for everybody: C:\Users\E18300\.oauth-credentials
May 22, 2015 8:19:15 AM com.google.api.client.util.store.FileDataStoreFactory setPermissionsToOwnerOnly
WARNING: unable to change permissions for owner: C:\Users\E18300\.oauth-credentials
2015-05-22 08:19:15.192:INFO::Logging to STDERR via org.mortbay.log.StdErrLog
2015-05-22 08:19:15.193:INFO::jetty-6.1.26
2015-05-22 08:19:15.212:INFO::Started SocketConnector#localhost:8080
2015-05-22 08:19:20.433:INFO::Stopped SocketConnector#localhost:8080
GoogleJsonResponseException code: 403 : Insufficient Permission
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:145)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:113)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:40)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:321)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1045)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at com.google.api.services.samples.youtube.cmdline.youtube_cmdline_addsubscription_sample.AddSubscription.main(AddSubscription.java:86)
The documentation lacks in this part, but you need to use the scope https://www.googleapis.com/auth/youtube.force-ssl to retrieve comments from the YouTube API. Took me way too much time to solve this issue.
var OAUTH2_SCOPES = [
'https://www.googleapis.com/auth/youtube',
'https://www.googleapis.com/auth/youtube.force-ssl'
];
to retrieve comments from the YouTube API add
https://www.googleapis.com/auth/youtube.force-ssl
this into OAUTH2_SCOPES array
As the error message indicates, your request does not have sufficient permissions. If you look at the API Reference Overview you will see:
Every request must either specify an API key (with the key parameter) or provide an OAuth 2.0 token. Your API key is available in the API console's API Access pane for your project.
For example I am able to view the comment thread list for a video by making a GET request to this link in the browser directly:
https://www.googleapis.com/youtube/v3/commentThreads?part=snippet&key=YOUR_KEY&videoId=tLTm_POao1c. You will need to replace YOUR_KEY with your application key that you can find in your Google developer console.
I don't know why the code sample for comment threads does not mention anything about the need to include the API key (probably because it is assumed that you read the API Overview first). But
if you look at this other code sample, you will see that you can include a developer key in a local file that you can load into a Properties object:
// Read the developer key from the properties file.
Properties properties = new Properties();
try {
InputStream in = Search.class.getResourceAsStream("/" + PROPERTIES_FILENAME);
properties.load(in);
} catch (IOException e) {
System.err.println("There was an error reading " + PROPERTIES_FILENAME + ": " + e.getCause()
+ " : " + e.getMessage());
System.exit(1);
}
Further down the line, the api key is extracted from the Properties object and is used in the search API call:
// Set your developer key from the Google Developers Console for
// non-authenticated requests. See:
// https://console.developers.google.com/
String apiKey = properties.getProperty("youtube.apikey");
search.setKey(apiKey);
search.setQ(queryTerm);
In a similar manner, you can call setKey() on your code, as described by the JavaDocs: https://developers.google.com/resources/api-libraries/documentation/youtube/v3/java/latest/com/google/api/services/youtube/YouTube.CommentThreads.List.html#setKey(java.lang.String)
So, you may need to add something like this:
CommentThreadListResponse videoCommentsListResponse = youtube.commentThreads()
.list("snippet")
.setKey(YOUR_KEY)
.setVideoId("tLTm_POao1c")
.setTextFormat("plainText")
.execute();
You don't even need the Properties file, unless you plan to change the API key after you write the code and deploy it.
You only need a key to retrieve comments. Something like this:
String apiUrl = "https://www.googleapis.com/youtube/v3/commentThreads?part=snippet%2Creplies&videoId=" + ytId + "&moderationStatus=published&order=relevance&maxResults=5&key=" + apiKey;
Then handle the Json response.

insert new instance using API of GCE

i write a code to create instance in GCE using java API
but this code does not work i get the following error
403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
my code is posted bellow does it has any error or does it need any library to import please help me
the library that i import are
import com.google.api.client.auth.oauth2.Credential;
import com.google.api.client.extensions.java6.auth.oauth2.AuthorizationCodeInstalledApp;
import com.google.api.client.extensions.jetty.auth.oauth2.LocalServerReceiver;
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleClientSecrets;
import com.google.api.client.googleapis.javanet.GoogleNetHttpTransport;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.client.util.store.DataStoreFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.compute.Compute;
import com.google.api.services.compute.ComputeScopes;
import com.google.api.services.compute.model.Instance;
import com.google.api.services.compute.model.InstanceList;
import com.google.api.services.compute.model.NetworkInterface;
import com.google.api.services.compute.model.Operation;
import com.google.api.services.compute.model.Zone;
import com.google.api.services.compute.model.ZoneList;
private static void createInstance(String projectId, JsonFactory jsonFactory,Compute compute) throws IOException {
Instance instance = new Instance();
instance.setFactory(jsonFactory);
// Select a machine type.
String machine = "https://www.googleapis.com/compute/v1/projects/hindproj/global/machineTypes/n1-standard-1";
instance.setMachineType(machine);
// Get a name from the user.
String name = "v1";
instance.setName(name);
// Use the default network. Could select here if needed.
List<NetworkInterface> networkInterfaces = new ArrayList<NetworkInterface>();
NetworkInterface iface = new NetworkInterface();
iface.setFactory(jsonFactory);
iface.setName("eth0");
iface.setNetwork("https://www.googleapis.com/compute/v1/projects/hindproj/global/networks/default");//( COMPUTE_API + "/projects/" + projectId + "/networks/default");
networkInterfaces.add(iface);
instance.setNetworkInterfaces(networkInterfaces);
// Select a zone.
String zone = "https://www.googleapis.com/compute/v1/projects/hindproj/zones/us-central1-b";
instance.setZone(zone);
Compute.Instances.Insert ins = compute.instances().insert(projectId,zoneName, instance);
// Finally, let's run it.
Operation op = ins.execute();
System.out.println(op.toPrettyString());
System.out.println(instance.toPrettyString());
}
Machine type resources are zonal, not global. Try https://www.googleapis.com/compute/v1/projects/hindproj/zones/us-central1-b/machineTypes/n1-standard-1

BigQuery and OAuth2

I'm trying to access Google BigQuery using Service Account approach. My code is as follows:
private static final HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
GoogleCredential credentials = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(BigqueryScopes.BIGQUERY)
.setServiceAccountPrivateKeyFromP12File(
new File("PATH-TO-privatekey.p12"))
.build();
Bigquery bigquery = Bigquery.builder(HTTP_TRANSPORT, JSON_FACTORY).setHttpRequestInitializer(credentials)
.build();
com.google.api.services.bigquery.Bigquery.Datasets.List datasetRequest = bigquery.datasets().list(
"PROJECT_ID");
DatasetList datasetList = datasetRequest.execute();
if (datasetList.getDatasets() != null) {
java.util.List<Datasets> datasets = datasetList.getDatasets();
System.out.println("Available datasets\n----------------");
for (Datasets dataset : datasets) {
System.out.format("%s\n", dataset.getDatasetReference().getDatasetId());
}
}
But it throws the following exception:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 401 Unauthorized
{
"code" : 401,
"errors" : [ {
"domain" : "global",
"location" : "Authorization",
"locationType" : "header",
"message" : "Authorization required",
"reason" : "required"
} ],
"message" : "Authorization required"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:159)
at com.google.api.client.googleapis.json.GoogleJsonResponseException.execute(GoogleJsonResponseException.java:187)
at com.google.api.client.googleapis.services.GoogleClient.executeUnparsed(GoogleClient.java:115)
at com.google.api.client.http.json.JsonHttpRequest.executeUnparsed(JsonHttpRequest.java:112)
at com.google.api.services.bigquery.Bigquery$Datasets$List.execute(Bigquery.java:979)
The exception is fired on this line:
DatasetList datasetList = datasetRequest.execute();
I'm getting the account ID from Google's API console from the second line on the section that looks like this:
Client ID: XXXXX.apps.googleusercontent.com
Email address: XXXXX#developer.gserviceaccount.com
What am I missing?
Eureka! Both Eric's and Michael's code works well.
The error posted in the question can be reproduced by setting the time on the client machine incorrectly. Fortunately, it can be solved by setting the time on the client machine correctly.
Note: For what it's worth, I synchronized the time on a Windows 7 box using the "Update now" button in the "Internet Time Settings" dialog. I figured that should be pretty idiot-proof... but I guess I beat the system. It corrected the seconds but left the machine off by exactly one minute. The BigQuery call failed after that. It succeeded after I manually changed the time.
Our error handling code in the Java library needs to be improved a bit!
It looks like the signed JWT for requesting an OAuth access token is failing. You can see this by enabling the logs that #MichaelManoochehri mentioned above.
There's only a few things that I think could be causing this failure:
Invalid signature (using the wrong key)
Invalid e-mail address for the service account (I think that's been ruled out)
Invalid date/time stamp used for generating the signed blob (an issue date, and an expiration date)
Invalid scope (I think that's been ruled out)
You should check that your date/time is properly set on your server with the proper timezone -- sync'd to NTP. You can use time.gov to see the official US atomic clock time.
EDIT: The answer I gave below is relevant to using Google App Engine Service Accounts - leaving here for reference.
Double check that you have added your service account address to your project's team page as an owner.
I'd recommend using the AppIdentityCredential class to handle service account auth. Here's a small snippet that demonstrates this, and I'll add additional documentation about this on the BigQuery API developer page.
Also, make sure that you are using the latest version of the Google Java API client (as of today, it's version "v2-rev5-1.5.0-beta" here).
import java.io.IOException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.google.api.client.googleapis.extensions.appengine.auth.oauth2.AppIdentityCredential;
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.http.json.JsonHttpRequest;
import com.google.api.client.http.json.JsonHttpRequestInitializer;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.BigqueryRequest;
#SuppressWarnings("serial")
public class Bigquery_service_accounts_demoServlet<TRANSPORT> extends HttpServlet {
// ENTER YOUR PROJECT ID HERE
private static final String PROJECT_ID = "";
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
private static final String BIGQUERY_SCOPE = "https://www.googleapis.com/auth/bigquery";
AppIdentityCredential credential = new AppIdentityCredential(BIGQUERY_SCOPE);
Bigquery bigquery = Bigquery.builder(TRANSPORT,JSON_FACTORY)
.setHttpRequestInitializer(credential)
.setJsonHttpRequestInitializer(new JsonHttpRequestInitializer() {
public void initialize(JsonHttpRequest request) {
BigqueryRequest bigqueryRequest = (BigqueryRequest) request;
bigqueryRequest.setPrettyPrint(true);
}
}).build();
public void doGet(HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.setContentType("text/plain");
resp.getWriter().println(bigquery.datasets()
.list(PROJECT_ID)
.execute().toString());
}
}
Here is a complete snippet for reference:
import com.google.api.client.http.HttpTransport;
import com.google.api.client.http.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.jackson.JacksonFactory;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.services.bigquery.Bigquery;
import com.google.api.services.bigquery.Bigquery.Datasets;
import com.google.api.services.bigquery.model.DatasetList;
import java.io.File;
import java.io.IOException;
import java.security.GeneralSecurityException;
public class BigQueryJavaServiceAccount {
private static final String SCOPE = "https://www.googleapis.com/auth/bigquery";
private static final HttpTransport TRANSPORT = new NetHttpTransport();
private static final JsonFactory JSON_FACTORY = new JacksonFactory();
public static void main(String[] args) throws IOException, GeneralSecurityException {
GoogleCredential credential = new GoogleCredential.Builder().setTransport(TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("XXXXXXX#developer.gserviceaccount.com")
.setServiceAccountScopes(SCOPE)
.setServiceAccountPrivateKeyFromP12File(new File("my_file.p12"))
.build();
Bigquery bigquery = Bigquery.builder(TRANSPORT, JSON_FACTORY)
.setApplicationName("Google-BigQuery-App/1.0")
.setHttpRequestInitializer(credential).build();
Datasets.List datasetRequest = bigquery.datasets().list("publicdata");
DatasetList datasetList = datasetRequest.execute();
System.out.format("%s\n", datasetList.toPrettyString());
}

Categories