not able to add meet link to google calendar events in java - java

I am working on a spring boot api which schedules events for me but and its working fine but along with events I want to add a meet link too and I am not able to do that.I am using a service account from cloud console and shared my personal account with this service account.How can I implement google meet?
Here's my code:
Event event = new Event()
.setSummary("Google I/O 2015")
.setLocation("800 Howard St., San Francisco, CA 94103")
.setDescription("A chance to hear more about Google's developer products.");
ConferenceSolutionKey conferenceSKey = new ConferenceSolutionKey();
conferenceSKey.setType("hangoutsMeet");
CreateConferenceRequest createConferenceReq = new CreateConferenceRequest();
createConferenceReq.setRequestId("adojajaod"); // ID generated by you
createConferenceReq.setConferenceSolutionKey(conferenceSKey);
ConferenceData conferenceData = new ConferenceData();
conferenceData.setCreateRequest(createConferenceReq);
System.out.println(conferenceData);
event.setConferenceData(conferenceData);
DateTime startDateTime = new DateTime("2021-08-14T09:00:00-07:00");
EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2021-08-15T17:00:00-07:00");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[]{"RRULE:FREQ=DAILY;COUNT=2"};
event.setRecurrence(Arrays.asList(recurrence));
EventReminder[] reminderOverrides = new EventReminder[]{
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10),
};
Event.Reminders reminders = new Event.Reminders()
.setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
event = client.events().insert("himanshuranjan30#gmail.com", event).setConferenceDataVersion(1).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
Here I am trying to setup a meet link using conference but its not working and giving a error like:
{
"code" : 400,
"errors" : [ {
"domain" : "global",
"message" : "Invalid conference type value.",
"reason" : "invalid"
} ],
"message" : "Invalid conference type value."
}
Any help will be appreciated.

conferenceSKey.setType("hangoutsMeet");
Looks like the calendar where you try to insert the event does not accept the "hangoutsMeet" conference call type.
To verify use get of Calendar API to view your target Calendar metadata.
https://developers.google.com/calendar/api/v3/reference/calendars
You can see the allowed types under,
"conferenceProperties": {
"allowedConferenceSolutionTypes": [
string
]
}

Related

Error while creating google calendar event with a service account

