{"id":2033,"date":"2022-05-19T12:33:15","date_gmt":"2022-05-19T19:33:15","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/azure-sdk\/?p=2033"},"modified":"2022-05-20T10:17:51","modified_gmt":"2022-05-20T17:17:51","slug":"nnouncing-the-stable-release-of-the-azure-schema-registry-client-libraries","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/azure-sdk\/nnouncing-the-stable-release-of-the-azure-schema-registry-client-libraries\/","title":{"rendered":"Announcing the stable release of the Azure Schema Registry client libraries"},"content":{"rendered":"<p>Azure Schema Registry is a feature of Azure Event Hubs. It provides a central repository for schemas for event-driven and messaging-centric applications, which often work with structured data payload in events or messages. Producers use a schema to serialize payload before publishing it to a broker like Azure Event Hubs; consumers get the payload from the broker and deserialize it using the same schema. For example, a commonly used schema format is <a href=\"https:\/\/avro.apache.org\/\">Apache Avro<\/a>. Schema Registry allows producers and consumers to exchange data without having to manage and share the schema. Read more about this feature at <a href=\"https:\/\/docs.microsoft.com\/azure\/event-hubs\/schema-registry-overview\">Azure Schema Registry in Azure Event Hubs<\/a>.<\/p>\n<h2>Azure Schema Registry client<\/h2>\n<p>The Azure SDK team previously released a stable version of the <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/main\/sdk\/schemaregistry\/Azure.Data.SchemaRegistry\">.NET<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/main\/sdk\/schemaregistry\/azure-data-schemaregistry\">Java<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/main\/sdk\/schemaregistry\/schema-registry\">JavaScript\/TypeScript<\/a>, and <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/main\/sdk\/schemaregistry\/azure-schemaregistry\">Python<\/a> library for the Schema Registry client. This client allows you to interact with Schema Registry and perform operations like registering and retrieving a schema. Check out the code samples below.<\/p>\n<h3>.NET<\/h3>\n<h4>Registering<\/h4>\n<pre><code class=\"language-csharp\">string name = \"employeeSample\";\r\nSchemaFormat format = SchemaFormat.Avro;\r\n\/\/ Example schema's definition\r\nstring definition = @\"\r\n{\r\n   \"\"type\"\" : \"\"record\"\",\r\n    \"\"namespace\"\" : \"\"TestSchema\"\",\r\n    \"\"name\"\" : \"\"Employee\"\",\r\n    \"\"fields\"\" : [\r\n        { \"\"name\"\" : \"\"Name\"\" , \"\"type\"\" : \"\"string\"\" },\r\n        { \"\"name\"\" : \"\"Age\"\", \"\"type\"\" : \"\"int\"\" }\r\n    ]\r\n}\";\r\n\r\nResponse&lt;SchemaProperties&gt; schemaProperties = client.RegisterSchema(groupName, name, definition, format);<\/code><\/pre>\n<h4>Retrieving<\/h4>\n<pre><code class=\"language-csharp\">SchemaRegistrySchema schema = client.GetSchema(schemaId);\r\nstring definition = schema.Definition;<\/code><\/pre>\n<h3>Java<\/h3>\n<h4>Registering<\/h4>\n<pre><code class=\"language-java\">String schemaContent = \"{n\"\r\n    + \"    \"type\" : \"record\",  n\"\r\n    + \"    \"namespace\" : \"SampleSchemaNameSpace\", n\"\r\n    + \"    \"name\" : \"Person\", n\"\r\n    + \"    \"fields\" : [n\"\r\n    + \"        { n\"\r\n    + \"            \"name\" : \"FirstName\" , \"type\" : \"string\" n\"\r\n    + \"        }, n\"\r\n    + \"        { n\"\r\n    + \"            \"name\" : \"LastName\", \"type\" : \"string\" n\"\r\n    + \"        }n\"\r\n    + \"    ]n\"\r\n    + \"}\";\r\nSchemaProperties schemaProperties = schemaRegistryClient.registerSchema(\"{schema-group}\", \"{schema-name}\",\r\n    schemaContent, SchemaFormat.AVRO);\r\n\r\nSystem.out.println(\"Registered schema: \" + schemaProperties.getId());<\/code><\/pre>\n<h4>Retrieving<\/h4>\n<pre><code class=\"language-java\">String schemaContent = \"{n\"\r\n    + \"    \"type\" : \"record\",  n\"\r\n    + \"    \"namespace\" : \"SampleSchemaNameSpace\", n\"\r\n    + \"    \"name\" : \"Person\", n\"\r\n    + \"    \"fields\" : [n\"\r\n    + \"        { n\"\r\n    + \"            \"name\" : \"FirstName\" , \"type\" : \"string\" n\"\r\n    + \"        }, n\"\r\n    + \"        { n\"\r\n    + \"            \"name\" : \"LastName\", \"type\" : \"string\" n\"\r\n    + \"        }n\"\r\n    + \"    ]n\"\r\n    + \"}\";\r\nSchemaProperties properties = schemaRegistryClient.getSchemaProperties(\"{schema-group}\", \"{schema-name}\",\r\n    schemaContent, SchemaFormat.AVRO);\r\n\r\nSystem.out.println(\"Retrieved schema id: \" + properties.getId());<\/code><\/pre>\n<h3>JavaScript\/TypeScript<\/h3>\n<h4>Registering<\/h4>\n<pre><code class=\"language-javascript\">import { DefaultAzureCredential } from \"@azure\/identity\";\r\nimport { SchemaRegistryClient } from \"@azure\/schema-registry\";\r\n\r\nconst client = new SchemaRegistryClient(\"&lt;fullyQualifiedNamespace&gt;\", new DefaultAzureCredential());\r\n\r\nconst description = {\r\n  name: \"&lt;name&gt;\",\r\n  groupName: \"&lt;group name&gt;\",\r\n  format: \"&lt;schema format&gt;\",\r\n  definition: \"&lt;schema definition&gt;\"\r\n}\r\n\r\nconst registered = await client.registerSchema(description);\r\nconsole.log(registered.id);<\/code><\/pre>\n<h4>Retrieving<\/h4>\n<pre><code class=\"language-javascript\">import { DefaultAzureCredential } from \"@azure\/identity\";\r\nimport { SchemaRegistryClient } from \"@azure\/schema-registry\";\r\n\r\nconst client = new SchemaRegistryClient(\"&lt;fullyQualifiedNamespace&gt;\", new DefaultAzureCredential());\r\nconst foundSchema = await client.getSchema(\"&lt;id&gt;\");\r\nif (foundSchema) {\r\n  console.log(`Got schema definition=${foundSchema.definition}`);\r\n}<\/code><\/pre>\n<h3>Python<\/h3>\n<h4>Registering<\/h4>\n<pre><code class=\"language-python\">import os\r\n\r\nfrom azure.identity import DefaultAzureCredential\r\nfrom azure.schemaregistry import SchemaRegistryClient\r\n\r\ntoken_credential = DefaultAzureCredential()\r\nfully_qualified_namespace = os.environ['SCHEMA_REGISTRY_FULLY_QUALIFIED_NAMESPACE']\r\ngroup_name = os.environ['SCHEMA_REGISTRY_GROUP']\r\nname = \"your-schema-name\"\r\nformat = \"Avro\"\r\ndefinition = \"\"\"\r\n{\"namespace\": \"example.avro\",\r\n \"type\": \"record\",\r\n \"name\": \"User\",\r\n \"fields\": [\r\n     {\"name\": \"name\", \"type\": \"string\"},\r\n     {\"name\": \"favorite_number\",  \"type\": [\"int\", \"null\"]},\r\n     {\"name\": \"favorite_color\", \"type\": [\"string\", \"null\"]}\r\n ]\r\n}\r\n\"\"\"\r\n\r\nschema_registry_client = SchemaRegistryClient(fully_qualified_namespace=fully_qualified_namespace, credential=token_credential)\r\nwith schema_registry_client:\r\n    schema_properties = schema_registry_client.register_schema(group_name, name, definition, format)\r\n    id = schema_properties.id<\/code><\/pre>\n<h4>Retrieving<\/h4>\n<pre><code class=\"language-python\">import os\r\n\r\nfrom azure.identity import DefaultAzureCredential\r\nfrom azure.schemaregistry import SchemaRegistryClient\r\n\r\ntoken_credential = DefaultAzureCredential()\r\nfully_qualified_namespace = os.environ['SCHEMA_REGISTRY_FULLY_QUALIFIED_NAMESPACE']\r\nschema_id = 'your-schema-id'\r\n\r\nschema_registry_client = SchemaRegistryClient(fully_qualified_namespace=fully_qualified_namespace, credential=token_credential)\r\nwith schema_registry_client:\r\n    schema = schema_registry_client.get_schema(schema_id)\r\n    definition = schema.definition\r\n    properties = schema.properties<\/code><\/pre>\n<h2>Azure Schema Registry Avro serializer<\/h2>\n<p>Recently, a stable version of the Schema Registry Avro serializer library has also been released, available in these four languages: <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/main\/sdk\/schemaregistry\/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro\">.NET<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/tree\/main\/sdk\/schemaregistry\/azure-data-schemaregistry-apacheavro\">Java<\/a>, <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/tree\/main\/sdk\/schemaregistry\/schema-registry-avro\">JavaScript\/TypeScript<\/a>, and <a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/tree\/main\/sdk\/schemaregistry\/azure-schemaregistry-avroencoder\">Python<\/a>. Combining the serializer and the client allows you to serialize and deserialize data into the Avro format. See the following code samples. The samples demonstrate how to use the serializer with event data from Azure Event Hubs <em>and<\/em> with other data types of your choice.<\/p>\n<h3>.NET<\/h3>\n<h4>Serialize<\/h4>\n<pre><code class=\"language-csharp\">var serializer = new SchemaRegistryAvroSerializer(client, groupName, new SchemaRegistryAvroSerializerOptions { AutoRegisterSchemas = true });\r\n\r\nvar employee = new Employee { Age = 42, Name = \"Caketown\" };\r\nEventData eventData = await serializer.SerializeAsync&lt;EventData, Employee&gt;(employee);\r\n\r\n\/\/ the schema Id will be included as a parameter of the content type\r\nConsole.WriteLine(eventData.ContentType);\r\n\r\n\/\/ the serialized Avro data will be stored in the EventBody\r\nConsole.WriteLine(eventData.EventBody);<\/code><\/pre>\n<h4>Deserialize<\/h4>\n<pre><code class=\"language-csharp\">\/\/ construct a consumer and consume the event from our event hub\r\nawait using var consumer = new EventHubConsumerClient(EventHubConsumerClient.DefaultConsumerGroupName, fullyQualifiedNamespace, eventHubName, credential);\r\nawait foreach (PartitionEvent receivedEvent in consumer.ReadEventsAsync())\r\n{\r\n    Employee deserialized = await serializer.DeserializeAsync&lt;Employee&gt;(eventData);\r\n    Console.WriteLine(deserialized.Age);\r\n    Console.WriteLine(deserialized.Name);\r\n    break;\r\n}<\/code><\/pre>\n<h3>Java<\/h3>\n<h4>Serialize<\/h4>\n<pre><code class=\"language-java\">PlayingCard playingCard = new PlayingCard();\r\nplayingCard.setPlayingCardSuit(PlayingCardSuit.SPADES);\r\nplayingCard.setIsFaceCard(false);\r\nplayingCard.setCardValue(5);\r\n\r\nMessageContent message = serializer.serializeMessageData(playingCard,\r\n    TypeReference.createInstance(MessageContent.class));<\/code><\/pre>\n<h4>Deserialize<\/h4>\n<pre><code class=\"language-java\">SchemaRegistryApacheAvroSerializer serializer = createAvroSchemaRegistrySerializer();\r\nMessageContent message = getSchemaRegistryAvroMessage();\r\nPlayingCard playingCard = serializer.deserializeMessageData(message, TypeReference.createInstance(PlayingCard.class));<\/code><\/pre>\n<h3>JavaScript\/TypeScript<\/h3>\n<h4>Serialize<\/h4>\n<pre><code class=\"language-javascript\">import { DefaultAzureCredential } from \"@azure\/identity\";\r\nimport { createEventDataAdapter } from \"@azure\/event-hubs\";\r\nimport { SchemaRegistryClient } from \"@azure\/schema-registry\";\r\nimport { AvroSerializer } from \"@azure\/schema-registry-avro\";\r\n\r\nconst client = new SchemaRegistryClient(\r\n  \"&lt;fully qualified namespace&gt;\",\r\n  new DefaultAzureCredential()\r\n);\r\nconst serializer = new AvroSerializer(client, {\r\n  groupName: \"&lt;group&gt;\",\r\n  messageAdapter: createEventDataAdapter(),\r\n});\r\n\r\n\/\/ Example Avro schema\r\nconst schema = JSON.stringify({\r\n  type: \"record\",\r\n  name: \"Rating\",\r\n  namespace: \"my.example\",\r\n  fields: [{ name: \"score\", type: \"int\" }],\r\n});\r\n\r\n\/\/ Example value that matches the Avro schema above\r\nconst value = { score: 42 };\r\n\r\n\/\/ Serialize value to a message\r\nconst message = await serializer.serialize(value, schema);<\/code><\/pre>\n<h4>Deserialize<\/h4>\n<pre><code class=\"language-javascript\">\/\/ Deserialize a message to value\r\nconst deserializedValue = await serializer.deserialize(message);<\/code><\/pre>\n<h3>Python<\/h3>\n<h4>Serialize<\/h4>\n<pre><code class=\"language-python\">import os\r\nfrom azure.schemaregistry import SchemaRegistryClient\r\nfrom azure.schemaregistry.encoder.avroencoder import AvroEncoder\r\nfrom azure.identity import DefaultAzureCredential\r\nfrom azure.eventhub import EventData\r\n\r\ntoken_credential = DefaultAzureCredential()\r\nfully_qualified_namespace = os.environ['SCHEMAREGISTRY_FULLY_QUALIFIED_NAMESPACE']\r\ngroup_name = os.environ['SCHEMAREGISTRY_GROUP']\r\nname = \"example.avro.User\"\r\nformat = \"Avro\"\r\n\r\ndefinition = \"\"\"\r\n{\"namespace\": \"example.avro\",\r\n \"type\": \"record\",\r\n \"name\": \"User\",\r\n \"fields\": [\r\n     {\"name\": \"name\", \"type\": \"string\"},\r\n     {\"name\": \"favorite_number\",  \"type\": [\"int\", \"null\"]},\r\n     {\"name\": \"favorite_color\", \"type\": [\"string\", \"null\"]}\r\n ]\r\n}\"\"\"\r\n\r\nschema_registry_client = SchemaRegistryClient(fully_qualified_namespace, token_credential)\r\nschema_registry_client.register_schema(group_name, name, definition, format)\r\nencoder = AvroEncoder(client=schema_registry_client, group_name=group_name)\r\n\r\nwith encoder:\r\n    dict_content = {\"name\": \"Ben\", \"favorite_number\": 7, \"favorite_color\": \"red\"}\r\n    event_data = encoder.encode(dict_content, schema=definition, message_type=EventData)\r\n\r\n    # OR\r\n\r\n    message_content_dict = encoder.encode(dict_content, schema=definition)\r\n    event_data = EventData.from_message_content(message_content_dict[\"content\"], message_content_dict[\"content_type\"])<\/code><\/pre>\n<h4>Deserialize<\/h4>\n<pre><code class=\"language-python\">import os\r\nfrom azure.schemaregistry import SchemaRegistryClient\r\nfrom azure.schemaregistry.encoder.avroencoder import AvroEncoder\r\nfrom azure.identity import DefaultAzureCredential\r\n\r\ntoken_credential = DefaultAzureCredential()\r\nfully_qualified_namespace = os.environ['SCHEMAREGISTRY_FULLY_QUALIFIED_NAMESPACE']\r\ngroup_name = \"&lt;your-group-name&gt;\"\r\n\r\nschema_registry_client = SchemaRegistryClient(fully_qualified_namespace, token_credential)\r\nencoder = AvroEncoder(client=schema_registry_client)\r\n\r\nwith encoder:\r\n    # event_data is an EventData object with Avro encoded body\r\n    dict_content = {\"name\": \"Ben\", \"favorite_number\": 7, \"favorite_color\": \"red\"}\r\n    event_data = encoder.encode(dict_content, schema=definition, message_type=EventData)\r\n    decoded_content = encoder.decode(event_data)\r\n\r\n    # OR \r\n\r\n    encoded_bytes = b'&lt;content_encoded_by_azure_schema_registry_avro_encoder&gt;'\r\n    content_type = 'avro\/binary+&lt;schema_id_of_corresponding_schema&gt;'\r\n    content_dict = {\"content\": encoded_bytes, \"content_type\": content_type}\r\n    decoded_content = encoder.decode(content_dict)<\/code><\/pre>\n<p>The serializer also allows you to cache schemas to optimize performance.<\/p>\n<h3>More samples<\/h3>\n<p>The following samples demonstrate how to use the Avro Serializer to create events with Avro-serialized payload then sending them to Azure Event Hubs. To prevent this blog post from getting too long, links to samples are given here instead of code:<\/p>\n<ul>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-net\/tree\/main\/sdk\/schemaregistry\/Microsoft.Azure.Data.SchemaRegistry.ApacheAvro#serialize-and-deserialize-data-using-the-event-hub-eventdata-model\">.NET<\/a><\/li>\n<li>Java<\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-js\/blob\/main\/sdk\/schemaregistry\/schema-registry-avro\/samples\/v1\/javascript\/withEventHubsProducerClient.js\">JavaScript\/TypeScript<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-python\/blob\/main\/sdk\/schemaregistry\/azure-schemaregistry-avroencoder\/samples\/sync_samples\/eventhub_send_integration.py\">Python<\/a><\/li>\n<li><a href=\"https:\/\/github.com\/Azure\/azure-sdk-for-java\/blob\/main\/sdk\/schemaregistry\/azure-data-schemaregistry-apacheavro\/src\/samples\/java\/com\/azure\/data\/schemaregistry\/apacheavro\/SchemaRegistryWithEventHubs.java\">Java<\/a><\/li>\n<\/ul>\n<h2>Summary<\/h2>\n<p>Azure Schema Registry allows your consumer and producer applications to work with serialized data without having to worry about schemas. The Schema Registry client allows you to register and retrieve schemas. The Schema Registry Avro serializer allows you to serialize and deserialize data to and from the popular Avro format.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Azure Schema Registry provides a central repository for schemas for event-driven and messaging-centric applications. It allows producers and consumers to exchange data without having to manage and share the schema. Learn about the Azure Schema Registry client libraries in this blog post.<\/p>\n","protected":false},"author":32500,"featured_media":2036,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[750,706,785,705],"class_list":["post-2033","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure-sdk","tag-azure-sdk","tag-azuresdk","tag-event-hubs","tag-sdk"],"acf":[],"blog_post_summary":"<p>Azure Schema Registry provides a central repository for schemas for event-driven and messaging-centric applications. It allows producers and consumers to exchange data without having to manage and share the schema. Learn about the Azure Schema Registry client libraries in this blog post.<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/2033","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\/32500"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/comments?post=2033"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/posts\/2033\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media\/2036"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/media?parent=2033"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/categories?post=2033"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/azure-sdk\/wp-json\/wp\/v2\/tags?post=2033"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}