I am trying to write a value to a cell with Google Sheet API with Java.
For reading I used guide from Java Quickstart which worked fine for me.
For writing to Google Sheet I use:
service.spreadsheets().values().update(spreadsheetId, "Sheet1!A4:H", response).execute();
This function outputs the following error while run:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Request had insufficient authentication scopes.",
"reason" : "forbidden"
} ],
"message" : "Request had insufficient authentication scopes.",
"status" : "PERMISSION_DENIED"
}
As a Authentication Scope I am using
private static final List<String> SCOPES = Arrays.asList(SheetsScopes.SPREADSHEETS);
Apparently there were several issues together:
Delete credentials that were stored at /Users/XXX/.credentials.
Change Scopes to SheetsScopes.SPREADSHEETS.
Google Sheet Share and Edit options at on Sheet itself.
Now it works!
Thank you guys for help
I was having the same issue. I resolved the problem that was in the scope.
I just changed
SheetsScopes.SPREADSHEETS.READONLY
To
SheetsScopes.SPREADSHEETS
And it works very well.
The Java API must be used in an interactive way, if you're running this on a server that can't pop up a web-browser (which will let you approve an OAuth dialog), then the authentication flow doesn't get proper credentials and won't work.
While running this, do you see a browser pop up to approve an OAuth dialog? If not, you're likely running in a headless session and will need some other means to get the user's credentials.
Try replacing "Sheet1!A4:H" with A4:H
Related
I'm trying to create a Google Vault Export containing all messages in a Chat Space by querying for a specific Chat Space ID. Unfortunately, creating an export for the following query:
newQuery
.setDataScope("ALL_DATA")
.setCorpus("HANGOUTS_CHAT")
.setStartTime(startDate)
.setEndTime(endDate)
.setSearchMethod("ROOM")
.setHangoutsChatOptions(new HangoutsChatOptions().setIncludeRooms(false))
.setHangoutsChatInfo(new HangoutsChatInfo().setRoomId(spaceId));
produces the following error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 400 Bad Request
POST https://vault.googleapis.com/v1/matters/<matterID>/exports
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Search method ROOM is not supported for corpus type HANGOUTS_CHAT.",
"reason" : "badRequest"
} ],
"message" : "Search method ROOM is not supported for corpus type HANGOUTS_CHAT.",
"status" : "INVALID_ARGUMENT"
}
CorpusType needs to be set to "HANGOUTS_CHAT" in order to search in the Google Chat Service. The API also mentions that a HangoutsChatInfo() object needs to be passed when the search method is "ROOM" (https://developers.google.com/vault/reference/rest/v1/Query#SearchMethod).
Am I missing something or is this a bug? Does anyone know a workaround for this issue, if what I want to accomplish is not possible?
It seems that is intended behavior as per current design of the API since you will need to provide the corresponding RoomId and it's not possible at the moment.
Someone had a similar problem before and it ended up in a feature request, you can check it here: https://issuetracker.google.com/189250955
I follow the https://cloud.google.com/translate/docs/reference/libraries#client-libraries-usage-java to get started java client demo.
I have already set authentication json file to the environment variable GOOGLE_APPLICATION_CREDENTIALS. However, I got the translateException when I run java sample code.
Exception in thread "main" com.google.cloud.translate.TranslateException: The request is missing a valid API key.
at com.google.cloud.translate.spi.v2.HttpTranslateRpc.translate(HttpTranslateRpc.java:61)
at com.google.cloud.translate.spi.v2.HttpTranslateRpc.translate(HttpTranslateRpc.java:144)
at com.google.cloud.translate.TranslateImpl$4.call(TranslateImpl.java:113)
at com.google.cloud.translate.TranslateImpl$4.call(TranslateImpl.java:110)
Caused by:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403
Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "The request is missing a valid API key.",
"reason" : "forbidden"
} ],
"message" : "The request is missing a valid API key.",
"status" : "PERMISSION_DENIED"
}
The doc shows that this JSON file contains key infomation.
The sample code is shown
// Instantiates a client
Translate translate = TranslateOptions.getDefaultInstance().getService();
// The text to translate
String text = "Hello, world!";
// Translates some text into Russian
Translation translation =
translate.translate(
text,
TranslateOption.sourceLanguage("en"),
TranslateOption.targetLanguage("ru"));
System.out.printf("Text: %s%n", text);
System.out.printf("Translation: %s%n", translation.getTranslatedText());
I have no idea how to set api-key.
It still doesn't work after I set environment variable for key and credentials.
you can try to authenticating by your service acount json file like below
its pretty simple in node
// Instantiates a client
const translate = new Translate(
{
projectId: 'your project id', //eg my-project-0o0o0o0o'
keyFilename: 'path of your service acount json file' //eg my-project-0fwewexyz.json
}
);
you can take the reference https://cloud.google.com/bigquery/docs/authentication/service-account-file for java
To make authenticated requests to Google Translation, you must create a service object with credentials or use an API key. The simplest way to authenticate is to use Application Default Credentials. These credentials are automatically inferred from your environment, so you only need the following code to create your service object:
Translate translate = TranslateOptions.getDefaultInstance().getService();
I have personally never gotten that to work.
This code can be also used with an API key. By default, an API key is looked for in the GOOGLE_API_KEY environment variable. Once the API key is set, you can make API calls by invoking methods on the Translation service created via TranslateOptions.getDefaultInstance().getService().
Sample project here
I was able to get google translate to work by running
"gcloud auth application-default login"
on the command prompt. This regenerated the credentials to the default location after asking you to authorize with your google account. See https://github.com/GoogleCloudPlatform/google-cloud-java/tree/master/google-cloud-translate for more details.
Add
System.setProperty("GOOGLE_API_KEY", "your key here");
before
Translate translate = TranslateOptions.getDefaultInstance().getService();
Cheers :)
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Requests from this Android client application <empty> are blocked.",
"reason" : "forbidden"
} ],
"message" : "Requests from this Android client application <empty> are blocked.",
"status" : "PERMISSION_DENIED"
}
Following Approach I follow in android to resolve it. I tried with Private key but did not work for me. so I use public key for this
System.setProperty("GOOGLE_API_KEY", "Public key");
val translate = TranslateOptions.getDefaultInstance().service
translate?.let {
val translation = it.translate("Hola Mundo!",
Translate.TranslateOption.sourceLanguage("es"),
Translate.TranslateOption.targetLanguage("en"),
Translate.TranslateOption.model("nmt"));
val check = translation.translatedText
Log.e("inf",""+check)
}
I'm trying to create an app that copies and deletes existing spreadsheets. I've set up the DriveQuickstart from https://developers.google.com/drive/v2/web/quickstart/java
The error that I'm getting now is saying that I do not have sufficient permissions to access that, even after I click the "Allow" button that comes up on my browser after I run the sample.
My code is exactly the same as on the quickstart link.
I'm getting this stacktrace:
Exception in thread "main" 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:1056)
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 DriveQuickstart.main(DriveQuickstart.java:110)
To build on adjuremods response, this is what worked for me:
1) Change this line:
private static final List<String> SCOPES =
Arrays.asList(DriveScopes.DRIVE_METADATA_READONLY);
to:
private static final java.util.Collection<String> SCOPES =
DriveScopes.all();
2) Delete your existing stored credentials so that it will fetch them again, and reexecute your program:
rm ~/.credentials/drive-java-quickstart/StoredCredential
Note: you want an OAuth Client ID called client_secret.json file, not the client_id.json file (I think - that's what worked for me anyway).
Since you're using the exact code form the QuickStart, it may have something to do with the scope set, its currently set as DriveScopes.DRIVE_METADATA_READONLY, which if you check out its meaning in the Choose Auth Scopes page, it states
Allows read-only access to file metadata, but does not allow any access to read or download file content
You can look at the cited page to know what scope it is you'll exactly use. Its most likely going to be https://www.googleapis.com/auth/drive, so check out the DriveScopes class for the constant of the same nature.
I have an application set up to access the Google Classroom API. I have it authorized and can pull Course and Roster data. It's updated to use the V1 calls, but when I add in the Profile.Name and Profile.Email scopes, I get the following error:
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Unregistered request was blocked. Please sign up using Google Developers Console.",
"reason" : "forbidden"
} ],
"message" : "Unregistered request was blocked. Please sign up using Google Developers Console.",
"status" : "PERMISSION_DENIED"
}
The service account has been authorized in the admin console with all 4 relevant Classroom scopes. The Domain has also been confirmed as having the Classroom APIs enabled, if I attempt to use them through the OAuth playground it all works fine.
Any ideas as to why I'm getting the error only when I add in the profile scopes?
The issue was that we were required to fill in a second form for Google to authorize the domain, we'd only found the first one. After filling in the new form, it all started working.
I got a problem on getting the post of user on google plus. I only have the access token and refresh token of this user ( not the ID !), how could i get the post from google plus of this user ?, i do searching a lot, but none of them meets my circumstance. When the user provide his google plus Id on the front end side, the access token and refresh token were generated and stored in database, i, on the backend side, will use these tokens to retrieve the post of this user.
p/s: I use this library https://code.google.com/p/google-plus-java-api/ because it looks so simple, i don't want to use so complicated library just for getting the post, thanks you guy a lot
here is my code
import com.googlecode.googleplus.GooglePlusFactory;
import com.googlecode.googleplus.Plus;
import com.googlecode.googleplus.model.activity.ActivityCollection;
import com.googlecode.googleplus.model.activity.ActivityFeed;
public void getInfo(String accessToken, String refreshToken) {
GooglePlusFactory factory = new GooglePlusFactory(clientId, clientSecret);
Plus plus = factory.getApi(accessToken, refreshToken,null);
if (plus != null) {
ActivityFeed af = plus.getActivityOperations().list("me",ActivityCollection.PUBLIC);
String firstpost = af.getItems().get(0).getObject().getContent();
}
, i got 403 error when call this method, the error output was :
403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "usageLimits",
"message" : "Daily Limit Exceeded. Please sign up",
"reason" : "dailyLimitExceededUnreg",
"extendedHelp" : "https://code.google.com/apis/console"
} ],
"message" : "Daily Limit Exceeded. Please sign up"
}
Actually, i think the reason is not because daily limit exceeded, because i got that message at the first time i run, i also turn the google+ api, google+ domain api on google api console. I suppose the error come from using the "me" in the "list" method to retrieve the post. I still dont' have any idea how to fix this problem
Updated #1#:
I have change my code a lot, so here is exactly what i stuck at, i already get a new accessToken, and (when it is still not expired) , i run this code below:
GoogleCredential credential = new GoogleCredential.Builder()
.setJsonFactory(JSON_FACTORY)
.setTransport(TRANSPORT)
.setClientSecrets(CLIENT_ID, CLIENT_SECRET).build().setAccessToken(newAccessToken);
// Create a new authorized API client.
Plus service = new Plus.Builder(TRANSPORT, JSON_FACTORY, credential)
.setApplicationName(APPLICATION_NAME)
.build();
// Get a list of people that this user has shared with this app.
ActivityFeed feed = service.activities().list("me", "public").execute()
then i got this error:
com.google.api.client.googleapis.json.GoogleJsonResponseException: 403 Forbidden
{
"code" : 403,
"errors" : [ {
"domain" : "global",
"message" : "Insufficient Permission",
"reason" : "insufficientPermissions"
} ],
"message" : "Insufficient Permission"
}
Using "me" as the ID for the list call should work correctly, and your code generally appears correct.
The error message suggests that your client is unregistered. I would check to make sure of the following:
Make sure you have created a Client ID and Secret (and don't post them here!) for your project and you're passing them to the GooglePlusFactory correctly.
Make sure this project has the Google+ API turned on.
Make sure that the access token you're providing for the user corresponds to them authenticating to this same project
I solved this problem, everything is fine except 1 thing, that's is the access token and refresh token was created by some scopes but not the scopes Plus.me, that why's i can't request a new access token by using this refresh token, and then i got the insufficient permission error 403. So when i get the new access and refresh token by using the approriated scope, i can query with keyword "me". Hope you guy don't stuck like me, it takes me nearly 2 days to figure it out