I have a requirement of creating a google calendar event on a calendar and add other users as attendees to that event. The objective is to send calendar events to the application users without taking their consent ( O-Auth ).
After reading Google's documentation, I found out that I need a service account. So I created a project and a service account from one of the email addresses of our G-Suite, noreply#xxxxx.com and enabled calendar API for the same.
I created and downloaded a key pair ( JSON ) whose content is,
{
"type": "service_account",
"project_id": "*****",
"private_key_id": "bdbbcd**************49f77d599f2",
"private_key": "**"
"client_email": "******#*****.iam.gserviceaccount.com",
"client_id": "11083******576856",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/****dev%40*****kdev.iam.gserviceaccount.com"
}
And as per the documentation, I proceded to write authentication flow code,
public static GoogleCredential doOauth( String credsPath ) throws IOException
{
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream(credsPath))
.createScoped(Collections.singleton(CalendarScopes.CALENDAR));
System.out.println(credential);
return credential;
}
The credential object has most of the details from the key file. But, the fields, serviceAccountUser, accessToken, refreshToken, clientAuthentication and requestInitializer have null value. ( I am guessing something wrong here )
Now, using the credentialObject, I continued to write the code as per the documentation to create the event.
GoogleCredential credential = doOauth(CREDENTIALS_FILE_PATH);
Event event = new Event().setSummary("Google I/O 2015").setLocation("800 Howard St., San Francisco, CA 94103")
.setDescription("A chance to hear more about Google's developer products.");
final NetHttpTransport HTTP_TRANSPORT = GoogleNetHttpTransport.newTrustedTransport();
DateTime startDateTime = new DateTime("2020-12-28T09:00:00-07:00");
EventDateTime start = new EventDateTime().setDateTime(startDateTime).setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2020-12-28T17:00:00-07:00");
EventDateTime end = new EventDateTime().setDateTime(endDateTime).setTimeZone("America/Los_Angeles");
event.setEnd(end);
String[] recurrence = new String[] { "RRULE:FREQ=DAILY;COUNT=2" };
event.setRecurrence(Arrays.asList(recurrence));
EventAttendee[] attendees = new EventAttendee[] { new EventAttendee().setEmail("myemailaddress#gmail.com.com") };
event.setAttendees(Arrays.asList(attendees));
EventReminder[] reminderOverrides = new EventReminder[] {
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10), };
Event.Reminders reminders = new Event.Reminders().setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
String calendarId = "primary";
Calendar service = new Calendar.Builder(HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("testapp").build();
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink());
But, this resulted in the error,
{
"code" : 403,
"errors" : [ {
"domain" : "calendar",
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority.",
"reason" : "forbiddenForServiceAccounts"
} ],
"message" : "Service accounts cannot invite attendees without Domain-Wide Delegation of Authority."
}
After spending time on Domain-Wide Delegation, I understood that this is needed if we have to send the event as other user from our g-suite, which is not needed for my problem. But, to debug, I went ahead and provided Domain-Wide Delegation and re ran the program. The same error came again.
So, I removed the invitees/attendees from the event object and re ran the application. This time the program ran without any error, but the event link generated, on click says, Could not find the requested event.
I do not see any examples of using the service account via java client libraries on the google developer link.
Can you please let me know what is going wrong here and the official/working documentation on how exactly to create a google calendar event from my project add other ( non g suite as well ) users to add as attendees, so that I do not have to get consent from other users to add events to their own calendar?
Thank You.
Fist off I want to say that this is something new, if you are seeing a lot of questions, and tutorials that did not state you needed to do this its because service accounts used to be able to send invites, this is something google locked down about a year ago.
This should work but i have not tested it as i no longer have access to a Gsuite account. You need to have the gsuite admin set up domain wide delegation to anther user. Then the service account needs to impersonate that user so it will appear as that user is the one sending the invites.
The only example I have for how that is added is in .net
.net example
var gsuiteUser = "se#clawskeyboard.com";
var serviceAccountCredentialInitializer = new ServiceAccountCredential.Initializer(serviceAccount)
{
User = gsuiteUser,
Scopes = new[] { GmailService.Scope.GmailSend, GmailService.Scope.GmailLabels }
}.FromCertificate(certificate);
Java example guess
I am not a java dev but the .net client library and the Java client library are very close in how they were developed. I would guess that you are looking for a method called setServiceAccountUser
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(CalendarScopes.CALENDAR)
.setServiceAccountPrivateKeyFromP12File(credsPath))
.setServiceAccountUser(gsuiteUser)
.build();
OAuth2 for Service Accounts
You should be able to impersonate the account user by setting the delegated variable to the user's email in the GoogleCredential object.
GoogleCredential credential = GoogleCredential.fromStream(new FileInputStream("credentials.json"))
.createScoped(<SCOPES>)
.createDelegated("user#example.com");

Google calendar event, conference details are not being set

I'm trying to create the Google Calendar event with the conference(Google Meet) using Java SDK V3. The event is getting created but the conference details are not being set. Not sure what's missing
Create request:
Calendar service = new Calendar
.Builder(GoogleNetHttpTransport.newTrustedTransport(),
getDefaultInstance(),
new HttpCredentialsAdapter(googleCalendarCredentials()))
.setApplicationName(APPLICATION_NAME)
.build();
Event event = new Event();
event.setStart(new EventDateTime().setDateTime(new DateTime(currentTimeMillis())));
event.setEnd(new EventDateTime().setDateTime(new DateTime(currentTimeMillis() + 10000000)));
ConferenceData conferenceData = new ConferenceData();
conferenceData.setCreateRequest(
new CreateConferenceRequest()
.setConferenceSolutionKey(
new ConferenceSolutionKey()
.setType("hangoutsMeet")));
event.setConferenceData(conferenceData);
service.events().insert("primary", event).execute();
Get Request:
Events events = service.events()
.list("primary")
.execute();
List<Event> items = events.getItems();
if (items.isEmpty()) {
System.out.println("No upcoming events found.");
} else {
System.out.println("Upcoming events");
for (Event eventRs : items) {
System.out.printf("%s\n", eventRs.getConferenceData().getConferenceId());
}
}
Getting eventRs.getConferenceData() as null.
If you check the documentaiton on Event.insert you will see that you need to set the option parameter conferenceDataVersion inorder to enable it to set the conference data.
Version 0 assumes no conference data support and ignores conference data in the event's body. Version 1 enables support for copying of ConferenceData

get google calendar id from an email address

I'm inserting a new event on Google Calendar using a service account service#entreprise.tn.
I can't specify the organizer or the creator of an event.
My code is:
Organizer organizer = new Organizer().setEmail("user1#entreprise.tn").setSelf(true);
Creator creator = new Creator().setEmail("user1#entreprise.tn").setSelf(true);
Calendar service = Calendar_Utils.getCalendarService();
Event event = new Event()
.setSummary("Google Calendar API")
.setOrganizer(organizer)
.setCreator(creator);
DateTime startDateTime = new DateTime("2020-04-24T09:00:00.000Z");
EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("Africa/Tunis");
event.setStart(start);
DateTime endDateTime = new DateTime("2020-04-24T10:30:00.000Z");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("Africa/Tunis");
event.setEnd(end);
String calendarId = "primary";
event = service.events().insert(calendarId, event).execute();
System.out.printf("Event created: %s\n", event.getHtmlLink() + " - " + event.getOrganizer() + " - " + event.getCreator());
As result, the new event is inserted, but with organizer and creator service#entreprise.tn and not user1#entreprise.tn.
Could you please tell me how can I change my code to set the organizer to user1#entreprise.tn.
Thanks a lot.
When you create an event with the service account, you need to impersonate the user on whose behalf the event shall be created
In Java you would do it as following:
GoogleCredential getCredentials = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(serviceAccount)
.setServiceAccountPrivateKeyFromP12File(pk12)
.setServiceAccountScopes(SCOPES)
.setServiceAccountUser("user1#entreprise.tn")
.build();
Do an events.patch and update the organizer fields on the Event by default the organizer property is set to the person or service account which created the event.
Impersonation
If the service account has been set up with domain wide delegation to a gsuie domain you can impersonate one of the users on the domain and the organizer will be the user who was impersonated.

Google Calendar, Java : Set up google event colour and event date from timestamp

I am working on Google calendar and I would like to set colour for an event and to set event time from java timestamp object I have. Currently I cannot find anywhere which are the possible colors available and the format of colour string.
Below is the code I have with static date and time, and no colour. I tried to use the timestamp, but Google has some weird DateTime object. Also, I am unable to find any default format for colors.
THe basic sample which contains date and time setting are static strings. That's so horrible, what kind of developer uses hardcoded date and time values as example to show how their date time api is. I hope I don't have to deal with such messed up API in future. Sorry for ranting, here is code :
#Override
public Event setUpEventToSave(GroupNotes groupNotes, Person person) {
Event event = new Event();
event.setSummary(groupNotes.getMnotetag());
event.setDescription(groupNotes.getMnotetext());
Event.Creator creator = new Event.Creator();
creator.setDisplayName(person.getFirstName());
creator.setEmail(person.getUsername());
event.setCreator(creator);
event.setDescription(groupNotes.getMnotetext());
// I have color in #colorid in DB, but that didn't work, which is standard
// event.setColorId(groupNotes.getMnotecolor());
event.setSummary(groupNotes.getMnotetext());
event.setLocation("Hamburg");
// How can i pass java timestamp below with system time zone?
DateTime startDateTime = new DateTime("2015-08-07T09:00:00-07:00");
EventDateTime start = new EventDateTime()
.setDateTime(startDateTime)
.setTimeZone("America/Los_Angeles");
event.setStart(start);
DateTime endDateTime = new DateTime("2015-08-07T17:00:00-07:00");
EventDateTime end = new EventDateTime()
.setDateTime(endDateTime)
.setTimeZone("America/Los_Angeles");
event.setEnd(end);
/* EventAttendee[] attendees = new EventAttendee[] {
new EventAttendee().setEmail("lpage#example.com"),
new EventAttendee().setEmail("sbrin#example.com"),
};
event.setAttendees(Arrays.asList(attendees));
*/
EventReminder[] reminderOverrides = new EventReminder[] {
new EventReminder().setMethod("email").setMinutes(24 * 60),
new EventReminder().setMethod("popup").setMinutes(10),
};
Event.Reminders reminders = new Event.Reminders()
.setUseDefault(false)
.setOverrides(Arrays.asList(reminderOverrides));
event.setReminders(reminders);
return event;
}
Any help would be nice. Thanks a lot. :-)
You can check all the possible colors in colors endpoint. Here is the sample response:
"event": {
"1": {
"background": "#a4bdfc",
"foreground": "#1d1d1d"
},
"2": {
"background": "#7ae7bf",
"foreground": "#1d1d1d"
},
"3": {
"background": "#dbadff",
"foreground": "#1d1d1d"
},
"4": {
"background": "#ff887c",
"foreground": "#1d1d1d"
},
While inserting event, using event.insert, you can specify colorId. ColorId should be the one which is in colors.get response. You should give value as colorId="1" which takes value as below:
"1": {
"background": "#a4bdfc",
"foreground": "#1d1d1d"
},
Let me know if you still have issues. Also, check calendarList.update

Java Google Calendar api "access_denied" on Service Account

I'm trying to connect to a calendar using the Java Google Calendar api. The java application uses a service account.
I've the following code:
java.io.File licenseFile = new java.io.File("39790cb51b361f51cab6940d165c6cda4dc60177-privatekey.p12");
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("xxx#developer.gserviceaccount.com")
.setServiceAccountUser(EMAIL_ADRESS)
.setServiceAccountScopes(CalendarScopes.CALENDAR)
.setServiceAccountPrivateKeyFromP12File(licenseFile)
.build();
client = new com.google.api.services.calendar.Calendar.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("Google Calendar Sync").build();
Calendar calendar = client.calendars().get(EMAIL_ADRESS).execute();
On the last line I get an IOException with the message:
ex = (com.google.api.client.auth.oauth2.TokenResponseException)
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad
Request { "error" : "access_denied" }
I dubble checked the values for the GoogleCredential object and they are correct.
I've also added https://www.google.com/calendar/feeds/, http://www.google.com/calendar/feeds/ in my domain console with the application id as client to authorize third party application access
Am I forgetting a step?
The api isn't finished yet. More specifically the service account part.
The calendar owner needs to give permission to the application to read/write the calendar in it's calendar settings. It's found in the sharing settings of the calendar, there you can add e-mail adresses of accounts and give them permission on your calendar.
So in this case I had to add: xxx#developer.gserviceaccount.com to the permission/share list of the calendars the application needed access to.
I also deleted another post that didn't full work because of the issue above. I'll undelete it since it contains some code fragments that may help other people in the future. But beaware of the permission issues and service accounts not supporting Google Calendar
I do:
List find = client.events().list(EMAIL_ADRESS);
DateTime timeMin = new DateTime(DateUtil.stringToDate("01/01/2013"));
DateTime timeMax = new DateTime(DateUtil.stringToDate("01/02/2013"));
find.setTimeMin(timeMin);
find.setTimeMax(timeMax);
try{
Events events = find.execute();
int i =0;
while (true) {
System.out.println("Page: "+(++i)+": "+events.getItems().size());
for (Event event : events.getItems()) {
System.out.println(event.getSummary());
}
String pageToken = events.getNextPageToken();
if (pageToken != null && !pageToken.isEmpty()) {
events = client.events().list(EMAIL_ADRESS).setPageToken(pageToken).execute();
} else {
break;
}
}
}catch(GoogleJsonResponseException e){
System.out.println(e.getMessage());
// e.printStackTrace();
}
I got it to work
I don't know why but I deleted the line
.setServiceAccountUser(EMAIL_ADRESS)
Also I added an extra url in the domain scope:
https://apps-apis.google.com/a/feeds/calendar/resource/#readonly
and deleted a link that wasn't working.
Finally I changed the applicationName in my client declaration to the same name as in the api console
client = new com.google.api.services.calendar.Calendar.Builder(
HTTP_TRANSPORT, JSON_FACTORY, credential)
.setApplicationName("HolidaySyncs").build();
After these steps it started to work.
Also note for future reference after I did this I had the following error:
{
"error": {
"errors": [
{
"domain": "global",
"reason": "notFound",
"message": "Not Found"
}
],
"code": 404,
"message": "Not Found"
}
}
I solved this by changing for example:
Event result = client.events().insert(<EMAIL ADRESS>, event).execute();
to
Event result = client.events().insert("primary", event).execute();
First I tought there was something wrong with the google servers, but apparently it goes wrong when you try to link to a calendar ID. So linking to "primary" which is the primary calendar of an account works. But according to the documentation it should also work when you refer to a specific calendar ID, where the email address is the primary calendar. Probably a bug?
UPDATE: after these code correction I still had issues. Read the accepted answer for more information.

Categories