DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Knowledge Graph Embeddings and NLP Innovations
  • Blue Skies Ahead: An AI Case Study on LLM Use for a Graph Theory Related Application
  • Graph API for Entra ID (Azure AD) Object Management
  • Building Neural Networks With Automatic Differentiation

Trending

  • AWS to Azure Migration: A Cloudy Journey of Challenges and Triumphs
  • Infrastructure as Code (IaC) Beyond the Basics
  • Unlocking AI Coding Assistants: Generate Unit Tests
  • MySQL to PostgreSQL Database Migration: A Practical Case Study

Commonly Occurring Errors in Microsoft Graph Integrations and How to Troubleshoot Them (Part 2)

This second article documents common integration errors that may be seen for Microsoft Graph integrations into business apps.

By 
Constantin Kwiatkowski user avatar
Constantin Kwiatkowski
·
Nov. 14, 22 · Tutorial
Likes (2)
Comment
Save
Tweet
Share
4.2K Views

Join the DZone community and get the full member experience.

Join For Free

Due to the switch from EWS to MS Graph, various companies have to adapt their digital products. In the first article, I have already covered a few issues you may face during such a transition to the Microsoft Graph REST API v1.0 with the MS Graph Java SDK. So, let's dive right into the following use cases. 

Read All Available Rooms and Room Lists of the Company (Getting Multiple Room Lists Is Not Possible)

In many companies, rooms can be booked automatically when an Outlook appointment is created. This is possible because all rooms are assigned to an email address by the administration. By adding the email address of the resource to the attendees of the event, a booking process is automatically triggered, which checks if the room is available or not. There is also the option to create room lists, which also have their own email address. For this reason, we can start the availability check for multiple rooms at the same time. For instance, a room list can stand for a building.
In case your business app has to get all rooms or room lists for a tenant. With the Microsoft Graph REST API v1.0, this can be done by using the Places API. The following example shows how to create a GET request in Java to read all rooms of a tenant (HTTP: GET /places/microsoft.graph.room):

Java
 
GraphService service = getGraphService();
 
//load available rooms for one tenant 

String  extendedUrl = service.getGraphServiceClient()  
    .places() 
    .getRequestUrlWithAdditionalParameter("microsoft.graph.room");

 RoomList roomList = new RoomListRequestBuilder(extendedUrl,service.getGraphServiceClient(),null)
	.buildRequest()
	.get(); 

In this example, we create a URL with the specific attachment "microsoft.graph.room" in the first place that is used to tell the API we want a list of all rooms of the tenant. Then we use the request builder to build and send the request. 

According to the Microsoft documentation, room lists can also be read (HTTP: GET /places/microsoft.graph.roomlist). Instead of using the parameter value "microsoft.graph.room", we must use the parameter "microsoft.graph.roomlist". Applied to the example above, the extended URL would look as fellow: 

Java
 
String  extendedUrl = service.getGraphServiceClient()  
    .places() 
    .getRequestUrlWithAdditionalParameter("microsoft.graph.roomlist");
 

However, the Microsoft documentation shows clearly that reading out multiple room lists is not possible via the Microsoft Graph Java SDK. If you check the SDK itself, there is no matching request builder to create the appropriate request. Although the documentation also shows for other technologies like GO, PowerShell, or PHP, this room list option is available; the documentation emphasizes all implementations are still under test and should not be used in production. 

The bottom line is in the current version of Microsoft Graph REST API v1.0, all rooms must always be read, although you only need a subset of certain rooms.

Read Instances of Recurring Events Without an End Date

There are different types of appointments. Basically, appointments can be divided into single and serial appointments. In Office365, a series appointment has the following structure. There is one calendar event for the whole series. In addition to that, there is a calendar event for each instance. In EWS, the event of the first instance is also the series event for the whole series. If you look at the following example of a series event, read via MS Graph:

Java
 
