Getting 400 when uploading video with YouTube API - java

When trying to upload a video using YouTube Data API, I get:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
POST https://www.googleapis.com/upload/youtube/v3/videos?part=part&uploadType=resumable
{
"code": 400,
"errors": [
{
"domain": "youtube.part",
"location": "part",
"locationType": "parameter",
"message": "'part'",
"reason": "unknownPart"
}
],
"message": "'part'"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:150)
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.executeUnparsed(AbstractGoogleClientRequest.java:432)
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 YoutubeDataApi.upload(YoutubeDataApi.kt:20)
I'm using the following code to upload:
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.InputStreamContent
import com.google.api.client.json.gson.GsonFactory
import com.google.api.client.util.store.FileDataStoreFactory
import com.google.api.services.youtube.YouTube
import com.google.api.services.youtube.model.Video
import java.io.*
object YoutubeDataApi {
fun upload(mediaFile: File) {
val mediaContent =
InputStreamContent("application/octet-stream", BufferedInputStream(FileInputStream(mediaFile)))
mediaContent.length = mediaFile.length()
service.videos().insert("part", Video(), mediaContent).execute()
}
private val gsonFactory = GsonFactory.getDefaultInstance()
private val httpTransport = GoogleNetHttpTransport.newTrustedTransport()
private val service = YouTube.Builder(httpTransport, gsonFactory, authorize("userId"))
.setApplicationName("uploader")
.build()
private fun authorize(user: String): Credential? {
val clientSecretReader: Reader =
InputStreamReader(this::class.java.getResourceAsStream("/client_secret.json"))
val clientSecrets = GoogleClientSecrets.load(gsonFactory, clientSecretReader)
val fileDataStoreFactory = FileDataStoreFactory(File("."))
val flow = GoogleAuthorizationCodeFlow.Builder(
httpTransport, gsonFactory, clientSecrets,
setOf("https://www.googleapis.com/auth/youtube.upload")
).setCredentialDataStore(fileDataStoreFactory.getDataStore("datastore_tokens"))
.setAccessType("offline")
.build()
val localReceiver = LocalServerReceiver.Builder().setPort(8090).setCallbackPath("/callback").build()
return AuthorizationCodeInstalledApp(flow, localReceiver).authorize(user)
}
}
The code was inspired on the official docs.

The part paramter is a required paramater for the videos.insert method. However the string "part" is not a valid part.
Try something more like:
YouTube.Videos.Insert videoInsert = youtube.videos().insert(
"snippet,statistics,status",
videoObjectDefiningMetadata, mediaContent);
MediaHttpUploader uploader = videoInsert.getMediaHttpUploader();

Related

Reading labels works but reading messages results in ACCESS_TOKEN_SCOPE_INSUFFICIENT

