{"id":496,"date":"2020-09-15T10:00:03","date_gmt":"2020-09-15T17:00:03","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=496"},"modified":"2020-09-15T15:18:52","modified_gmt":"2020-09-15T22:18:52","slug":"event-grid-client-libraries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/event-grid-client-libraries\/","title":{"rendered":"Introducing the new Azure Event Grid Client Libraries with CloudEvents v1.0 Support"},"content":{"rendered":"<p>For those looking to build applications with event-based architectures, <a href=\"https:\/\/docs.microsoft.com\/azure\/event-grid\/overview\">Azure Event Grid<\/a> is a cloud-based service that provides reliable event delivery at a massive scale, insulating users from infrastructure concerns. The service fully manages all routing of events from any source, to any destination, for any application. Azure service events and custom events can be published directly to the service, where the events can then be filtered and sent to various recipients, such as built-in handlers or custom webhooks. These features help vastly improve serverless, ops automation, and integration work (for more information, read <a href=\"https:\/\/docs.microsoft.com\/azure\/event-grid\/overview#what-can-i-do-with-event-grid\">What can I do with Event Grid?<\/a>). Included below is an image that demonstrates how Event Grid connects to various event sources and handlers.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2020\/09\/20200915-functional-model.png\" alt=\"Event Grid Functional Model\" \/><\/p>\n<p>We are excited to announce the release of the new Azure Event Grid client library&#8217;s first beta for <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/blob\/master\/sdk\/eventgrid\/Azure.Messaging.EventGrid\">.NET<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/master\/sdk\/eventgrid\/azure-messaging-eventgrid\">Java<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/master\/sdk\/eventgrid\/eventgrid\">JavaScript<\/a>, and <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/blob\/master\/sdk\/eventgrid\/azure-eventgrid\">Python<\/a>! Check out the links to learn more about how to install the package for each language.<\/p>\n<p>The new client libraries simplify the process of authenticating and publishing messages. You can use the new Azure Event Grid client library to publish events to the Event Grid service in various event schemas (EventGrid, CloudEvents v1.0, or a custom schema) and to consume events that have been delivered to event handlers. This post will explore both event publishing and event consuming in more detail. Another notable difference from the previous Event Grid client library is the ability to specify a custom <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/azure.core.serialization.objectserializer?view=azure-dotnet\">ObjectSerializer<\/a> to use when serializing event data to\/from JSON (by default, using <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/azure.core.serialization.jsonobjectserializer?view=azure-dotnet\">JsonObjectSerializer<\/a>).<\/p>\n<p>Read on to learn more about the <a href=\"https:\/\/cloudevents.io\/\">CloudEvents v1.0 schema<\/a>, and how you can now use Event Grid to work with CloudEvents!<\/p>\n<h2>What is CloudEvents?<\/h2>\n<p><a href=\"https:\/\/cloudevents.io\/\">CloudEvents<\/a> is a collaborative effort between numerous companies and individuals in the industry (Microsoft included) to produce a vendor-neutral specification for &#8220;describing event data in a common way&#8221;. Simply stated, the <a href=\"https:\/\/github.com\/cloudevents\/spec\/blob\/v1.0\/spec.md\">CloudEvents spec<\/a> defines a set of common metadata <em>attributes<\/em> that describe the event being transferred (such as a unique identifier or the time of the event occurrence). The self-described goal of CloudEvents is \u201cto define interoperability of event systems that allow services to produce or consume events, where the producer and consumer can be developed and deployed independently\u201d. The common event format thus allows for easy integration of work across platforms and services and can help standardize how events are consumed.<\/p>\n<p>The new Event Grid client libraries support the JSON format for CloudEvents, meaning that JSON-serialized events of the CloudEvents schema that are sent and received by the service must adhere to the <a href=\"https:\/\/github.com\/cloudevents\/spec\/blob\/v1.0\/json-format.md\">given specification<\/a>.<\/p>\n<p>Below is an example of an Azure Blob Storage event in CloudEvents format:<\/p>\n<pre><code>{\n    \"specversion\": \"1.0\",\n    \"type\": \"Microsoft.Storage.BlobCreated\",  \n    \"source\": \"\/subscriptions\/{subscription-id}\/resourceGroups\/{resource-group}\/providers\/Microsoft.Storage\/storageAccounts\/{storage-account}\",\n    \"id\": \"9aeb0fdf-c01e-0131-0922-9eb54906e209\",\n    \"time\": \"2019-11-18T15:13:39.4589254Z\",\n    \"subject\": \"blobServices\/default\/containers\/{storage-container}\/blobs\/{new-file}\",\n    \"dataschema\": \"#\",\n    \"data\": {\n        \"api\": \"PutBlockList\",\n        \"clientRequestId\": \"4c5dd7fb-2c48-4a27-bb30-5361b5de920a\",\n        \"requestId\": \"9aeb0fdf-c01e-0131-0922-9eb549000000\",\n        \"eTag\": \"0x8D76C39E4407333\",\n        \"contentType\": \"image\/png\",\n        \"contentLength\": 30699,\n        \"blobType\": \"BlockBlob\",\n        \"url\": \"https:\/\/gridtesting.blob.core.windows.net\/testcontainer\/{new-file}\",\n        \"sequencer\": \"000000000000000000000000000099240000000000c41c18\",\n        \"storageDiagnostics\": {\n            \"batchId\": \"681fe319-3006-00a8-0022-9e7cde000000\"\n        }\n    }\n}\n<\/code><\/pre>\n<p>Now, let\u2019s use the Azure Event Grid client library to send and receive some CloudEvents!<\/p>\n<h2>Prerequisites<\/h2>\n<p>You must have an <a href=\"https:\/\/azure.microsoft.com\/free\/\">Azure subscription<\/a> and an Azure resource group with a custom Event Grid topic or domain. Follow this <a href=\"https:\/\/docs.microsoft.com\/azure\/event-grid\/custom-event-quickstart-portal\">step-by-step tutorial<\/a> to register the Event Grid resource provider and create Event Grid topics using the <a href=\"https:\/\/portal.azure.com\/\">Azure portal<\/a>. Importantly, when creating your Event Grid topic, you must set the input schema to \u201cCloudEvents v1.0\u201d in the \u201cAdvanced\u201d tab. After creating your custom topic, navigate to your newly-created topic page to retrieve the topic endpoint and access key, both of which are required in order for the client library to interact with that topic.<\/p>\n<h2>Creating and Authenticating the Client<\/h2>\n<p>Once you have your access key and topic endpoint, you can create the publisher client as follows:<\/p>\n<h4>.NET<\/h4>\n<pre><code class=\"csharp\">EventGridPublisherClient client = new EventGridPublisherClient(\n    \"&lt;endpoint&gt;\",\n    new AzureKeyCredential(\"&lt;access-key&gt;\"));\n<\/code><\/pre>\n<h4>Java<\/h4>\n<pre><code class=\"java\">EventGridPublisherClient egClient = new EventGridPublisherClientBuilder()\n    .endpoint(\"&lt;endpoint&gt;\")\n    .keyCredential(new AzureKeyCredential(\"&lt;access-key&gt;\"))\n    .buildClient();\n<\/code><\/pre>\n<h4>JavaScript<\/h4>\n<pre><code class=\"js\">const { EventGridPublisherClient, AzureKeyCredential } = require(\"@azure\/eventgrid\");\n\nconst client = new EventGridPublisherClient(\"&lt;endpoint&gt;\", new AzureKeyCredential(\"&lt;Access Key&gt;\"));\n<\/code><\/pre>\n<h4>Python<\/h4>\n<pre><code class=\"python\">from azure.core.credentials import AzureKeyCredential\nfrom azure.eventgrid import EventGridPublisherClient\n\ncredential = AzureKeyCredential(\"&lt;access-key&gt;\")\neg_publisher_client = EventGridPublisherClient(\"&lt;endpoint&gt;\", credential)\n<\/code><\/pre>\n<p>We will be using the .NET SDK for the remainder of the article, but similar functionality is available for all libraries. Check out the samples for all languages in the <a href=\"#next-steps\">Next Steps section<\/a>.<\/p>\n<h2>Publishing CloudEvents to your Topic<\/h2>\n<p>The publisher sends events to the Event Grid service. Regardless of what schema your topic or domain is configured to use, <code>EventGridPublisherClient<\/code> will be used to publish events to the service. After creating the <code>EventGridPublisherClient<\/code> such that the custom topic is configured to accept events of the CloudEvents v1.0 schema, we can now create some events of the <code>CloudEvent<\/code> type to publish to the topic.<\/p>\n<p>The <code>CloudEvent<\/code> type represents the event format as described by the specification. Each <code>CloudEvent<\/code> has a set of required, non-nullable properties. Notably for CloudEvents, you can include any number of <em>extension attributes<\/em> such that additional metadata can be added to the event envelope as needed.<\/p>\n<pre><code class=\"csharp\">\/\/ Add CloudEvents to a list to publish to the topic\nList&lt;CloudEvent&gt; eventsList = new List&lt;CloudEvent&gt;\n{\n    new CloudEvent(\n        \"\/cloudevents\/example\/source\",    \/\/ source - identifies the context in which an event happened\n        \"Example.EventType\",              \/\/ type - describing the type of event\n        \"This is the event data\")         \/\/ data - the event payload\n};\n<\/code><\/pre>\n<p>Following that, invoke <code>SendEvents<\/code> or <code>SendEventsAsync<\/code> to publish the events to Azure Event Grid.<\/p>\n<pre><code class=\"csharp\">await client.SendEventsAsync(eventsList);\n<\/code><\/pre>\n<p>To see the events that you\u2019ve sent, the quickstart tutorial also includes <a href=\"https:\/\/docs.microsoft.com\/azure\/event-grid\/custom-event-quickstart-portal#create-a-message-endpoint\">instructions<\/a> on how to subscribe to your new topic with a pre-built web app, which will display the events you sent as JSON:<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-content\/uploads\/sites\/58\/2020\/09\/20200915-events-sent-to-topic.png\" alt=\"Events Sent to Topic\" \/><\/p>\n<h2>Deserializing CloudEvents Delivered to an Event Handler<\/h2>\n<p>The Azure Event Grid client library can also be used to parse events from JSON to access event data. There are several different Azure services that act as <a href=\"https:\/\/docs.microsoft.com\/azure\/event-grid\/event-handlers\">event handlers<\/a>. Regardless of the event handler, events are always sent as <em>UTF-8 encoded JSON<\/em>.<\/p>\n<p>Once events are delivered to the event handler, you can parse the JSON payload into list of events.<\/p>\n<pre><code class=\"csharp\">CloudEvent[] cloudEvents = CloudEvent.Parse(jsonPayload);\n<\/code><\/pre>\n<p>From here, you can access the event data by deserializing to a specific type using <code>GetData&lt;T&gt;()<\/code> and passing in a custom serializer if necessary. Calling <code>GetData()<\/code> will either return a deserialized system event (an event generated by an Azure service), or the event data wrapped in <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/master\/sdk\/core\/Azure.Core.Experimental#binary-data\"><code>BinaryData<\/code><\/a>, which represents the serialized JSON event data as bytes.<\/p>\n<p>Below is an example calling <code>GetData&lt;T&gt;()<\/code> for CloudEvents. The <code>Type<\/code> property for CloudEvents describes the event type related to the occurrence, which may help differentiate between events during deserialization. Custom event data should be deserialized using the generic method <code>GetData&lt;T&gt;()<\/code>. There is also an overload for <code>GetData&lt;T&gt;()<\/code> that accepts a custom <a href=\"https:\/\/docs.microsoft.com\/dotnet\/api\/azure.core.serialization.objectserializer?view=azure-dotnet\"><code>ObjectSerializer<\/code><\/a> to deserialize the event data.<\/p>\n<pre><code class=\"csharp\">foreach (CloudEvent cloudEvent in cloudEvents)\n{\n    switch (cloudEvent.Type)\n    {\n        case \"Contoso.Items.ItemReceived\":\n            \/\/ By default, GetData uses JsonObjectSerializer to deserialize the payload\n            ContosoItemReceivedEventData itemReceived = cloudEvent.GetData&lt;ContosoItemReceivedEventData&gt;();\n            Console.WriteLine(itemReceived.ItemSku);\n            break;\n        case \"MyApp.Models.CustomEventType\":\n            \/\/ You can also specify a custom ObjectSerializer as needed to deserialize the payload correctly\n            TestPayload testPayload = await cloudEvent.GetDataAsync&lt;TestPayload&gt;(myCustomSerializer);\n            Console.WriteLine(testPayload.Name);\n            break;\n        case \"Microsoft.Storage.BlobDeleted\":\n            \/\/ Example for deserializing system events using GetData&lt;T&gt;\n            StorageBlobDeletedEventData blobDeleted = cloudEvent.GetData&lt;StorageBlobDeletedEventData&gt;();\n            Console.WriteLine(blobDeleted.BlobType);\n            break;\n    }\n}\n<\/code><\/pre>\n<h2>Summary<\/h2>\n<p>The new Azure Event Grid client library follows the <a href=\"https:\/\/azure.github.io\/azure-sdk\/general_introduction.html\">Azure SDK Design guidelines<\/a>, bringing about SDKs that are approachable, consistent, and idiomatic for their target languages. As a result, the process of publishing and consuming events should be straightforward for both new and experienced users. Finally, the new support for CloudEvents v1.0 relies less on service specifics, allowing for greater interoperability.<\/p>\n<p><strong>A big shout out to the other 2020 summer interns <a href=\"https:\/\/github.com\/Soreloser2\">Soren Dahl<\/a> and <a href=\"https:\/\/github.com\/t-swpill\">Swathi Pillalamarri<\/a> who worked on getting these libraries shipped for Java and Python! You guys are amazing!!<\/strong><\/p>\n<h2>Next Steps<\/h2>\n<ul>\n<li>Visit the Azure Event Grid repositories for more information and samples! \n<ul>\n<li>.NET: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/blob\/master\/sdk\/eventgrid\/Azure.Messaging.EventGrid\/README.md\">Readme<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/blob\/master\/sdk\/eventgrid\/Azure.Messaging.EventGrid\/samples\/README.md\">Samples<\/a><\/li>\n<li>Java: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/master\/sdk\/eventgrid\/azure-messaging-eventgrid\/README.md\">Readme<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/master\/sdk\/eventgrid\/azure-messaging-eventgrid\/src\/samples\/java\/com\/azure\/messaging\/eventgrid\">Samples<\/a><\/li>\n<li>JavaScript: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/master\/sdk\/eventgrid\/eventgrid\/README.md\">Readme<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/master\/sdk\/eventgrid\/eventgrid\/samples\">Samples<\/a><\/li>\n<li>Python: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/blob\/master\/sdk\/eventgrid\/azure-eventgrid\/README.md\">Readme<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/master\/sdk\/eventgrid\/azure-eventgrid\/samples\">Samples<\/a><\/li>\n<\/ul>\n<\/li>\n<li>Learn more about CloudEvents through the <a href=\"https:\/\/github.com\/cloudevents\/spec\/blob\/master\/primer.md\">CloudEvents primer<\/a> and <a href=\"https:\/\/github.com\/cloudevents\/spec\/blob\/v1.0\/spec.md\">specification<\/a><\/li>\n<\/ul>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n<h2>Azure SDK Blog Contributions<\/h2>\n<p>Thank you for reading this Azure SDK blog post! We hope that you learned something new and welcome you to share this post. We are open to Azure SDK blog contributions. Please contact us at <a href=\"&#109;&#x61;&#105;&#x6c;&#116;&#x6f;&#58;&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;\">&#x61;z&#115;&#x64;&#107;&#x62;&#108;&#x6f;&#103;&#x40;&#109;&#105;&#x63;&#114;&#x6f;&#115;&#x6f;&#102;&#x74;&#46;&#x63;o&#109;<\/a> with your topic and we&#8217;ll get you setup as a guest blogger.<\/p>\n<h2>Azure SDK Links<\/h2>\n<ul>\n<li>Azure SDK Website: <a href=\"https:\/\/aka.ms\/azsdk\">aka.ms\/azsdk<\/a><\/li>\n<li>Azure SDK Intro (3 minute video): <a href=\"https:\/\/aka.ms\/azsdk\/intro\">aka.ms\/azsdk\/intro<\/a><\/li>\n<li>Azure SDK Intro Deck (PowerPoint deck): <a href=\"https:\/\/aka.ms\/azsdk\/intro\/deck\">aka.ms\/azsdk\/intro\/deck<\/a><\/li>\n<li>Azure SDK Releases: <a href=\"https:\/\/aka.ms\/azsdk\/releases\">aka.ms\/azsdk\/releases<\/a><\/li>\n<li>Azure SDK Blog: <a href=\"https:\/\/aka.ms\/azsdk\/blog\">aka.ms\/azsdk\/blog<\/a><\/li>\n<li>Azure SDK Twitter: <a href=\"https:\/\/twitter.com\/AzureSDK\">twitter.com\/AzureSDK<\/a><\/li>\n<li>Azure SDK Design Guidelines: <a href=\"https:\/\/aka.ms\/azsdk\/guide\">aka.ms\/azsdk\/guide<\/a><\/li>\n<li>Azure SDKs &amp; Tools: <a href=\"https:\/\/azure.microsoft.com\/downloads\">azure.microsoft.com\/downloads<\/a><\/li>\n<li>Azure SDK Central Repository: <a href=\"https:\/\/github.com\/azure\/azure-sdk#azure-sdk\">github.com\/azure\/azure-sdk<\/a><\/li>\n<li>Azure SDK for .NET: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-net\">github.com\/azure\/azure-sdk-for-net<\/a><\/li>\n<li>Azure SDK for Java: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-java\">github.com\/azure\/azure-sdk-for-java<\/a><\/li>\n<li>Azure SDK for Python: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-python\">github.com\/azure\/azure-sdk-for-python<\/a><\/li>\n<li>Azure SDK for JavaScript\/TypeScript: <a href=\"https:\/\/github.com\/azure\/azure-sdk-for-js\">github.com\/azure\/azure-sdk-for-js<\/a><\/li>\n<li>Azure SDK for Android: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-android\">github.com\/Azure\/azure-sdk-for-android<\/a><\/li>\n<li>Azure SDK for iOS: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-ios\">github.com\/Azure\/azure-sdk-for-ios<\/a><\/li>\n<li>Azure SDK for Go: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-go\">github.com\/Azure\/azure-sdk-for-go<\/a><\/li>\n<li>Azure SDK for C: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-c\">github.com\/Azure\/azure-sdk-for-c<\/a><\/li>\n<li>Azure SDK for C++: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-cpp\">github.com\/Azure\/azure-sdk-for-cpp<\/a><\/li>\n<\/ul>\n<p><!-- FOOTER: DO NOT EDIT OR REMOVE --><\/p>\n","protected":false},"excerpt":{"rendered":"<p>The new Azure Event Grid client library now supports sending and receiving events in the JSON implementation of CloudEvents v1.0. Read on to learn more about the CloudEvents v1.0 schema, and how you can now use Event Grid to work with CloudEvents!<\/p>\n","protected":false},"author":38557,"featured_media":503,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[706,745,744,705],"class_list":["post-496","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-azuresdk","tag-cloudevents","tag-eventgrid","tag-sdk"],"acf":[],"blog_post_summary":"<p>The new Azure Event Grid client library now supports sending and receiving events in the JSON implementation of CloudEvents v1.0. Read on to learn more about the CloudEvents v1.0 schema, and how you can now use Event Grid to work with CloudEvents!<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/496","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/users\/38557"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=496"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/496\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/503"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=496"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=496"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=496"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}