{
  "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('dfb7498b-0c85-4386-bfe7-eddssbdd45390ea5')/events/$entity",
  "@odata.etag": "W/\"1+bFCkpFZUSj6sPne4wWRgAAjrcaBg==\"",
  "id": "AAMkADg4ZTk4NTQ5LTEyMWYtNDg5OSDFSSC1hZjcxLWMzZThhZGIwOTE0ZQBGAAAAAACeiB2A59PoRKo3vfjfoBEBBwDX5sUKSkVlRKPqw_d7jBZGAAAAAAENAADX5sUKSkVlRKPqw_d7jBZGAABuo5X8AAA=",
  "createdDateTime": "2022-09-22T04:35:05.4543959Z",
  "lastModifiedDateTime": "2022-09-22T04:37:06.4192553Z",
  "changeKey": "1+bFCkpFZUSj6sPne4wWRgAAjrcssfaBg==",
  "categories": [
    
  ],
  "transactionId": null,
  "originalStartTimeZone": "W. Europe Standard Time",
  "originalEndTimeZone": "W. Europe Standard Time",
  "iCalUId": "040000008200E00074C5B7101A82E0080000000020D324248C44DCED8010000000000000000100000001FA3A5B1E378134990BBA3383A6A7674",
  "reminderMinutesBeforeStart": 15,
  "isReminderOn": true,
  "hasAttachments": false,
  "subject": "title 1",
  "bodyPreview": "",
  "importance": "normal",
  "sensitivity": "normal",
  "isAllDay": false,
  "isCancelled": false,
  "isOrganizer": true,
  "responseRequested": true,
  "seriesMasterId": null,
  "showAs": "busy",
  "type": "seriesMaster",
  "webLink": "https://outlook.office365.com/owa/?itemid=AAMkADg4ZTk4ADFFSSFFNTQ5LTEyMWYtNDg5OC1hZjcxLWMzZThhZGIwOTE0ZQBGAAAAAACeiB2A59PoRKo3vfjfoBEBBwDX5sUKSkVlRKPqw%2Bd7jBZGAAAAAAENAADX5sUKSkVlRKPqw%2Bd7jBZGAABuo5X8AAA%3D&exvsurl=1&path=/calendar/item",
  "onlineMeetingUrl": null,
  "isOnlineMeeting": false,
  "onlineMeetingProvider": "unknown",
  "allowNewTimeProposals": true,
  "isDraft": false,
  "hideAttendees": false,
  "onlineMeeting": null,
  "responseStatus": {
    "response": "none",
    "time": "0001-01-01T00:00:00Z"
  },
  "body": {
    "contentType": "html",
    "content": "<html><head><meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"><meta name=\"ProgId\" content=\"Word.Document\"><meta name=\"Generator\" content=\"Microsoft Word 15\"><meta name=\"Originator\" content=\"Microsoft Word 15\"><style><!--@font-face{font-family:\"Cambria Math\"}@font-face{font-family:Calibri}p.MsoNormal, li.MsoNormal, div.MsoNormal{margin:0cm;font-size:11.0pt;font-family:\"Calibri\",sans-serif}a:link, span.MsoHyperlink{color:#0563C1;text-decoration:underline}a:visited, span.MsoHyperlinkFollowed{color:#954F72;text-decoration:underline}span.EmailStyle17{font-family:\"Calibri\",sans-serif;color:windowtext}.MsoChpDefault{font-family:\"Calibri\",sans-serif}@page WordSection1{margin:70.85pt 70.85pt 2.0cm 70.85pt}div.WordSection1{}--></style></head><body lang=\"DE\" link=\"#0563C1\" vlink=\"#954F72\" style=\"word-wrap:break-word\"><div class=\"WordSection1\"><p class=\"MsoNormal\"> </p></div></body></html>"
  },
  "start": {
    "dateTime": "2022-09-23T12:30:00.0000000",
    "timeZone": "UTC"
  },
  "end": {
    "dateTime": "2022-09-23T13:00:00.0000000",
    "timeZone": "UTC"
  },
  "location": {
    "displayName": "",
    "locationType": "default",
    "uniqueIdType": "unknown",
    "address": {
      
    },
    "coordinates": {
      
    }
  },
  "locations": [
    
  ],
  "recurrence": {
    "pattern": {
      "type": "daily",
      "interval": 1,
      "month": 0,
      "dayOfMonth": 0,
      "firstDayOfWeek": "sunday",
      "index": "first"
    },
    "range": {
      "type": "noEnd",
      "startDate": "2022-09-23",
      "endDate": "0001-01-01",
      "recurrenceTimeZone": "W. Europe Standard Time",
      "numberOfOccurrences": 0
    }
  ]
  }
}

An example is the series event for a series of events where the dates repeat daily, and the series has no end. For series that do not have a specific end date, Office365 still defines a value for the end date each time: "endDate": "0001-01-01". The value is the same for all series without an end date.