I have created one poc using Gmail API which read all email and print on console. I have take refrence from Gmail api Java quickstart.
I have follows all the steps like create project, Gmail API enable, OAuth credentials in google cloud console
The problem is, when I run the code all the labels are printed successfully but I'm not able to read mail messages. Some an error are getting which are below:
> Task :GmailQuickstart.main()
Labels:
- CHAT
- SENT
- INBOX
- IMPORTANT
- TRASH
- DRAFT
- SPAM
- CATEGORY_FORUMS
- CATEGORY_UPDATES
- CATEGORY_PERSONAL
- CATEGORY_PROMOTIONS
- CATEGORY_SOCIAL
- STARRED
- UNREAD
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
GET https://gmail.googleapis.com/gmail/v1/users/me/messages
{
"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"
}
at com.google.api.client.googleapis.json.GoogleJsonResponseException.from(GoogleJsonResponseException.java:146)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:118)
at com.google.api.client.googleapis.services.json.AbstractGoogleJsonClientRequest.newExceptionOnError(AbstractGoogleJsonClientRequest.java:37)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest$1.interceptResponse(AbstractGoogleClientRequest.java:439)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:1111)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:525)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:466)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:576)
at GmailQuickstart.main(GmailQuickstart.java:80)
> Task :GmailQuickstart.main() FAILED
Execution failed for task ':GmailQuickstart.main()'.
> Process 'command '/home/bhautik/Downloads/jdk-11.0.15.1_linux-x64_bin/data/usr/lib/jvm/jdk-11/bin/java'' finished with non-zero exit value 1
* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.
And my code was below:
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.javanet.NetHttpTransport;
import com.google.api.client.json.JsonFactory;
import com.google.api.client.json.gson.GsonFactory;
import com.google.api.client.util.store.FileDataStoreFactory;
import com.google.api.services.gmail.Gmail;
import com.google.api.services.gmail.GmailScopes;
import com.google.api.services.gmail.model.Label;
import com.google.api.services.gmail.model.ListLabelsResponse;
import com.google.api.services.gmail.model.ListMessagesResponse;
import com.google.api.services.gmail.model.Message;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/* class to demonstrate use of Gmail list labels API */
public class GmailQuickstart {
private static final String APPLICATION_NAME = "Gmail API Java Quickstart";
private static final JsonFactory JSON_FACTORY = GsonFactory.getDefaultInstance();
private static final String TOKENS_DIRECTORY_PATH = "tokens";
private static final List<String> SCOPES = Collections.singletonList(GmailScopes.GMAIL_LABELS);
private static final String CREDENTIALS_FILE_PATH = "/credentials.json";
private static final String USER_ID = "me";
private static Credential getCredentials(final NetHttpTransport HTTP_TRANSPORT)
throws IOException {
// Load client secrets.
InputStream in = GmailQuickstart.class.getResourceAsStream(CREDENTIALS_FILE_PATH);
if (in == null) {
throw new FileNotFoundException("Resource not found: " + CREDENTIALS_FILE_PATH);
}
GoogleClientSecrets clientSecrets =
GoogleClientSecrets.load(JSON_FACTORY, new InputStreamReader(in));
// Build flow and trigger user authorization request.
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT, JSON_FACTORY, clientSecrets, SCOPES)
.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setAccessType("offline")
.build();
LocalServerReceiver receiver = new LocalServerReceiver.Builder().setPort(8888).build();
Credential credential = new AuthorizationCodeInstalledApp(flow, receiver).authorize("user");
//returns an authorized Credential object.
return credential;
}
public static void main(String... args) throws IOException, GeneralSecurityException {
// Build a new authorized API client service.
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
Gmail service = new Gmail.Builder(HTTP_TRANSPORT, JSON_FACTORY, getCredentials(HTTP_TRANSPORT))
.setApplicationName(APPLICATION_NAME)
.build();
// Print the labels in the user's account.
String user = "me";
ListLabelsResponse listResponse = service.users().labels().list(user).execute();
List<Label> labels = listResponse.getLabels();
if (labels.isEmpty()) {
System.out.println("No labels found.");
} else {
System.out.println("Labels:");
for (Label label : labels) {
System.out.printf("- %s\n", label.getName());
}
}
// Print the message
ListMessagesResponse response = service.users().messages().list(USER_ID).execute();
// List<Message> messages = response.getMessages();
List<Message> messages = new ArrayList<Message>();
while (response.getMessages() != null) {
messages.addAll(response.getMessages());
if (response.getNextPageToken() != null) {
String pageToken = response.getNextPageToken();
response = service.users().messages().list(USER_ID).setPageToken(pageToken).execute();
} else {
break;
}
}
for (Message message : messages) {
System.out.println(message.getId());
System.out.println(message.getPayload());
Message test = service.users().messages().get("me", message.getId()).execute();
System.out.println(test.getSnippet());
}
}
}
ACCESS_TOKEN_SCOPE_INSUFFICIENT is a very common error message. It comes from copying the example without understanding what its doing. This is googles fault for not explaining things better.
The quick start uses the lables.list method. This method runs on users private data so you used Oauth2 to request permission of the user to access their data.
The method can run with any of the following permissions being requested
Best practice is to only request the permissions you need. So the code is asking for the GmailScopes.GMAIL_LABELS permission which will only give you access to see the lables
Now to read a users messages the messges.listmethod you need to request permission with one of the following scopes
as you can see the label scope is not there. Thats because you need a higher level of permissions to access this data..
Solution:
Change the scope in your code to request one of the scopes needed for messgaes.list.
Then you need to reauthorize your application. YOu can do this in a few was.
delete the file found in TOKENS_DIRECTORY_PATH
change .authorize("user"); the text passed here to something else.
When you run your app again it should prompt you for authorization again.
I would comment but I have too few rep.
I guess you didn't properly set up the permissions of your access token. The error message suggessts, that you need a specific set of permissions to access the ressource

