From 6121eafc794cc109de25121f762f3074d922d1ac Mon Sep 17 00:00:00 2001 From: Abhipsa Misra Date: Tue, 1 Sep 2020 14:13:31 -0700 Subject: [PATCH 1/3] feat(adt): Add helpers for accessing sample's resources --- .../azure-digitaltwins-core/pom.xml | 5 + .../core/DigitalTwinsLifecycleSample.java | 112 ++++++++++++++++++ .../azure/digitaltwins/core/FileHelper.java | 47 ++++++++ .../digitaltwins/core/SamplesConstants.java | 12 ++ .../src/samples/resources/BuildingTwin.json | 7 ++ .../DTDL/DigitalTwins/BuildingTwin.json | 7 ++ .../DTDL/DigitalTwins/FloorTwin.json | 6 + .../resources/DTDL/DigitalTwins/HVACTwin.json | 8 ++ .../resources/DTDL/DigitalTwins/RoomTwin.json | 15 +++ .../resources/DTDL/Models/Building.json | 35 ++++++ .../samples/resources/DTDL/Models/Floor.json | 18 +++ .../samples/resources/DTDL/Models/HVAC.json | 28 +++++ .../samples/resources/DTDL/Models/Room.json | 33 ++++++ .../samples/resources/DTDL/Models/Wifi.json | 18 +++ .../Relationships/HospitalRelationships.json | 27 +++++ 15 files changed, 378 insertions(+) create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/SamplesConstants.java create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/BuildingTwin.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/BuildingTwin.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/FloorTwin.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/HVACTwin.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/RoomTwin.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Building.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Floor.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/HVAC.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Room.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Wifi.json create mode 100644 sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Relationships/HospitalRelationships.json diff --git a/sdk/digitaltwins/azure-digitaltwins-core/pom.xml b/sdk/digitaltwins/azure-digitaltwins-core/pom.xml index 04dc54125c67..7d174b46bcdd 100644 --- a/sdk/digitaltwins/azure-digitaltwins-core/pom.xml +++ b/sdk/digitaltwins/azure-digitaltwins-core/pom.xml @@ -78,6 +78,11 @@ + + + src/samples/resources + + org.apache.maven.plugins diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java new file mode 100644 index 000000000000..fbf673be4632 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java @@ -0,0 +1,112 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.digitaltwins.core; + +import com.azure.core.http.policy.HttpLogDetailLevel; +import com.azure.core.http.policy.HttpLogOptions; +import com.azure.core.util.logging.ClientLogger; +import com.azure.identity.ClientSecretCredentialBuilder; + +import java.io.IOException; +import java.net.URISyntaxException; +import java.net.URL; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Map; +import java.util.concurrent.Semaphore; +import java.util.concurrent.TimeUnit; + +public class DigitalTwinsLifecycleSample { + private static final ClientLogger logger = new ClientLogger(DigitalTwinsLifecycleSample.class); + + private static final String tenantId = System.getenv("TENANT_ID"); + private static final String clientId = System.getenv("CLIENT_ID"); + private static final String clientSecret = System.getenv("CLIENT_SECRET"); + private static final String endpoint = System.getenv("DIGITAL_TWINS_ENDPOINT"); + + private static final int MaxTimeForTwinOperationsInSeconds = 10; + + private static final URL DtdlDirectoryUrl = DigitalTwinsLifecycleSample.class.getClassLoader().getResource("DTDL"); + private static final Path DtDlDirectoryPath; + private static final Path TwinsPath; + private static final Path ModelsPath; + private static final Path RelationshipsPath; + + private static final DigitalTwinsAsyncClient client; + + static { + try { + assert DtdlDirectoryUrl != null; + DtDlDirectoryPath = Paths.get(DtdlDirectoryUrl.toURI()); + } catch (URISyntaxException e) { + logger.error("Unable to convert the DTDL directory URL to URI: ", e); + throw new RuntimeException(e); + } + TwinsPath = Paths.get(DtDlDirectoryPath.toString(), "DigitalTwins"); + ModelsPath = Paths.get(DtDlDirectoryPath.toString(), "Models"); + RelationshipsPath = Paths.get(DtDlDirectoryPath.toString(), "Relationships"); + + client = new DigitalTwinsClientBuilder() + .tokenCredential( + new ClientSecretCredentialBuilder() + .tenantId(tenantId) + .clientId(clientId) + .clientSecret(clientSecret) + .build() + ) + .endpoint(endpoint) + .httpLogOptions( + new HttpLogOptions() + .setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .buildAsyncClient(); + } + + public static void main(String[] args) throws IOException, InterruptedException { + // Ensure existing twins with the same name are deleted first + deleteTwins(); + + // Create twin counterparts for all the models + createTwins(); + } + + public static void deleteTwins() throws IOException, InterruptedException { + System.out.println("DELETE DIGITAL TWINS"); + Map twins = FileHelper.loadAllFilesInPath(TwinsPath); + final Semaphore deleteTwinsSemaphore = new Semaphore(0); + + twins + .forEach((twinId, twinContent) -> client.deleteDigitalTwin(twinId) + .subscribe( + aVoid -> { }, + throwable -> System.err.println("Could not create digital twin " + twinId + " due to " + throwable), + () -> { + System.out.println("Deleted digital twin: " + twinId); + deleteTwinsSemaphore.release(); + })); + + boolean created = deleteTwinsSemaphore.tryAcquire(twins.size(), MaxTimeForTwinOperationsInSeconds, TimeUnit.SECONDS); + System.out.println("Twins deleted: " + created); + } + + public static void createTwins() throws IOException, InterruptedException { + System.out.println("CREATE DIGITAL TWINS"); + Map twins = FileHelper.loadAllFilesInPath(TwinsPath); + final Semaphore createTwinsSemaphore = new Semaphore(0); + + // Call APIs to create the twins. + twins + .forEach( + (twinId, twinContent) -> client.createDigitalTwinWithResponse(twinId, twinContent) + .subscribe( + stringDigitalTwinsResponse -> { + System.out.println("Created digital twin: " + twinId); + System.out.println("\t Body: " + stringDigitalTwinsResponse.getValue()); + }, + throwable -> System.err.println("Could not create digital twin " + twinId + " due to " + throwable), + createTwinsSemaphore::release)); + + boolean created = createTwinsSemaphore.tryAcquire(twins.size(), MaxTimeForTwinOperationsInSeconds, TimeUnit.SECONDS); + System.out.println("Twins created: " + created); + } +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java new file mode 100644 index 000000000000..e89bf1ce6aec --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.digitaltwins.core; + +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import java.util.stream.Stream; + +public class FileHelper { + public static Map loadAllFilesInPath(Path path) throws IOException { + Map fileContents = new HashMap<>(); + + Stream paths = Files.walk(path); + paths + .filter(filePath -> filePath.toFile().getName().endsWith(".json")) + .forEach(filePath -> { + try { + String fileAsString = Files.readString(filePath, StandardCharsets.UTF_8); + fileContents.put(getFileNameFromPath(filePath), cleanupJsonString(fileAsString)); + } catch (IOException e) { + e.printStackTrace(); + } + }); + + return fileContents; + } + + public static String cleanupJsonString(String jsonString) { + // Remove newline characters, empty spaces and unwanted unicode characters + return jsonString.replaceAll("([\\r\\n\\s+\\uFEFF-\\uFFFF])", ""); + } + + public static String getFileNameFromPath(Path path) { + String fileName = path.getFileName().toString(); + if (fileName.indexOf(".") > 0) { + fileName = fileName.substring(0, fileName.lastIndexOf(".")); + } + + return fileName; + } + +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/SamplesConstants.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/SamplesConstants.java new file mode 100644 index 000000000000..4838dec3a12a --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/SamplesConstants.java @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package com.azure.digitaltwins.core; + +public class SamplesConstants { + public static final String RoomModelId = "dtmi:samples:Room;1"; + public static final String WifiModelId = "dtmi:samples:Wifi;1"; + public static final String BuildingModelId = "dtmi:samples:Building;1"; + public static final String FloorModelId = "dtmi:samples:Floor;1"; + public static final String HvacModelId = "dtmi:samples:HVAC;1"; +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/BuildingTwin.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/BuildingTwin.json new file mode 100644 index 000000000000..ba5291c2b571 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/BuildingTwin.json @@ -0,0 +1,7 @@ +{ + "$metadata": { + "$model": "dtmi:samples:Building;1" + }, + "AverageTemperature": 68, + "TemperatureUnit": "Celsius" +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/BuildingTwin.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/BuildingTwin.json new file mode 100644 index 000000000000..ba5291c2b571 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/BuildingTwin.json @@ -0,0 +1,7 @@ +{ + "$metadata": { + "$model": "dtmi:samples:Building;1" + }, + "AverageTemperature": 68, + "TemperatureUnit": "Celsius" +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/FloorTwin.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/FloorTwin.json new file mode 100644 index 000000000000..f9a08edfd8bb --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/FloorTwin.json @@ -0,0 +1,6 @@ +{ + "$metadata": { + "$model": "dtmi:samples:Floor;1" + }, + "AverageTemperature": 75 +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/HVACTwin.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/HVACTwin.json new file mode 100644 index 000000000000..49b4ad617232 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/HVACTwin.json @@ -0,0 +1,8 @@ +{ + "$metadata": { + "$model": "dtmi:samples:HVAC;1" + }, + "Efficiency": 94, + "TargetTemperature": 72, + "TargetHumidity": 30 +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/RoomTwin.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/RoomTwin.json new file mode 100644 index 000000000000..bc75da2917f4 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/DigitalTwins/RoomTwin.json @@ -0,0 +1,15 @@ +{ + "$metadata": { + "$model": "dtmi:samples:Room;1" + }, + "Temperature": 80, + "Humidity": 25, + "IsOccupied": true, + "EmployeeId": "Employee1", + "wifiAccessPoint": { + "$metadata": { + }, + "RouterName": "Cisco1", + "Network": "Room1" + } +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Building.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Building.json new file mode 100644 index 000000000000..1a032d636473 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Building.json @@ -0,0 +1,35 @@ +{ + "@id": "dtmi:samples:Building;1", + "@type": "Interface", + "@context": "dtmi:dtdl:context;2", + "displayName": "Building", + "contents": [ + { + "@type": "Relationship", + "name": "has", + "target": "dtmi:samples:Floor;1", + "properties": [ + { + "@type": "Property", + "name": "isAccessRestricted", + "schema": "boolean" + } + ] + }, + { + "@type": "Relationship", + "name": "isEquippedWith", + "target": "dtmi:samples:HVAC;1" + }, + { + "@type": "Property", + "name": "AverageTemperature", + "schema": "double" + }, + { + "@type": "Property", + "name": "TemperatureUnit", + "schema": "string" + } + ] +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Floor.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Floor.json new file mode 100644 index 000000000000..fe4ea891228b --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Floor.json @@ -0,0 +1,18 @@ +{ + "@id": "dtmi:samples:Floor;1", + "@type": "Interface", + "@context": "dtmi:dtdl:context;2", + "displayName": "Floor", + "contents": [ + { + "@type": "Relationship", + "name": "contains", + "target": "dtmi:samples:Room;1" + }, + { + "@type": "Property", + "name": "AverageTemperature", + "schema": "double" + } + ] +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/HVAC.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/HVAC.json new file mode 100644 index 000000000000..35186f130a95 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/HVAC.json @@ -0,0 +1,28 @@ +{ + "@id": "dtmi:samples:HVAC;1", + "@type": "Interface", + "@context": "dtmi:dtdl:context;2", + "displayName": "HVAC", + "contents": [ + { + "@type": "Property", + "name": "Efficiency", + "schema": "double" + }, + { + "@type": "Property", + "name": "TargetTemperature", + "schema": "double" + }, + { + "@type": "Property", + "name": "TargetHumidity", + "schema": "double" + }, + { + "@type": "Relationship", + "name": "controlsTemperature", + "target": "dtmi:samples:Floor;1" + } + ] +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Room.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Room.json new file mode 100644 index 000000000000..a6c2dfe6bd78 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Room.json @@ -0,0 +1,33 @@ +{ + "@id": "dtmi:samples:Room;1", + "@type": "Interface", + "@context": "dtmi:dtdl:context;2", + "displayName": "Room", + "contents": [ + { + "@type": "Property", + "name": "Temperature", + "schema": "double" + }, + { + "@type": "Property", + "name": "Humidity", + "schema": "double" + }, + { + "@type": "Property", + "name": "IsOccupied", + "schema": "boolean" + }, + { + "@type": "Property", + "name": "EmployeeId", + "schema": "string" + }, + { + "@type": "Component", + "name": "wifiAccessPoint", + "schema": "dtmi:samples:Wifi;1" + } + ] +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Wifi.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Wifi.json new file mode 100644 index 000000000000..a2b07b484334 --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Models/Wifi.json @@ -0,0 +1,18 @@ +{ + "@id": "dtmi:samples:Wifi;1", + "@type": "Interface", + "@context": "dtmi:dtdl:context;2", + "displayName": "Wifi", + "contents": [ + { + "@type": "Property", + "name": "RouterName", + "schema": "string" + }, + { + "@type": "Property", + "name": "Network", + "schema": "string" + } + ] +} diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Relationships/HospitalRelationships.json b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Relationships/HospitalRelationships.json new file mode 100644 index 000000000000..82d426e17a3d --- /dev/null +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/resources/DTDL/Relationships/HospitalRelationships.json @@ -0,0 +1,27 @@ +[ + { + "$relationshipId": "BuildingHasFloor", + "$sourceId": "BuildingTwin", + "$relationshipName": "has", + "$targetId": "FloorTwin", + "isAccessRestricted": false + }, + { + "$relationshipId": "BuildingIsEquippedWithHVAC", + "$sourceId": "BuildingTwin", + "$relationshipName": "isEquippedWith", + "$targetId": "HVACTwin" + }, + { + "$relationshipId": "HVACCoolsFloor", + "$sourceId": "HVACTwin", + "$relationshipName": "controlsTemperature", + "$targetId": "FloorTwin" + }, + { + "$relationshipId": "FloorContainsRoom", + "$sourceId": "FloorTwin", + "$relationshipName": "contains", + "$targetId": "RoomTwin" + } +] From 5d894f41229232d4d1bd8ef9f6c755c792620567 Mon Sep 17 00:00:00 2001 From: Abhipsa Misra Date: Tue, 1 Sep 2020 21:45:48 -0700 Subject: [PATCH 2/3] Files.readString not available in java 8 --- .../digitaltwins/core/DigitalTwinsLifecycleSample.java | 8 +++++++- .../java/com/azure/digitaltwins/core/FileHelper.java | 8 +++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java index fbf673be4632..1abb0becf2b8 100644 --- a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java @@ -6,6 +6,7 @@ import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; import com.azure.core.util.logging.ClientLogger; +import com.azure.digitaltwins.core.implementation.models.ErrorResponseException; import com.azure.identity.ClientSecretCredentialBuilder; import java.io.IOException; @@ -79,7 +80,12 @@ public static void deleteTwins() throws IOException, InterruptedException { .forEach((twinId, twinContent) -> client.deleteDigitalTwin(twinId) .subscribe( aVoid -> { }, - throwable -> System.err.println("Could not create digital twin " + twinId + " due to " + throwable), + throwable -> { + // If digital twin does not exist, ignore. + if (!(throwable instanceof ErrorResponseException) || !((ErrorResponseException) throwable).getValue().getError().getCode().equals("DigitalTwinNotFound")) { + throw new RuntimeException(throwable); + } + }, () -> { System.out.println("Deleted digital twin: " + twinId); deleteTwinsSemaphore.release(); diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java index e89bf1ce6aec..144dc63824a3 100644 --- a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/FileHelper.java @@ -3,12 +3,15 @@ package com.azure.digitaltwins.core; +import java.io.BufferedReader; +import java.io.FileInputStream; import java.io.IOException; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; import java.util.HashMap; import java.util.Map; +import java.util.stream.Collectors; import java.util.stream.Stream; public class FileHelper { @@ -20,7 +23,10 @@ public static Map loadAllFilesInPath(Path path) throws IOExcepti .filter(filePath -> filePath.toFile().getName().endsWith(".json")) .forEach(filePath -> { try { - String fileAsString = Files.readString(filePath, StandardCharsets.UTF_8); + Stream lines = Files.lines(filePath); + String fileAsString = lines.collect(Collectors.joining()); + lines.close(); + fileContents.put(getFileNameFromPath(filePath), cleanupJsonString(fileAsString)); } catch (IOException e) { e.printStackTrace(); From 243fe60c10edf1ebd7a720c9809d59b982717b91 Mon Sep 17 00:00:00 2001 From: Abhipsa Misra Date: Wed, 2 Sep 2020 09:42:53 -0700 Subject: [PATCH 3/3] some small modifications --- .../core/DigitalTwinsLifecycleSample.java | 57 ++++++++----------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java index 1abb0becf2b8..537c3d637048 100644 --- a/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java +++ b/sdk/digitaltwins/azure-digitaltwins-core/src/samples/java/com/azure/digitaltwins/core/DigitalTwinsLifecycleSample.java @@ -5,7 +5,6 @@ import com.azure.core.http.policy.HttpLogDetailLevel; import com.azure.core.http.policy.HttpLogOptions; -import com.azure.core.util.logging.ClientLogger; import com.azure.digitaltwins.core.implementation.models.ErrorResponseException; import com.azure.identity.ClientSecretCredentialBuilder; @@ -19,14 +18,12 @@ import java.util.concurrent.TimeUnit; public class DigitalTwinsLifecycleSample { - private static final ClientLogger logger = new ClientLogger(DigitalTwinsLifecycleSample.class); - private static final String tenantId = System.getenv("TENANT_ID"); private static final String clientId = System.getenv("CLIENT_ID"); private static final String clientSecret = System.getenv("CLIENT_SECRET"); private static final String endpoint = System.getenv("DIGITAL_TWINS_ENDPOINT"); - private static final int MaxTimeForTwinOperationsInSeconds = 10; + private static final int MaxWaitTimeAsyncOperationsInSeconds = 10; private static final URL DtdlDirectoryUrl = DigitalTwinsLifecycleSample.class.getClassLoader().getResource("DTDL"); private static final Path DtDlDirectoryPath; @@ -41,7 +38,7 @@ public class DigitalTwinsLifecycleSample { assert DtdlDirectoryUrl != null; DtDlDirectoryPath = Paths.get(DtdlDirectoryUrl.toURI()); } catch (URISyntaxException e) { - logger.error("Unable to convert the DTDL directory URL to URI: ", e); + System.err.println("Unable to convert the DTDL directory URL to URI: " + e); throw new RuntimeException(e); } TwinsPath = Paths.get(DtDlDirectoryPath.toString(), "DigitalTwins"); @@ -59,7 +56,7 @@ public class DigitalTwinsLifecycleSample { .endpoint(endpoint) .httpLogOptions( new HttpLogOptions() - .setLogLevel(HttpLogDetailLevel.BODY_AND_HEADERS)) + .setLogLevel(HttpLogDetailLevel.NONE)) .buildAsyncClient(); } @@ -76,22 +73,21 @@ public static void deleteTwins() throws IOException, InterruptedException { Map twins = FileHelper.loadAllFilesInPath(TwinsPath); final Semaphore deleteTwinsSemaphore = new Semaphore(0); + // Call APIs to delete the twins. For each async operation, once the operation is completed successfully, a semaphore is released. twins .forEach((twinId, twinContent) -> client.deleteDigitalTwin(twinId) - .subscribe( - aVoid -> { }, - throwable -> { - // If digital twin does not exist, ignore. - if (!(throwable instanceof ErrorResponseException) || !((ErrorResponseException) throwable).getValue().getError().getCode().equals("DigitalTwinNotFound")) { - throw new RuntimeException(throwable); - } - }, - () -> { - System.out.println("Deleted digital twin: " + twinId); - deleteTwinsSemaphore.release(); - })); - - boolean created = deleteTwinsSemaphore.tryAcquire(twins.size(), MaxTimeForTwinOperationsInSeconds, TimeUnit.SECONDS); + .doOnSuccess(aVoid -> System.out.println("Deleted digital twin: " + twinId)) + .doOnError(throwable -> { + // If digital twin does not exist, ignore. + if (!(throwable instanceof ErrorResponseException) || !((ErrorResponseException) throwable).getValue().getError().getCode().equals("DigitalTwinNotFound")) { + System.err.println("Could not delete digital twin " + twinId + " due to " + throwable); + } + }) + .doOnTerminate(deleteTwinsSemaphore::release) + .subscribe()); + + // Verify that a semaphore has been released for each async operation, signifying that the async call has completed. + boolean created = deleteTwinsSemaphore.tryAcquire(twins.size(), MaxWaitTimeAsyncOperationsInSeconds, TimeUnit.SECONDS); System.out.println("Twins deleted: " + created); } @@ -100,19 +96,16 @@ public static void createTwins() throws IOException, InterruptedException { Map twins = FileHelper.loadAllFilesInPath(TwinsPath); final Semaphore createTwinsSemaphore = new Semaphore(0); - // Call APIs to create the twins. + // Call APIs to create the twins. For each async operation, once the operation is completed successfully, a semaphore is released. twins - .forEach( - (twinId, twinContent) -> client.createDigitalTwinWithResponse(twinId, twinContent) - .subscribe( - stringDigitalTwinsResponse -> { - System.out.println("Created digital twin: " + twinId); - System.out.println("\t Body: " + stringDigitalTwinsResponse.getValue()); - }, - throwable -> System.err.println("Could not create digital twin " + twinId + " due to " + throwable), - createTwinsSemaphore::release)); - - boolean created = createTwinsSemaphore.tryAcquire(twins.size(), MaxTimeForTwinOperationsInSeconds, TimeUnit.SECONDS); + .forEach((twinId, twinContent) -> client.createDigitalTwinWithResponse(twinId, twinContent) + .doOnSuccess(response -> System.out.println("Created digital twin: " + twinId + "\n\t Body: " + response.getValue())) + .doOnError(throwable -> System.err.println("Could not create digital twin " + twinId + " due to " + throwable)) + .doOnTerminate(createTwinsSemaphore::release) + .subscribe()); + + // Verify that a semaphore has been released for each async operation, signifying that the async call has completed. + boolean created = createTwinsSemaphore.tryAcquire(twins.size(), MaxWaitTimeAsyncOperationsInSeconds, TimeUnit.SECONDS); System.out.println("Twins created: " + created); } }