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
Please enter at least three characters to search
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Zones

Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks

The software you build is only as secure as the code that powers it. Learn how malicious code creeps into your software supply chain.

Apache Cassandra combines the benefits of major NoSQL databases to support data management needs not covered by traditional RDBMS vendors.

Generative AI has transformed nearly every industry. How can you leverage GenAI to improve your productivity and efficiency?

Modernize your data layer. Learn how to design cloud-native database architectures to meet the evolving demands of AI and GenAI workloads.

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

  • Enforcing Architecture With ArchUnit in Java
  • Chat With Your Knowledge Base: A Hands-On Java and LangChain4j Guide
  • Intro to RAG: Foundations of Retrieval Augmented Generation, Part 1
  • How Can Developers Drive Innovation by Combining IoT and AI?

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
Oops! Something Went Wrong

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:

Likes
There are no likes...yet! 👀
Be the first to like this post!
It looks like you're not logged in.
Sign in to see who liked this post!