Java call with MS Graph to get Sharepoint sites returns 500 error

I have some code that will do a query to find all sites using the java ms graph libraries.
IDriveCollectionPage drives = graphClient.drives().buildRequest().get();
ISiteCollectionPage sitesPage = graphClient.sites().buildRequest(). get();
The first line still works, however the second line has suddenly started to fail with the error :
500 : Internal Server Error
Cache-Control : no-cache
client-request-id : 6bc81403-33ca-4aae-84d3-7b711ef12b6b
Content-Type : application/json
Date : Mon, 26 Apr 2021 08:10:34 GMT
request-id : e3004346-4297-4864-9802-cc17b81e875e
Strict-Transport-Security : max-age=31536000
Transfer-Encoding : chunked
Vary : Accept-Encoding
x-ms-ags-diagnostic : {"ServerInfo":{"DataCenter":"UK South","Slice":"E","Ring":"3","ScaleUnit":"000","RoleInstance":"LN2PEPF000039ED"}}
{
"error": {
"code": "generalException",
"message": "An assertion failed while processing this request",
"innerError": {
"code": "assertionFailed",
"date": "2021-04-26T08:10:34",
"request-id": "e3004346-4297-4864-9802-cc17b81e875e",
"client-request-id": "6bc81403-33ca-4aae-84d3-7b711ef12b6b"
}
}
}
Checked that the application registration in Azure has NOT changed.
There are a number of other ms graph calls that sill work, as illustrated by the call to one drive.
************** FULL CODE *************************************************
package com.example.testsharepoint;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.graph.models.extensions.IGraphServiceClient;
import com.microsoft.graph.requests.extensions.GraphServiceClient;
import com.microsoft.graph.requests.extensions.IDriveCollectionPage;
import com.microsoft.graph.requests.extensions.ISiteCollectionPage;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.function.BiConsumer;
#Component
public class SharepointAdapter {
private static final transient Logger log = LoggerFactory.getLogger(SharepointAdapter.class);
private String accessToken = null;
private String clientId = "XXX";
private String clientSecret = "XXX";
private String tenantId = "XXX";
protected final static String authority = "https://login.microsoftonline.com/";
public static final String DefaultScope = "https://graph.microsoft.com/.default";
protected Set<String> scopeSet = new HashSet<String>();
private ConfidentialClientApplication app;
protected IAuthenticationResult result;
private IGraphServiceClient graphClient = null;
private SimpleAuthProvider authProvider = null;
public SharepointAdapter()
{
}
#PostConstruct
public void init() throws Exception {
getUserAccessToken();
}
public void getUserAccessToken() throws Exception {
app = ConfidentialClientApplication.builder(
clientId,
ClientCredentialFactory.createFromSecret(clientSecret))
.authority(authority + tenantId + "/")
.build();
String[] appScopes = DefaultScope.split(",");
CollectionUtils.addAll(scopeSet, appScopes);
ClientCredentialParameters.ClientCredentialParametersBuilder builder = ClientCredentialParameters.builder(scopeSet);
ClientCredentialParameters clientCredentialParam = builder.build();
if ( log.isDebugEnabled())
{
log.debug("{} Getting token...", getLogPrefix());
}
CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
BiConsumer<IAuthenticationResult, Throwable> processAuthResult = (res, ex) -> {
if (ex != null) {
Throwable error = ex.getCause();
if (error != null) {
log.error("{}Error connecting to Microsoft - {}", getLogPrefix(), error.getMessage());
} else {
log.error("{}Error connecting to Microsoft - {}", getLogPrefix(), ex.getMessage());
}
}
};
future.whenCompleteAsync(processAuthResult);
future.join();
result = future.get();
if (result == null) {
throw new Exception("Unable to connect to Microsoft, did not get an authentication token.");
}
if ( log.isTraceEnabled())
{
log.trace("{}: TOKEN: {}", getLogPrefix(), result.accessToken() );
}
String token = result.accessToken();
authProvider = new SimpleAuthProvider(token);
// Build a Graph client
graphClient = GraphServiceClient.builder()
.authenticationProvider(authProvider)
.logger(MSLogger.getLogger())
.buildClient();
IDriveCollectionPage drives = graphClient.drives().buildRequest().get();
ISiteCollectionPage sitesPage = graphClient.sites().buildRequest(). get();
}
protected String getLogPrefix()
{
return "[ Client ID: "+ clientId + "] ";
}
}
Relevant version set:
<java.version>14</java.version>
<spring-cloud.version>Hoxton.SR10</spring-cloud.version>
<springframework.boot.version>2.3.9.RELEASE</springframework.boot.version>
<microsoft-msal4j-version>1.9.1</microsoft-msal4j-version>
<microsoft-graph-version>2.10.0</microsoft-graph-version>
<azure.version>3.2.0</azure.version>
Any help gratefully received.
Thanks in advance
For anyone else who has this issue, found the following change made the call successful:
LinkedList<Option> requestOptions = new LinkedList<Option>();
requestOptions.add(new QueryOption("search", "*"));
ISiteCollectionPage sitesPage = graphClient.sites().buildRequest(requestOptions).get();
Not sure why the old code suddenly stopped working, but this has fixed it.

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();
}
}

How to do a simple Google Cloud Trace request in 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

com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden

I am trying to upload a text file to my Google Drive account. No matter what, I always encounter an com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
Stacktrace:
Exception in thread "main" com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Forbidden",
"reason" : "forbidden"
} ],
"message" : "Forbidden"
}
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.executeUnparsed(AbstractGoogleClientRequest.java:423)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:343)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:460)
at chatterjee.sandeep.javabase.miscellaneous.DriveCommandLine.main(DriveCommandLine.java:69)
Here is line 69 of DriveCommandLine.java
File file = service.files().insert(body, mediaContent).execute();
Complete Code:
import com.google.api.client.googleapis.auth.oauth2.GoogleAuthorizationCodeFlow;
import com.google.api.client.googleapis.auth.oauth2.GoogleCredential;
import com.google.api.client.googleapis.auth.oauth2.GoogleTokenResponse;
import com.google.api.client.http.FileContent;
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.drive.Drive;
import com.google.api.services.drive.DriveScopes;
import com.google.api.services.drive.model.File;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
public class DriveCommandLine {
private static String CLIENT_ID = "CLIENT_ID";
private static String CLIENT_SECRET = "CLIENT_SECRET";
private static String REDIRECT_URI = "REDIRECT_URI";
public static void main(String[] args) throws IOException {
HttpTransport httpTransport = new NetHttpTransport();
JsonFactory jsonFactory = new JacksonFactory();
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
httpTransport, jsonFactory, CLIENT_ID, CLIENT_SECRET,
Arrays.asList(DriveScopes.DRIVE_FILE)).setAccessType("online")
.setApprovalPrompt("auto").build();
String url = flow.newAuthorizationUrl().setRedirectUri(REDIRECT_URI)
.build();
System.out
.println("Please open the following URL in your browser then type the authorization code:");
System.out.println(" " + url);
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String code = br.readLine();
GoogleTokenResponse response = flow.newTokenRequest(code)
.setRedirectUri(REDIRECT_URI).execute();
GoogleCredential credential = new GoogleCredential()
.setFromTokenResponse(response);
// Create a new authorized API client
Drive service = new Drive.Builder(httpTransport, jsonFactory,
credential).build();
// Insert a file
File body = new File();
body.setTitle("My document");
body.setDescription("A test document");
body.setMimeType("text/plain");
java.io.File fileContent = new java.io.File(
"/path/to/TextFile.txt");
FileContent mediaContent = new FileContent("text/plain", fileContent);
File file = service.files().insert(body, mediaContent).execute();
System.out.println("File ID: " + file.getId());
}
}
I have the following jars in my project build path:
commons-logging-1.1.1.jar
google-api-client-1.18.0-rc.jar
google-api-client-android-1.18.0-rc.jar
google-api-client-appengine-1.18.0-rc.jar
google-api-client-gson-1.18.0-rc.jar
google-api-client-jackson2-1.18.0-rc.jar
google-api-client-java6-1.18.0-rc.jar
google-api-client-servlet-1.18.0-rc.jar
google-api-services-drive-v1-rev123-1.18.0-rc.jar
google-http-client-1.18.0-rc.jar
google-http-client-android-1.18.0-rc.jar
google-http-client-appengine-1.18.0-rc.jar
google-http-client-gson-1.18.0-rc.jar
google-http-client-jackson2-1.18.0-rc.jar
google-http-client-jdo-1.18.0-rc.jar
google-oauth-client-1.18.0-rc.jar
google-oauth-client-appengine-1.18.0-rc.jar
google-oauth-client-java6-1.18.0-rc.jar
google-oauth-client-jetty-1.18.0-rc.jar
google-oauth-client-servlet-1.18.0-rc.jar
gson-2.1.jar
httpclient-4.0.3.jar
httpcore-4.0.1_1.jar
jackson-core-2.1.3.jar
jdo2-api-2.3-eb.jar
jetty-util-6.1.26.jar
jsr305-1.3.9.jar
transaction-api-1.1-rev-1.jar
At present I have two projects set up with Drive API enabled.
Now where do I properly set up the permissions to resolve this issue?
Also, what am I doing wrong here?
I had the same issue, I did the following change and it resolved the issue
1) Added SheetsScopes.DRIVE to the scopes to be given in authorize()
private static final List<String> SCOPES =
Arrays.asList(SheetsScopes.SPREADSHEETS,SheetsScopes.DRIVE);
2) Created a new directory, so that next time I run it, it will authenticate and save the credential to the newly created directory
private static final java.io.File DATA_STORE_DIR = new java.io.File(
System.getProperty("user.home"), ".credentials/2/sheets.googleapis.com-java-quickstart.json");
This issue happened when you change SCOPE and proceed to work with the old token. Just remove StoredCredential file.Idea
After a long time searching, I found this answer hidden in the search engine:
Change the line where you define scopes to:
private static final List<String> SCOPES = Arrays.asList(GmailScopes.MAIL_GOOGLE_COM);
https://stackoverflow.com/a/38599382/1317559
I just had this problem and it is likely that you have created the credential file using a scope that does not allow inserting a file. Remove the credential file and re-run.
For me issue was SCOPES, it was set to SheetsScopes.SPREADSHEETS_READONLY.
So I changed it to SheetsScopes.SPREADSHEETS, deleted the Token folder in the project directory and run the program again and it worked.
Been having same quota errors for months. Tried everything. It looks like problem on Google side.
Among all google products, Calendar API does not have any way to support their team. If anyone knows or have been able to contact Google team about Calendar API, let us know!
I had the same problem but in my case resolve this with:
private static final List<String> SCOPES =
Arrays.asList(DriveScopes.DRIVE);
from DriveScopes
and also create a new directory
private static final java.io.File DATA_STORE_DIR = new java.io.File(System.getProperty("user.home"), ".credentials/2/drive-java-quickstart.json");
and i solved the problem
For me the problem was that the url was http... and it should be https...
Make sure to use DriveScopes.DRIVE for allowed SCOPE:
private static final List SCOPES = Collections.singletonList(DriveScopes.DRIVE);
Make sure to reset token directory path as below:
GoogleAuthorizationCodeFlow flow = new GoogleAuthorizationCodeFlow.Builder(
HTTP_TRANSPORT,
JSON_FACTORY, clientSecrets, SCOPES)
//.setDataStoreFactory(new FileDataStoreFactory(new java.io.File(TOKENS_DIRECTORY_PATH)))
.setDataStoreFactory(new MemoryDataStoreFactory())
.setAccessType("offline")
.build();
Othewise it will always use the cached version.

Categories