The only way to read all instances of a series with Microsoft Graph REST API v1.0 is with the Instance API. For the above example, the call would look like this:

Java
 
email = "userEmail";
eventID = "ID of the series event";
startDate = "2022-09-23";
endDate = "0001-01-01";
GraphService service = getService(); 

LinkedList<Option> requestOptions = new LinkedList<>();   
requestOptions.add(new HeaderOption("Prefer", "outlook.body-content-type=\"text\"")); 
requestOptions.add(new QueryOption("startDateTime", startDate));    
requestOptions.add(new QueryOption("endDateTime", endDate));

List<Event> instances = service
	.getGraphServiceClient()
	.users(email)
    .events(eventID)
    .instances()  
    .buildRequest(requestOptions)
    .expand("attachments")     
    .get()        
    .getCurrentPage();

The example shows that a start date and an end date must be defined for the request. The problem here, the end date is before the start date, so the request will not be successful. How can we get the instances of the series now?

Assuming we have the use case, if the end date is equal to or lower than the start date, then the business app should read the next 30 events. Using the information from the recurrence pattern (recurrencePatternType and start date), we can define the end date we will use for the request via the Instance API.

Assuming we have the use case, if the end date is equal to or lower than the start date, then the business app should get all events for the next 100 days. In this case, we can easily define an update method:

Java
 
String update(String numberOfDays, String startDate, String endDate) {     	
	
	if(LocalDate.parse(endDate).isBefore(LocalDate.parse(startDate)) || 
		LocalDate.parse(endDate).isEqual(LocalDate.parse(startDate))){ 
	     LocalDate newEndDate = LocalDate.parse(startDate).plusDays(Long.valueOf(numberOfDays));  
		 endDate = newEndDate.toString(); 
    }
    return endDate;
}

We just add the number of days and return the new end date we may use for the request via the Instance API. 

Overall, it makes sense to restrict the time interval for series without an end date; otherwise, you would get all events from the future at once, and the payload would be too big to transfer. So, there are two possible ways to define the end date: you define the new date with regard to the number of events you want to get, or you define the new date with regard to a specific number of days.

Determine the ID of the Last Generated Appointment of a User

Sometimes it is important to determine the ID of the last generated event for a user by the use of a customized query. Let's consider the following instance of the MS Graph Java SDK:

Java
 
final List<Option> options = new LinkedList<>();
options.add(new QueryOption("top", "1"));
String primerID = "test@mail.com";

Event event = graphClient
                .users(primerID)
                .events()
                .buildRequest(options)
                .select("id")
                .get()
                .getCurrentPage();

In this sample, graphClientis the local MS Graph client, and primerIDis the user's email address. With the client and two parameters, we create the following query: 

HTML
 
GET https://graph.microsoft.com/user/<primerID>/events?top=1&$select=id

In this query, https://graph.microsoft.com is the base URL, primerID is the user's primary email address, and top and select are query parameters. How does this query work? The Events API without query parameter returns a list of all events which belong to the user. The query parameter top filters the list and reduces the list to the first entry. The second parameter select causes only the property id of the event to have a value. A possible response might be as follows:

JSON
 
{
    "@odata.context": "https://graph.microsoft.com/v1.0/$metadata#users('dfb7498b-0c85-4386-bfe7-ebdd45390ea5')/events(id)",
    "@odata.nextLink": "https://graph.microsoft.com/v1.0/me/events?$select=id&top=1&$skip=1",
    "value": [
        {
            "@odata.etag": "W/\"1+bFCkpFZUSj6sPne4wWRgAAnu59UQ==\"",
            "id": "AAMkADg4ZTk4NTQ5LTEyMWYtNDg5OC1hZjcxLWMzZThhZGIwOTE0ZQBGAAAAAACeiB2A59PoRKo3vfjfoBEBBwDX5sUKSkVlRKPqw_d7jBZGAAAAAAENAADX5sUKSkVlRKPqw_d7jBZGAABuo5YAAAA="
        }
    ]
}


Graph (Unix)

Opinions expressed by DZone contributors are their own.

Related

  • Knowledge Graph Embeddings and NLP Innovations
  • Blue Skies Ahead: An AI Case Study on LLM Use for a Graph Theory Related Application
  • Graph API for Entra ID (Azure AD) Object Management
  • Building Neural Networks With Automatic Differentiation

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • support@dzone.com

Let's be friends: