From f502fff6196d2fc909d4e8ea57e3b1bb01bab6f5 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Tue, 20 May 2025 10:03:43 -0400 Subject: [PATCH 01/10] add nepune Java examples --- javav2/example_code/neptune/.gitignore | 38 +++ ...ne delete-db-subnet-group --db-.dockerfile | 12 + javav2/example_code/neptune/pom.xml | 140 +++++++++ .../com/example/neptune/HelloNeptune.java | 107 +++++++ .../analytics/CreateNeptuneGraphExample.java | 53 ++++ .../NeptuneAnalyticsQueryExample.java | 89 ++++++ .../data/GremlinProfileQueryExample.java | 81 +++++ ...eptuneGremlinExplainAndProfileExample.java | 111 +++++++ .../data/NeptuneGremlinQueryExample.java | 93 ++++++ .../data/OpenCypherExplainExample.java | 82 ++++++ ...eptuneGremlinExplainAndProfileExample.java | 106 +++++++ .../neptune/scenerio/NeptuneActions.java | 278 ++++++++++++++++++ .../neptune/scenerio/NeptuneScenario.java | 148 ++++++++++ 13 files changed, 1338 insertions(+) create mode 100644 javav2/example_code/neptune/.gitignore create mode 100644 javav2/example_code/neptune/aws neptune delete-db-subnet-group --db-.dockerfile create mode 100644 javav2/example_code/neptune/pom.xml create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java create mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java diff --git a/javav2/example_code/neptune/.gitignore b/javav2/example_code/neptune/.gitignore new file mode 100644 index 00000000000..5ff6309b719 --- /dev/null +++ b/javav2/example_code/neptune/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/javav2/example_code/neptune/aws neptune delete-db-subnet-group --db-.dockerfile b/javav2/example_code/neptune/aws neptune delete-db-subnet-group --db-.dockerfile new file mode 100644 index 00000000000..44383f1fb86 --- /dev/null +++ b/javav2/example_code/neptune/aws neptune delete-db-subnet-group --db-.dockerfile @@ -0,0 +1,12 @@ +aws neptune delete-db-subnet-group --db-subnet-group-name my-neptune-subnet-group + +aws neptune delete-db-cluster --db-cluster-identifier my-neptune-cluster --skip-final-snapshot + +aws neptune describe-db-instances --query "DBInstances[?Engine=='neptune']" + +aws neptune delete-db-instance --db-instance-identifier my-neptune-db --skip-final-snapshot + + +aws iam create-role --role-name NeptuneLoadFromS3Role --assume-role-policy-document file://trust-policy.json + + diff --git a/javav2/example_code/neptune/pom.xml b/javav2/example_code/neptune/pom.xml new file mode 100644 index 00000000000..34fbd7b6d34 --- /dev/null +++ b/javav2/example_code/neptune/pom.xml @@ -0,0 +1,140 @@ + + + 4.0.0 + + org.example + neptune + 1.0-SNAPSHOT + + + UTF-8 + 21 + 21 + 21 + + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.5.2 + + + org.apache.maven.plugins + maven-compiler-plugin + 3.11.0 + + ${java.version} + 21 + 21 + --enable-preview + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.1 + + + + + + + software.amazon.awssdk + bom + 2.31.8 + pom + import + + + org.apache.logging.log4j + log4j-bom + 2.23.1 + pom + import + + + + + + org.junit.jupiter + junit-jupiter + 5.11.4 + test + + + software.amazon.awssdk + neptune + + + software.amazon.awssdk + ec2 + + + software.amazon.awssdk + neptunedata + + + software.amazon.awssdk + neptunegraph + + + software.amazon.awssdk + apache-client + 2.25.38 + + + + software.amazon.awssdk + secretsmanager + + + com.google.code.gson + gson + 2.10.1 + + + software.amazon.awssdk + sns + + + software.amazon.awssdk + sqs + + + software.amazon.awssdk + ssooidc + + + software.amazon.awssdk + sso + + + software.amazon.awssdk + iam-policy-builder + + + software.amazon.awssdk + sts + + + org.apache.logging.log4j + log4j-core + + + org.slf4j + slf4j-api + 2.0.13 + + + org.apache.logging.log4j + log4j-slf4j2-impl + + + org.apache.logging.log4j + log4j-1.2-api + + + diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java new file mode 100644 index 00000000000..6b2d8ddb86d --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java @@ -0,0 +1,107 @@ +package com.example.neptune; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; + +import java.net.URI; +import java.time.Duration; + +/** + * This example demonstrates how to run a Gremlin Explain and Profile query on an Amazon Neptune database + * using the AWS SDK for Java V2. + * + * VPC NETWORKING REQUIREMENT: + * ---------------------------------------------------------------------- + * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. + * It does not expose a public endpoint. This means: + * + * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, + * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. + * + * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) + * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. + * + * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** + * from the instance or environment where this Java code runs. + * + * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. + * + * TIP: + * You can test connectivity using `curl` or `telnet` from your instance to: + * curl https://:8182/status + * If this fails, it’s likely a networking or security group issue. + * + * ---------------------------------------------------------------------- + */ +public class HelloNeptune { + + private static final String NEPTUNE_ENDPOINT = "https://[Specify-Your-Endpoint]:8182"; + + public static void main(String[] args) { + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + runExplainQuery(client); + runProfileQuery(client); + } catch (NeptunedataException e) { + System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } + + private static void runExplainQuery(NeptunedataClient client) { + System.out.println("Running Gremlin EXPLAIN query..."); + + ExecuteGremlinExplainQueryRequest explainRequest = ExecuteGremlinExplainQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinExplainQueryResponse explainResponse = client.executeGremlinExplainQuery(explainRequest); + + System.out.println("Explain Query Result:"); + if (explainResponse.output() != null) { + System.out.println(explainResponse.output()); + } else { + System.out.println("No explain output returned."); + } + } + + private static void runProfileQuery(NeptunedataClient client) { + System.out.println("Running Gremlin PROFILE query..."); + + ExecuteGremlinProfileQueryRequest profileRequest = ExecuteGremlinProfileQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinProfileQueryResponse profileResponse = client.executeGremlinProfileQuery(profileRequest); + + System.out.println("Profile Query Result:"); + if (profileResponse.output() != null) { + System.out.println(profileResponse.output()); + } else { + System.out.println("No profile output returned."); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java new file mode 100644 index 00000000000..02c043bd252 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java @@ -0,0 +1,53 @@ +package com.example.neptune.analytics; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunegraph.NeptuneGraphClient; +import software.amazon.awssdk.services.neptunegraph.model.CreateGraphRequest; +import software.amazon.awssdk.services.neptunegraph.model.CreateGraphResponse; +import software.amazon.awssdk.services.neptunegraph.model.GraphStatus; +import software.amazon.awssdk.services.neptunegraph.model.NeptuneGraphException; + +public class CreateNeptuneGraphExample { + + public static void main(String[] args) { + // Set the desired region + Region region = Region.US_EAST_1; + + // Set the name for your new graph + String graphName = "sample-analytics-graph"; + + // Create the NeptuneGraph client + NeptuneGraphClient client = NeptuneGraphClient.builder() + .region(region) + .credentialsProvider(DefaultCredentialsProvider.create()) + .build(); + + try { + // Create the graph request + CreateGraphRequest request = CreateGraphRequest.builder() + .graphName(graphName) + .provisionedMemory(16) + .build(); + + // Create the graph + CreateGraphResponse response = client.createGraph(request); + + // Extract the graph name and ARN + String createdGraphName = response.name(); + String graphArn = response.arn(); + String graphEndpoint = response.endpoint(); + + System.out.println("Graph created successfully!"); + System.out.println("Graph Name: " + createdGraphName); + System.out.println("Graph ARN: " + graphArn); + System.out.println("Graph Endpoint: " +graphEndpoint ); + + } catch (NeptuneGraphException e) { + System.err.println("Failed to create graph: " + e.awsErrorDetails().errorMessage()); + } finally { + client.close(); + } + } +} + diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java new file mode 100644 index 00000000000..3ea5afd03dc --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java @@ -0,0 +1,89 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.analytics; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.ResponseInputStream; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunegraph.NeptuneGraphClient; +import software.amazon.awssdk.services.neptunegraph.model.ExecuteQueryRequest; +import software.amazon.awssdk.services.neptunegraph.model.ExecuteQueryResponse; +import software.amazon.awssdk.services.neptunegraph.model.NeptuneGraphException; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.net.URI; +import java.nio.charset.StandardCharsets; +import java.time.Duration; +import java.util.stream.Collectors; + +/** + * This Java example demonstrates how to query Amazon Neptune Analytics (Neptune Graph) using the AWS SDK for Java V2. + * + * VPC NETWORKING REQUIREMENT: + * ---------------------------------------------------------------------- + * Amazon Neptune Analytics must be accessed from within an Amazon VPC. This means: + * + * 1. Your application must run within a VPC environment such as EC2, Lambda, ECS, Cloud9, or an AWS managed notebook. + * 2. You **cannot run this code from your local machine** unless you are connected via a VPN or Direct Connect. + * 3. Ensure that your Neptune Graph cluster endpoint is accessible and security groups allow inbound access from your client. + * 4. Always use the HTTPS endpoint when setting the `endpointOverride()` value. + * + * You can test access by running: + * curl https://:8182/status + * ---------------------------------------------------------------------- + */ + +public class NeptuneAnalyticsQueryExample { + + public static void main(String[] args) { + + // Replace with your Neptune Analytics graph endpoint (including port 8182) + // You can get the Endpoint value by running CreateNeptuneGraphExample + String neptuneAnalyticsEndpoint = "https://:8182"; + String graphId = ""; + + NeptuneGraphClient client = NeptuneGraphClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(neptuneAnalyticsEndpoint)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(0)) // No socket timeout (read_timeout=None) + ) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(0)) // No total timeout + .retryPolicy(b -> b.numRetries(0)) // Disable retries (total_max_attempts=1) + .build()) + .build(); + + try { + System.out.println("Running openCypher query on Neptune Analytics..."); + + ExecuteQueryRequest request = ExecuteQueryRequest.builder() + .graphIdentifier(graphId) + .queryString("MATCH (n {code: 'ANC'}) RETURN n") + .language("OPEN_CYPHER") + .build(); + + ResponseInputStream response = client.executeQuery(request); + try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, StandardCharsets.UTF_8))) { + String result = reader.lines().collect(Collectors.joining("\n")); + System.out.println("Query Result:"); + System.out.println(result); + } catch (Exception e) { + System.err.println("Error reading response: " + e.getMessage()); + } + + } catch (NeptuneGraphException e) { + System.err.println("NeptuneGraph error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } +} + diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java new file mode 100644 index 00000000000..95d339597f3 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java @@ -0,0 +1,81 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.data; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; + +import java.net.URI; +import java.time.Duration; + +/** + * Example: Running a Gremlin Profile query using the AWS SDK for Java V2. + * + * ---------------------------------------------------------------------------------- + * VPC Networking Requirement: + * ---------------------------------------------------------------------------------- + * Amazon Neptune must be accessed from **within the same VPC** as the Neptune cluster. + * It does not expose a public endpoint, so this code must be executed from: + * - An EC2 instance, Lambda function, ECS task, Cloud9 IDE, or + * - A connected environment (VPN, Direct Connect, or peered VPC). + * + * Notes: + * - Ensure Neptune's security group allows inbound traffic on port 8182. + * - Replace the endpoint below with your Neptune cluster's HTTPS endpoint. + * - To verify access, run: curl https://:8182/status + * ---------------------------------------------------------------------------------- + */ +public class GremlinProfileQueryExample { + + // Specify the endpoint. You can obtain an endpoint by running + // the main scenario. + private static final String NEPTUNE_ENDPOINT = "https://:8182"; + + public static void main(String[] args) { + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + executeGremlinProfileQuery(client); + } catch (NeptunedataException e) { + System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } + + private static void executeGremlinProfileQuery(NeptunedataClient client) { + System.out.println("Executing Gremlin PROFILE query..."); + + ExecuteGremlinProfileQueryRequest request = ExecuteGremlinProfileQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinProfileQueryResponse response = client.executeGremlinProfileQuery(request); + if (response.output() != null) { + System.out.println("Query Profile Output:"); + System.out.println(response.output()); + } else { + System.out.println("No output returned from the profile query."); + } + } +} \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java new file mode 100644 index 00000000000..92c1b815789 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java @@ -0,0 +1,111 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.data; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; +import java.net.URI; +import java.time.Duration; + +/** + * This example demonstrates how to run a Gremlin Explain and Profile query on an Amazon Neptune database + * using the AWS SDK for Java V2. + * + * VPC NETWORKING REQUIREMENT: + * ---------------------------------------------------------------------- + * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. + * It does not expose a public endpoint. This means: + * + * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, + * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. + * + * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) + * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. + * + * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** + * from the instance or environment where this Java code runs. + * + * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. + * + * TIP: + * You can test connectivity using `curl` or `telnet` from your instance to: + * curl https://:8182/status + * If this fails, it’s likely a networking or security group issue. + * + * ---------------------------------------------------------------------- + */ +public class NeptuneGremlinExplainAndProfileExample { + + // Specify the endpoint. You can obtain an endpoint by running + // the main scenario. + private static final String NEPTUNE_ENDPOINT = "https://[Specify-Your-Endpoint]:8182"; + + public static void main(String[] args) { + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + runExplainQuery(client); + runProfileQuery(client); + } catch (NeptunedataException e) { + System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } + + private static void runExplainQuery(NeptunedataClient client) { + System.out.println("Running Gremlin EXPLAIN query..."); + + ExecuteGremlinExplainQueryRequest explainRequest = ExecuteGremlinExplainQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinExplainQueryResponse explainResponse = client.executeGremlinExplainQuery(explainRequest); + + System.out.println("Explain Query Result:"); + if (explainResponse.output() != null) { + System.out.println(explainResponse.output()); + } else { + System.out.println("No explain output returned."); + } + } + + private static void runProfileQuery(NeptunedataClient client) { + System.out.println("Running Gremlin PROFILE query..."); + + ExecuteGremlinProfileQueryRequest profileRequest = ExecuteGremlinProfileQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinProfileQueryResponse profileResponse = client.executeGremlinProfileQuery(profileRequest); + + System.out.println("Profile Query Result:"); + if (profileResponse.output() != null) { + System.out.println(profileResponse.output()); + } else { + System.out.println("No profile output returned."); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java new file mode 100644 index 00000000000..2194d0e1080 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java @@ -0,0 +1,93 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.data; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; + +import java.net.URI; +import java.time.Duration; + +/** + * This example demonstrates how to execute a Gremlin query on an Amazon Neptune database using the AWS SDK for Java V2. + * + * VPC NETWORKING REQUIREMENT: + * ---------------------------------------------------------------------- + * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. + * It does not expose a public endpoint. This means: + * + * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, + * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. + * + * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) + * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. + * + * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** + * from the instance or environment where this Java code runs. + * + * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. + * + * TIP: + * You can test connectivity using `curl` or `telnet` from your instance to: + * curl https://:8182/status + * If this fails, it’s likely a networking or security group issue. + * + * ---------------------------------------------------------------------- + */ + +public class NeptuneGremlinQueryExample { + + public static void main(String[] args) { + + + // Specify the endpoint. You can obtain an endpoint by running + // the main scenario. + String neptuneEndpoint = "https://[Specify Endpoint]:8182"; + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(neptuneEndpoint)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + System.out.println("Querying Neptune..."); + + ExecuteGremlinQueryRequest request = ExecuteGremlinQueryRequest.builder() + .gremlinQuery("g.V().has('code', 'ANC')") + .build(); + + ExecuteGremlinQueryResponse response = client.executeGremlinQuery(request); + + System.out.println("Full Response:"); + System.out.println(response); + + // Retrieve and print the result + if (response.result() != null) { + System.out.println("Query Result:"); + System.out.println(response.result().toString()); + } else { + System.out.println("No result returned from the query."); + } + } catch (NeptunedataException e) { + System.err.println("Error calling Neptune: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java new file mode 100644 index 00000000000..f563d1ae9e6 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java @@ -0,0 +1,82 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.data; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherExplainQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherExplainQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; + +import java.net.URI; +import java.time.Duration; + +/** + * Example: Running an OpenCypher EXPLAIN query on Amazon Neptune using AWS SDK for Java V2. + * + * ------------------------------------------------------------------------------ + * VPC NETWORKING REQUIREMENT: + * ------------------------------------------------------------------------------ + * Amazon Neptune must be accessed from within an Amazon VPC. It does not expose + * a public endpoint. + * + * 1. This Java application must run from an environment inside the same VPC as the Neptune cluster, + * such as EC2, ECS, AWS Lambda, AWS Cloud9, or a connected network via VPN or Direct Connect. + * + * 2. Ensure the Neptune cluster’s security group allows inbound access on port 8182 from the host + * running this application. + * + * 3. Use the Neptune HTTPS endpoint with port 8182 in `endpointOverride()`. + * + * Test connectivity with: + * curl https://:8182/status + * ------------------------------------------------------------------------------ + */ +public class OpenCypherExplainExample { + + private static final String NEPTUNE_ENDPOINT = "https://:8182"; + + public static void main(String[] args) { + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + System.out.println("Executing OpenCypher EXPLAIN query..."); + + ExecuteOpenCypherExplainQueryRequest request = ExecuteOpenCypherExplainQueryRequest.builder() + .openCypherQuery("MATCH (n {code: 'ANC'}) RETURN n") + .explainMode("debug") + .build(); + + ExecuteOpenCypherExplainQueryResponse response = client.executeOpenCypherExplainQuery(request); + + if (response.results() != null) { + System.out.println("Explain Results:"); + System.out.println(response.results().asUtf8String()); + } else { + System.out.println("No explain results returned."); + } + + } catch (NeptunedataException e) { + System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java new file mode 100644 index 00000000000..b9c0849d460 --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java @@ -0,0 +1,106 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + + +package com.example.neptune.data; + +import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.http.apache.ApacheHttpClient; +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherQueryRequest; +import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherQueryResponse; +import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; + +import java.net.URI; +import java.time.Duration; +import java.util.Map; + +/** + * Example: Running OpenCypher queries on Amazon Neptune using AWS SDK for Java V2. + * + * ------------------------------------------------------------------------------ + * VPC NETWORKING REQUIREMENT: + * ------------------------------------------------------------------------------ + * Amazon Neptune is accessible only within an Amazon VPC. This means: + * + * 1. This Java code must run within the same VPC as your Neptune cluster. + * Options include EC2, ECS, Lambda, AWS Cloud9, or a VPC-connected environment. + * + * 2. You must allow inbound access on port 8182 to Neptune from the host where this + * Java program runs (via the cluster's Security Group). + * + * 3. The endpoint used must be the Neptune HTTPS endpoint (e.g., https://your-neptune-endpoint:8182). + * + * To test network access from your environment: + * curl https://:8182/status + * ------------------------------------------------------------------------------ + */ +public class eptuneGremlinExplainAndProfileExample { + + // Specify the endpoint. You can obtain an endpoint by running + // the main scenario. + private static final String NEPTUNE_ENDPOINT = "https://:8182"; + + public static void main(String[] args) { + + NeptunedataClient client = NeptunedataClient.builder() + .credentialsProvider(DefaultCredentialsProvider.create()) + .region(Region.US_EAST_1) + .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) + .httpClientBuilder(ApacheHttpClient.builder() + .connectionTimeout(Duration.ofSeconds(10)) + .socketTimeout(Duration.ofSeconds(30))) + .overrideConfiguration(ClientOverrideConfiguration.builder() + .apiCallAttemptTimeout(Duration.ofSeconds(30)) + .build()) + .build(); + + try { + runOpenCypherWithoutParameters(client); + runOpenCypherWithParameters(client); + } catch (NeptunedataException e) { + System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); + } catch (Exception e) { + System.err.println("Unexpected error: " + e.getMessage()); + } finally { + client.close(); + } + } + + private static void runOpenCypherWithoutParameters(NeptunedataClient client) { + System.out.println("\nExecuting OpenCypher query WITHOUT parameters..."); + + ExecuteOpenCypherQueryRequest request = ExecuteOpenCypherQueryRequest.builder() + .openCypherQuery("MATCH (n {code: 'ANC'}) RETURN n") + .build(); + + ExecuteOpenCypherQueryResponse response = client.executeOpenCypherQuery(request); + + if (response.results() != null) { + System.out.println("Results:"); + System.out.println(response.results()); + } else { + System.out.println("No results returned."); + } + } + + private static void runOpenCypherWithParameters(NeptunedataClient client) { + System.out.println("\nExecuting OpenCypher query WITH parameters..."); + + ExecuteOpenCypherQueryRequest request = ExecuteOpenCypherQueryRequest.builder() + .openCypherQuery("MATCH (n {code: $code}) RETURN n") + .parameters(Map.of("code", "ANC").toString()) + .build(); + + ExecuteOpenCypherQueryResponse response = client.executeOpenCypherQuery(request); + + if (response.results() != null) { + System.out.println("Results:"); + System.out.println(response.results()); + } else { + System.out.println("No results returned."); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java new file mode 100644 index 00000000000..ad248824c7d --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -0,0 +1,278 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.scenerio; + +import software.amazon.awssdk.regions.Region; +import software.amazon.awssdk.services.ec2.Ec2Client; +import software.amazon.awssdk.services.ec2.model.DescribeSubnetsRequest; +import software.amazon.awssdk.services.ec2.model.DescribeSubnetsResponse; +import software.amazon.awssdk.services.ec2.model.Subnet; +import software.amazon.awssdk.services.neptune.NeptuneClient; +import software.amazon.awssdk.services.neptune.model.*; +import software.amazon.awssdk.services.neptune.model.CreateDbClusterRequest; +import software.amazon.awssdk.services.neptune.model.CreateDbClusterResponse; +import software.amazon.awssdk.services.neptune.model.CreateDbInstanceRequest; +import software.amazon.awssdk.services.neptune.model.CreateDbInstanceResponse; +import software.amazon.awssdk.services.neptune.model.CreateDbSubnetGroupRequest; +import software.amazon.awssdk.services.neptune.model.CreateDbSubnetGroupResponse; +import software.amazon.awssdk.services.neptune.model.DBCluster; +import software.amazon.awssdk.services.neptune.model.DBInstance; +import software.amazon.awssdk.services.neptune.model.DeleteDbClusterRequest; +import software.amazon.awssdk.services.neptune.model.DeleteDbInstanceRequest; +import software.amazon.awssdk.services.neptune.model.DeleteDbSubnetGroupRequest; +import software.amazon.awssdk.services.neptune.model.DescribeDbClustersResponse; +import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesRequest; +import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesResponse; + +import software.amazon.awssdk.services.neptunedata.NeptunedataClient; +import software.amazon.awssdk.services.neptunedata.model.*; + +import software.amazon.awssdk.services.neptune.model.DescribeDbClustersRequest; + + +import java.net.URI; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +public class NeptuneActions { + + private final Region region = Region.US_EAST_1; + + private final NeptuneClient neptuneClient = NeptuneClient.builder().region(region).build(); + + public void deleteDBSubnetGroup(String subnetGroupId) { + DeleteDbSubnetGroupRequest deleteDbSubnetGroupRequest = DeleteDbSubnetGroupRequest.builder() + .dbSubnetGroupName(subnetGroupId) + .build(); + + neptuneClient.deleteDBSubnetGroup(deleteDbSubnetGroupRequest); + System.out.println("Deleted group " + subnetGroupId); + } + + public void deleteDBCluster(String dbClusterId) { + DeleteDbClusterRequest deleteDbClusterRequest = DeleteDbClusterRequest.builder() + .dbClusterIdentifier(dbClusterId) + .skipFinalSnapshot(true) + .build(); + neptuneClient.deleteDBCluster(deleteDbClusterRequest); + System.out.println("Deleted Cluster " + dbClusterId); + + } + + public void describeDBInstances(String instanceIdentifier) { + DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder() + .dbInstanceIdentifier(instanceIdentifier) + .build(); + + try { + DescribeDbInstancesResponse response = neptuneClient.describeDBInstances(request); + for (DBInstance instance : response.dbInstances()) { + System.out.println("DB Instance Identifier: " + instance.dbInstanceIdentifier()); + System.out.println("DB Instance Class: " + instance.dbInstanceClass()); + System.out.println("Engine: " + instance.engine()); + System.out.println("Engine Version: " + instance.engineVersion()); + System.out.println("Availability Zone: " + instance.availabilityZone()); + System.out.println("DB Subnet Group: " + instance.dbSubnetGroup().dbSubnetGroupName()); + System.out.println("VPC ID: " + instance.dbSubnetGroup().vpcId()); + System.out.println("Subnet Group Description: " + instance.dbSubnetGroup().dbSubnetGroupDescription()); + System.out.println("Endpoint: " + instance.endpoint().address() + ":" + instance.endpoint().port()); + System.out.println("Storage Type: " + instance.storageType()); + System.out.println("Multi-AZ: " + instance.multiAZ()); + System.out.println("IAM DB Auth Enabled: " + instance.iamDatabaseAuthenticationEnabled()); + System.out.println("Publicly Accessible: " + instance.publiclyAccessible()); + System.out.println("Instance Status: " + instance.dbInstanceStatus()); + System.out.println("Preferred Maintenance Window: " + instance.preferredMaintenanceWindow()); + System.out.println("------"); + } + } catch (NeptuneException e) { + System.err.println("Failed to describe DB instances: " + e.awsErrorDetails().errorMessage()); + throw new RuntimeException(e); + } + } + + public void describeDBClusters(String clusterId) { + DescribeDbClustersRequest request = DescribeDbClustersRequest.builder() + .dbClusterIdentifier(clusterId) + .build(); + + try { + DescribeDbClustersResponse response = neptuneClient.describeDBClusters(request); + for (DBCluster cluster : response.dbClusters()) { + System.out.println("Cluster Identifier: " + cluster.dbClusterIdentifier()); + System.out.println("Status: " + cluster.status()); + System.out.println("Engine: " + cluster.engine()); + System.out.println("Engine Version: " + cluster.engineVersion()); + System.out.println("Endpoint: " + cluster.endpoint()); + System.out.println("Reader Endpoint: " + cluster.readerEndpoint()); + System.out.println("Availability Zones: " + cluster.availabilityZones()); + System.out.println("Subnet Group: " + cluster.dbSubnetGroup()); + System.out.println("VPC Security Groups:"); + cluster.vpcSecurityGroups().forEach(vpcGroup -> + System.out.println(" - " + vpcGroup.vpcSecurityGroupId())); + System.out.println("Storage Encrypted: " + cluster.storageEncrypted()); + System.out.println("IAM DB Auth Enabled: " + cluster.iamDatabaseAuthenticationEnabled()); + System.out.println("Backup Retention Period: " + cluster.backupRetentionPeriod() + " days"); + System.out.println("Preferred Backup Window: " + cluster.preferredBackupWindow()); + System.out.println("Preferred Maintenance Window: " + cluster.preferredMaintenanceWindow()); + System.out.println("------"); + } + } catch (NeptuneException e) { + System.err.println("Failed to describe the DB cluster: " + e.awsErrorDetails().errorMessage()); + throw new RuntimeException(e); + } + } + + + public void deleteDBInstance(String dbInstanceId) { + DeleteDbInstanceRequest instanceRequest = DeleteDbInstanceRequest.builder() + .dbInstanceIdentifier(dbInstanceId) + .skipFinalSnapshot(true) + .build(); + + neptuneClient.deleteDBInstance(instanceRequest); + System.out.println("Deleted DBInstance " + dbInstanceId); + } + + public void isNeptuneInstanceReady(String instanceId) { + try { + boolean isReady = false; + int elapsedSeconds = 0; + String lastStatus = "checking..."; + + while (!isReady) { + for (int i = 0; i < 20 && !isReady; i++) { + String line = String.format( + "\r⏰ Elapsed: %-20s 🔄 Status: %-20s", + formatElapsedTime(elapsedSeconds), + lastStatus + ); + System.out.print(line); + System.out.flush(); + + Thread.sleep(1000); + elapsedSeconds++; + } + + // Every 20 seconds, check DB instance status + DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder() + .dbInstanceIdentifier(instanceId) + .build(); + + DescribeDbInstancesResponse response = neptuneClient.describeDBInstances(request); + List instances = response.dbInstances(); + if (instances.isEmpty()) { + System.out.print("\r❌ No instance found with ID: " + instanceId + " \n"); + break; + } + + String status = instances.get(0).dbInstanceStatus(); + lastStatus = status; + + if ("available".equalsIgnoreCase(status)) { + String doneLine = String.format( + "\r✅ Neptune instance is now available after %s. \n", + formatElapsedTime(elapsedSeconds) + ); + System.out.print(doneLine); + isReady = true; + } + } + + } catch (NeptuneException e) { + System.err.println("\n❌ Error checking instance status: " + e.awsErrorDetails().errorMessage()); + throw e; + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + throw new RuntimeException("Thread interrupted while waiting", e); + } + } + + private String formatElapsedTime(int seconds) { + int minutes = seconds / 60; + int remainingSeconds = seconds % 60; + + if (minutes > 0) { + return minutes + (minutes == 1 ? " min" : " mins") + ", " + + remainingSeconds + (remainingSeconds == 1 ? " sec" : " secs"); + } else { + return remainingSeconds + (remainingSeconds == 1 ? " sec" : " secs"); + } + } + + + + + + public String createDBInstance(String dbInstanceId, String dbClusterId) { + try { + CreateDbInstanceRequest request = CreateDbInstanceRequest.builder() + .dbInstanceIdentifier(dbInstanceId) + .dbInstanceClass("db.r5.large") + .engine("neptune") + .dbClusterIdentifier(dbClusterId) + .availabilityZone("us-east-1b") + .build(); + + CreateDbInstanceResponse response = neptuneClient.createDBInstance(request); + System.out.println("Created Neptune DB Instance: " + response.dbInstance().dbInstanceIdentifier()); + return response.dbInstance().dbInstanceIdentifier(); + + } catch (NeptuneException e) { + System.err.println("Failed to create Neptune DB instance: " + e.awsErrorDetails().errorMessage()); + return ""; + } + } + + public String createDBCluster(String dbName) { + try { + CreateDbClusterRequest request = CreateDbClusterRequest.builder() + .dbClusterIdentifier(dbName) + .engine("neptune") + .deletionProtection(false) + .backupRetentionPeriod(1) + .build(); + + CreateDbClusterResponse response = neptuneClient.createDBCluster(request); + System.out.println("DB Cluster created: " + response.dbCluster().dbClusterIdentifier()); + return response.dbCluster().dbClusterIdentifier(); + + } catch (NeptuneException e) { + System.err.println("Failed to create Neptune DB cluster: " + e.awsErrorDetails().errorMessage()); + throw e; + } + } + + public String createSubnetGroup(String vpcId, String groupName) { + List subnetList = getSubnetIds(vpcId); + try { + CreateDbSubnetGroupRequest request = CreateDbSubnetGroupRequest.builder() + .dbSubnetGroupName(groupName) + .dbSubnetGroupDescription("Subnet group for Neptune cluster") + .subnetIds(subnetList) + .build(); + + CreateDbSubnetGroupResponse response = neptuneClient.createDBSubnetGroup(request); + System.out.println("Subnet group created: " + response.dbSubnetGroup().dbSubnetGroupName()); + return response.dbSubnetGroup().dbSubnetGroupArn(); + + } catch (NeptuneException e) { + System.err.println("Error creating subnet group: " + e.awsErrorDetails().errorMessage()); + return ""; + } + } + + private List getSubnetIds(String vpcId) { + try (Ec2Client ec2 = Ec2Client.builder().region(region).build()) { + DescribeSubnetsRequest request = DescribeSubnetsRequest.builder() + .filters(builder -> builder.name("vpc-id").values(vpcId)) + .build(); + + DescribeSubnetsResponse response = ec2.describeSubnets(request); + return response.subnets().stream() + .map(Subnet::subnetId) + .collect(Collectors.toList()); + } + } +} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java new file mode 100644 index 00000000000..036894ba4fd --- /dev/null +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java @@ -0,0 +1,148 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.example.neptune.scenerio; + +import java.util.Scanner; + +//TIP To Run code, press or +// click the icon in the gutter. +public class NeptuneScenario { + public static final String DASHES = new String(new char[80]).replace("\0", "-"); + + static Scanner scanner = new Scanner(System.in); + static NeptuneActions neptuneActions = new NeptuneActions(); + + public static void main(String[] args) { + String subnetGroupName = "neptuneSubnetGroup28" ; + String vpcId = "vpc-e97a4393" ; + String clusterName = "neptuneCluster28" ; + String dbInstanceId = "neptuneDB28" ; + + System.out.println(""" + Amazon Neptune is a fully managed graph + database service by AWS, designed specifically + for handling complex relationships and connected + datasets at scale. It supports two popular graph models: + property graphs (via openCypher and Gremlin) and RDF + graphs (via SPARQL). This makes Neptune ideal for + use cases such as knowledge graphs, fraud detection, + social networking, recommendation engines, and + network management, where relationships between + entities are central to the data. + + Being fully managed, Neptune handles database + provisioning, patching, backups, and replication, + while also offering high availability and durability + within AWS's infrastructure. + + For developers, programming with Neptune allows + for building intelligent, relationship-aware + applications that go beyond traditional tabular + databases. Developers can use the AWS SDK for Java + V2 to automate infrastructure operations + (via NeptuneClient). + + Let's get started... + """); + waitForInputToContinue(scanner); + runScenario(subnetGroupName, vpcId, dbInstanceId, clusterName); + } + + public static void runScenario(String subnetGroupName, String vpcId, String dbInstanceId, String clusterName) { + System.out.println(DASHES); + System.out.println("1. Create a Neptune DB Subnet Group"); + System.out.println("The Neptune DB subnet group is used when launching a Neptune cluster"); + waitForInputToContinue(scanner); + String groupARN = neptuneActions.createSubnetGroup(vpcId, subnetGroupName); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("2. Create a Neptune Cluster"); + System.out.println("A Neptune Cluster allows you to store and query highly connected datasets with low latency."); + waitForInputToContinue(scanner); + String dbClusterId = neptuneActions.createDBCluster(clusterName); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("3. Create a Neptune DB Instance"); + System.out.println("In this step, we add a new database instance to the Neptune cluster"); + waitForInputToContinue(scanner); + neptuneActions.createDBInstance(dbInstanceId, dbClusterId); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("4. Check the status of the Neptune DB Instance"); + System.out.println(""" + In this step, we will wait until the DB instance + becomes available. This may take around 10 minutes. + """); + waitForInputToContinue(scanner); + neptuneActions.isNeptuneInstanceReady(dbInstanceId); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("5. Tag the Amazon Neptune Resource"); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("6.Show Neptune Cluster details"); + waitForInputToContinue(scanner); + neptuneActions.describeDBClusters(clusterName); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("7.Show Neptune Instance details"); + waitForInputToContinue(scanner); + neptuneActions.describeDBInstances(dbInstanceId); + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println("8. Delete the Neptune Assets"); + System.out.println("Would you like to delete the Neptune Assets? (y/n)"); + String delAns = scanner.nextLine().trim(); + if (delAns.equalsIgnoreCase("y")) { + System.out.println("You selected to delete the Neptune assets."); + neptuneActions.deleteDBInstance(dbInstanceId); + neptuneActions.deleteDBCluster(dbClusterId); + neptuneActions.deleteDBSubnetGroup(subnetGroupName); + } else { + System.out.println("You selected not to delete Neptune assets."); + } + waitForInputToContinue(scanner); + System.out.println(DASHES); + + System.out.println(DASHES); + System.out.println( + """ + Thank you for checking out the Amazon Neptune Service Use demo. We hope you + learned something new, or got some inspiration for your own apps today. + For more AWS code examples, have a look at: + https://docs.aws.amazon.com/code-library/latest/ug/what-is-code-library.html + """); + System.out.println(DASHES); + } + + private static void waitForInputToContinue(Scanner scanner) { + while (true) { + System.out.println(""); + System.out.println("Enter 'c' followed by to continue:"); + String input = scanner.nextLine(); + + if (input.trim().equalsIgnoreCase("c")) { + System.out.println("Continuing with the program..."); + System.out.println(""); + break; + } else { + System.out.println("Invalid input. Please try again."); + } + } + } +} \ No newline at end of file From 3f9d2d02a7cb56f5a8abea8e159960ec24e9cc35 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Thu, 22 May 2025 14:11:27 -0400 Subject: [PATCH 02/10] add nepune Java tests --- javav2/example_code/neptune/pom.xml | 4 + .../neptune/scenerio/NeptuneActions.java | 627 ++++++++++++------ .../neptune/scenerio/NeptuneScenario.java | 126 ++-- .../neptune/src/main/resources/log4j2.xml | 17 + .../neptune/src/test/java/NeptuneTest.java | 108 +++ scenarios/basics/neptune/README.md | 39 ++ scenarios/basics/neptune/SPECIFICATION.md | 265 ++++++++ 7 files changed, 942 insertions(+), 244 deletions(-) create mode 100644 javav2/example_code/neptune/src/main/resources/log4j2.xml create mode 100644 javav2/example_code/neptune/src/test/java/NeptuneTest.java create mode 100644 scenarios/basics/neptune/README.md create mode 100644 scenarios/basics/neptune/SPECIFICATION.md diff --git a/javav2/example_code/neptune/pom.xml b/javav2/example_code/neptune/pom.xml index 34fbd7b6d34..6ae67fba0de 100644 --- a/javav2/example_code/neptune/pom.xml +++ b/javav2/example_code/neptune/pom.xml @@ -68,6 +68,10 @@ software.amazon.awssdk neptune + + software.amazon.awssdk + netty-nio-client + software.amazon.awssdk ec2 diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java index ad248824c7d..99a84934177 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -3,11 +3,18 @@ package com.example.neptune.scenerio; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; +import software.amazon.awssdk.core.retry.RetryMode; +import software.amazon.awssdk.http.async.SdkAsyncHttpClient; +import software.amazon.awssdk.http.nio.netty.NettyNioAsyncHttpClient; import software.amazon.awssdk.regions.Region; import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeSubnetsRequest; import software.amazon.awssdk.services.ec2.model.DescribeSubnetsResponse; import software.amazon.awssdk.services.ec2.model.Subnet; +import software.amazon.awssdk.services.neptune.NeptuneAsyncClient; import software.amazon.awssdk.services.neptune.NeptuneClient; import software.amazon.awssdk.services.neptune.model.*; import software.amazon.awssdk.services.neptune.model.CreateDbClusterRequest; @@ -24,170 +31,364 @@ import software.amazon.awssdk.services.neptune.model.DescribeDbClustersResponse; import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesRequest; import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesResponse; - -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.*; - import software.amazon.awssdk.services.neptune.model.DescribeDbClustersRequest; +import software.amazon.awssdk.services.neptunegraph.model.ServiceQuotaExceededException; - -import java.net.URI; +import java.time.Duration; import java.util.List; -import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; public class NeptuneActions { - + private CompletableFuture instanceCheckFuture; + private long instanceCheckStartTime; + private static NeptuneAsyncClient neptuneAsyncClient; private final Region region = Region.US_EAST_1; + private static final Logger logger = LoggerFactory.getLogger(NeptuneActions.class); + private final NeptuneClient neptuneClient = NeptuneClient.builder().region(region).build(); + + + /** + * Retrieves an instance of the NeptuneAsyncClient. + *

+ * This method initializes and returns a singleton instance of the NeptuneAsyncClient. The client + * is configured with the following settings: + *

    + *
  • Maximum concurrency: 100
  • + *
  • Connection timeout: 60 seconds
  • + *
  • Read timeout: 60 seconds
  • + *
  • Write timeout: 60 seconds
  • + *
  • API call timeout: 2 minutes
  • + *
  • API call attempt timeout: 90 seconds
  • + *
  • Retry strategy: STANDARD
  • + *
+ * The client is built using the NettyNioAsyncHttpClient. + * + * @return the singleton instance of the NeptuneAsyncClient + */ + private static NeptuneAsyncClient getAsyncClient() { + if (neptuneAsyncClient == null) { + SdkAsyncHttpClient httpClient = NettyNioAsyncHttpClient.builder() + .maxConcurrency(100) + .connectionTimeout(Duration.ofSeconds(60)) + .readTimeout(Duration.ofSeconds(60)) + .writeTimeout(Duration.ofSeconds(60)) + .build(); + + ClientOverrideConfiguration overrideConfig = ClientOverrideConfiguration.builder() + .apiCallTimeout(Duration.ofMinutes(2)) + .apiCallAttemptTimeout(Duration.ofSeconds(90)) + .retryStrategy(RetryMode.STANDARD) + .build(); + + neptuneAsyncClient = NeptuneAsyncClient.builder() + .httpClient(httpClient) + .overrideConfiguration(overrideConfig) + .build(); + } + return neptuneAsyncClient; + } - private final NeptuneClient neptuneClient = NeptuneClient.builder().region(region).build(); + /** + * Asynchronously deletes a set of Amazon Neptune resources in a defined order. + *

+ * The method performs the following operations in sequence: + *

    + *
  1. Deletes the Neptune DB instance identified by {@code dbInstanceId}.
  2. + *
  3. Waits until the DB instance is fully deleted.
  4. + *
  5. Deletes the Neptune DB cluster identified by {@code dbClusterId}.
  6. + *
  7. Deletes the Neptune DB subnet group identified by {@code subnetGroupName}.
  8. + *
+ *

+ * If any step fails, the subsequent operations are not performed, and the exception + * is logged. This method blocks the calling thread until all operations complete. + * + * @param dbInstanceId the ID of the Neptune DB instance to delete + * @param dbClusterId the ID of the Neptune DB cluster to delete + * @param subnetGroupName the name of the Neptune DB subnet group to delete + */ + public void deleteNeptuneResourcesAsync(String dbInstanceId, String dbClusterId, String subnetGroupName) { + deleteDBInstanceAsync(dbInstanceId) + .thenCompose(v -> waitUntilInstanceDeletedAsync(dbInstanceId)) + .thenCompose(v -> deleteDBClusterAsync(dbClusterId)) + .thenCompose(v -> deleteDBSubnetGroupAsync(subnetGroupName)) + .whenComplete((v, ex) -> { + if (ex != null) { + logger.info("❌ Failed to delete Neptune resources: " + ex.getMessage()); + } else { + logger.info("✅ Neptune resources deleted successfully."); + } + }) + .join(); // Waits for the entire async chain to complete + } - public void deleteDBSubnetGroup(String subnetGroupId) { - DeleteDbSubnetGroupRequest deleteDbSubnetGroupRequest = DeleteDbSubnetGroupRequest.builder() - .dbSubnetGroupName(subnetGroupId) - .build(); + // snippet-start:[neptune.java2.delete.subnet.group.main] + /** + * Deletes a subnet group. + * + * @param subnetGroupName the identifier of the subnet group to delete + * @return a {@link CompletableFuture} that completes when the cluster has been deleted + */ + public CompletableFuture deleteDBSubnetGroupAsync(String subnetGroupName) { + DeleteDbSubnetGroupRequest request = DeleteDbSubnetGroupRequest.builder() + .dbSubnetGroupName(subnetGroupName) + .build(); - neptuneClient.deleteDBSubnetGroup(deleteDbSubnetGroupRequest); - System.out.println("Deleted group " + subnetGroupId); - } + return getAsyncClient().deleteDBSubnetGroup(request) + .thenAccept(response -> logger.info("🗑️ Deleting Subnet Group: " + subnetGroupName)); + } + // snippet-end:[neptune.java2.delete.subnet.group.main] + + // snippet-start:[neptune.java2.delete.cluster.main] + /** + * Deletes a DB instance asynchronously. + * + * @param clusterId the identifier of the cluster to delete + * @return a {@link CompletableFuture} that completes when the cluster has been deleted + */ + public CompletableFuture deleteDBClusterAsync(String clusterId) { + DeleteDbClusterRequest request = DeleteDbClusterRequest.builder() + .dbClusterIdentifier(clusterId) + .skipFinalSnapshot(true) + .build(); - public void deleteDBCluster(String dbClusterId) { - DeleteDbClusterRequest deleteDbClusterRequest = DeleteDbClusterRequest.builder() - .dbClusterIdentifier(dbClusterId) - .skipFinalSnapshot(true) - .build(); - neptuneClient.deleteDBCluster(deleteDbClusterRequest); - System.out.println("Deleted Cluster " + dbClusterId); + return getAsyncClient().deleteDBCluster(request) + .thenAccept(response -> System.out.println("🗑️ Deleting DB Cluster: " + clusterId)); + } + // snippet-end:[neptune.java2.delete.cluster.main] - } + public CompletableFuture waitUntilInstanceDeletedAsync(String instanceId) { + CompletableFuture future = new CompletableFuture<>(); + long startTime = System.currentTimeMillis(); + checkInstanceDeletedRecursive(instanceId, startTime, future); + return future; + } - public void describeDBInstances(String instanceIdentifier) { + // snippet-start:[neptune.java2.delete.instance.main] + /** + * Deletes a DB instance asynchronously. + * + * @param instanceId the identifier of the DB instance to be deleted + * @return a {@link CompletableFuture} that completes when the DB instance has been deleted + */ + public CompletableFuture deleteDBInstanceAsync(String instanceId) { + DeleteDbInstanceRequest request = DeleteDbInstanceRequest.builder() + .dbInstanceIdentifier(instanceId) + .skipFinalSnapshot(true) + .build(); + + return getAsyncClient().deleteDBInstance(request) + .thenAccept(response -> System.out.println("🗑️ Deleting DB Instance: " + instanceId)); + } + // snippet-end:[neptune.java2.delete.instance.main] + + + private void checkInstanceDeletedRecursive(String instanceId, long startTime, CompletableFuture future) { DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder() - .dbInstanceIdentifier(instanceIdentifier) + .dbInstanceIdentifier(instanceId) .build(); - try { - DescribeDbInstancesResponse response = neptuneClient.describeDBInstances(request); - for (DBInstance instance : response.dbInstances()) { - System.out.println("DB Instance Identifier: " + instance.dbInstanceIdentifier()); - System.out.println("DB Instance Class: " + instance.dbInstanceClass()); - System.out.println("Engine: " + instance.engine()); - System.out.println("Engine Version: " + instance.engineVersion()); - System.out.println("Availability Zone: " + instance.availabilityZone()); - System.out.println("DB Subnet Group: " + instance.dbSubnetGroup().dbSubnetGroupName()); - System.out.println("VPC ID: " + instance.dbSubnetGroup().vpcId()); - System.out.println("Subnet Group Description: " + instance.dbSubnetGroup().dbSubnetGroupDescription()); - System.out.println("Endpoint: " + instance.endpoint().address() + ":" + instance.endpoint().port()); - System.out.println("Storage Type: " + instance.storageType()); - System.out.println("Multi-AZ: " + instance.multiAZ()); - System.out.println("IAM DB Auth Enabled: " + instance.iamDatabaseAuthenticationEnabled()); - System.out.println("Publicly Accessible: " + instance.publiclyAccessible()); - System.out.println("Instance Status: " + instance.dbInstanceStatus()); - System.out.println("Preferred Maintenance Window: " + instance.preferredMaintenanceWindow()); - System.out.println("------"); - } - } catch (NeptuneException e) { - System.err.println("Failed to describe DB instances: " + e.awsErrorDetails().errorMessage()); - throw new RuntimeException(e); - } + getAsyncClient().describeDBInstances(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + if (cause instanceof NeptuneException && + ((NeptuneException) cause).awsErrorDetails().errorCode().equals("DBInstanceNotFound")) { + long elapsed = (System.currentTimeMillis() - startTime) / 1000; + logger.info("\r✅ Instance %s deleted after %ds%n", instanceId, elapsed); + future.complete(null); + return; + } + future.completeExceptionally(new CompletionException("Error polling DB instance", cause)); + return; + } + + String status = response.dbInstances().get(0).dbInstanceStatus(); + long elapsed = (System.currentTimeMillis() - startTime) / 1000; + logger.info("\r⏳ Waiting: Instance %s status: %-10s (%ds elapsed)", instanceId, status, elapsed); + System.out.flush(); + + CompletableFuture.delayedExecutor(20, TimeUnit.SECONDS) + .execute(() -> checkInstanceDeletedRecursive(instanceId, startTime, future)); + }); } - public void describeDBClusters(String clusterId) { + + public void waitForClusterStatus(String clusterId, String desiredStatus) { + System.out.printf("🔍 Waiting for cluster '%s' to reach status '%s'...\n", clusterId, desiredStatus); + CompletableFuture future = new CompletableFuture<>(); + checkClusterStatusRecursive(clusterId, desiredStatus, System.currentTimeMillis(), future); + future.join(); // Wait for status + } + + private void checkClusterStatusRecursive(String clusterId, String desiredStatus, long startTime, CompletableFuture future) { DescribeDbClustersRequest request = DescribeDbClustersRequest.builder() .dbClusterIdentifier(clusterId) .build(); - try { - DescribeDbClustersResponse response = neptuneClient.describeDBClusters(request); - for (DBCluster cluster : response.dbClusters()) { - System.out.println("Cluster Identifier: " + cluster.dbClusterIdentifier()); - System.out.println("Status: " + cluster.status()); - System.out.println("Engine: " + cluster.engine()); - System.out.println("Engine Version: " + cluster.engineVersion()); - System.out.println("Endpoint: " + cluster.endpoint()); - System.out.println("Reader Endpoint: " + cluster.readerEndpoint()); - System.out.println("Availability Zones: " + cluster.availabilityZones()); - System.out.println("Subnet Group: " + cluster.dbSubnetGroup()); - System.out.println("VPC Security Groups:"); - cluster.vpcSecurityGroups().forEach(vpcGroup -> - System.out.println(" - " + vpcGroup.vpcSecurityGroupId())); - System.out.println("Storage Encrypted: " + cluster.storageEncrypted()); - System.out.println("IAM DB Auth Enabled: " + cluster.iamDatabaseAuthenticationEnabled()); - System.out.println("Backup Retention Period: " + cluster.backupRetentionPeriod() + " days"); - System.out.println("Preferred Backup Window: " + cluster.preferredBackupWindow()); - System.out.println("Preferred Maintenance Window: " + cluster.preferredMaintenanceWindow()); - System.out.println("------"); - } - } catch (NeptuneException e) { - System.err.println("Failed to describe the DB cluster: " + e.awsErrorDetails().errorMessage()); - throw new RuntimeException(e); - } + getAsyncClient().describeDBClusters(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + future.completeExceptionally( + new CompletionException("Error checking Neptune cluster status", cause) + ); + return; + } + + List clusters = response.dbClusters(); + if (clusters.isEmpty()) { + future.completeExceptionally(new RuntimeException("Cluster not found: " + clusterId)); + return; + } + + String currentStatus = clusters.get(0).status(); + long elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000; + System.out.printf("\r⏰ Elapsed: %-20s 🔄 Cluster status: %-20s", formatElapsedTime((int) elapsedSeconds), currentStatus); + System.out.flush(); + + if (desiredStatus.equalsIgnoreCase(currentStatus)) { + System.out.printf("\r✅ Neptune cluster reached desired status '%s' after %s.\n", desiredStatus, formatElapsedTime((int) elapsedSeconds)); + future.complete(null); + } else { + CompletableFuture.delayedExecutor(20, TimeUnit.SECONDS) + .execute(() -> checkClusterStatusRecursive(clusterId, desiredStatus, startTime, future)); + } + }); } - public void deleteDBInstance(String dbInstanceId) { - DeleteDbInstanceRequest instanceRequest = DeleteDbInstanceRequest.builder() - .dbInstanceIdentifier(dbInstanceId) - .skipFinalSnapshot(true) - .build(); + // snippet-start:[neptune.java2.start.cluster.main] + /** + * Starts an Amazon Neptune DB cluster. + * + * @param clusterIdentifier the unique identifier of the DB cluster to be stopped + */ + public void startDBCluster(String clusterIdentifier) { + StartDbClusterRequest clusterRequest = StartDbClusterRequest.builder() + .dbClusterIdentifier(clusterIdentifier) + .build(); - neptuneClient.deleteDBInstance(instanceRequest); - System.out.println("Deleted DBInstance " + dbInstanceId); - } + neptuneClient.startDBCluster(clusterRequest); + logger.info("🚀 DB Cluster starting..."); + } + // snippet-end:[neptune.java2.start.cluster.main] + + // snippet-start:[neptune.java2.stop.cluster.main] + /** + * Stops an Amazon Neptune DB cluster. + * + * @param clusterIdentifier the unique identifier of the DB cluster to be stopped + */ + public void stopDBCluster(String clusterIdentifier) { + StopDbClusterRequest clusterRequest = StopDbClusterRequest.builder() + .dbClusterIdentifier(clusterIdentifier) + .build(); + + neptuneClient.stopDBCluster(clusterRequest); + logger.info("DB Cluster Stopped"); + } + // snippet-stop:[neptune.java2.stop.cluster.main] + + // snippet-start:[neptune.java2.describe.cluster.main] + + /** + * Asynchronously describes the specified Amazon RDS DB cluster. + * + * @param clusterId the identifier of the DB cluster to describe + * @return a {@link CompletableFuture} that completes when the operation is done, or throws a {@link RuntimeException} + * if an error occurs + */ + public CompletableFuture describeDBClustersAsync(String clusterId) { + DescribeDbClustersRequest request = DescribeDbClustersRequest.builder() + .dbClusterIdentifier(clusterId) + .build(); + + return getAsyncClient().describeDBClusters(request) + .thenAccept(response -> { + for (DBCluster cluster : response.dbClusters()) { + logger.info("Cluster Identifier: " + cluster.dbClusterIdentifier()); + logger.info("Status: " + cluster.status()); + logger.info("Engine: " + cluster.engine()); + logger.info("Engine Version: " + cluster.engineVersion()); + logger.info("Endpoint: " + cluster.endpoint()); + logger.info("Reader Endpoint: " + cluster.readerEndpoint()); + logger.info("Availability Zones: " + cluster.availabilityZones()); + logger.info("Subnet Group: " + cluster.dbSubnetGroup()); + logger.info("VPC Security Groups:"); + cluster.vpcSecurityGroups().forEach(vpcGroup -> + logger.info(" - " + vpcGroup.vpcSecurityGroupId())); + logger.info("Storage Encrypted: " + cluster.storageEncrypted()); + logger.info("IAM DB Auth Enabled: " + cluster.iamDatabaseAuthenticationEnabled()); + logger.info("Backup Retention Period: " + cluster.backupRetentionPeriod() + " days"); + logger.info("Preferred Backup Window: " + cluster.preferredBackupWindow()); + logger.info("Preferred Maintenance Window: " + cluster.preferredMaintenanceWindow()); + logger.info("------"); + } + }) + .exceptionally(ex -> { + Throwable cause = ex.getCause() != null ? ex.getCause() : ex; + throw new RuntimeException("Failed to describe the DB cluster: " + cause.getMessage(), cause); + }); + } + // snippet-end:[neptune.java2.describe.cluster.main] - public void isNeptuneInstanceReady(String instanceId) { - try { - boolean isReady = false; - int elapsedSeconds = 0; - String lastStatus = "checking..."; - - while (!isReady) { - for (int i = 0; i < 20 && !isReady; i++) { - String line = String.format( - "\r⏰ Elapsed: %-20s 🔄 Status: %-20s", - formatElapsedTime(elapsedSeconds), - lastStatus - ); - System.out.print(line); + + public CompletableFuture checkInstanceStatus(String instanceId, String desiredStatus) { + CompletableFuture future = new CompletableFuture<>(); + long startTime = System.currentTimeMillis(); + checkStatusRecursive(instanceId, desiredStatus.toLowerCase(), startTime, future); + return future; + } + + // snippet-start:[neptune.java2.describe.dbinstance.main] + /** + * Checks the status of a Neptune instance recursively until the desired status is reached or a timeout occurs. + * + * @param instanceId the ID of the Neptune instance to check + * @param desiredStatus the desired status of the Neptune instance + * @param startTime the start time of the operation, used to calculate the elapsed time + * @param future a {@link CompletableFuture} that will be completed when the desired status is reached + */ + private void checkStatusRecursive(String instanceId, String desiredStatus, long startTime, CompletableFuture future) { + DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder() + .dbInstanceIdentifier(instanceId) + .build(); + + getAsyncClient().describeDBInstances(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + future.completeExceptionally( + new CompletionException("Error checking Neptune instance status", cause) + ); + return; + } + + List instances = response.dbInstances(); + if (instances.isEmpty()) { + future.completeExceptionally(new RuntimeException("Instance not found: " + instanceId)); + return; + } + + String currentStatus = instances.get(0).dbInstanceStatus(); + long elapsedSeconds = (System.currentTimeMillis() - startTime) / 1000; + System.out.printf("\r⏰ Elapsed: %-20s 🔄 Status: %-20s", formatElapsedTime((int) elapsedSeconds), currentStatus); System.out.flush(); - Thread.sleep(1000); - elapsedSeconds++; - } - - // Every 20 seconds, check DB instance status - DescribeDbInstancesRequest request = DescribeDbInstancesRequest.builder() - .dbInstanceIdentifier(instanceId) - .build(); - - DescribeDbInstancesResponse response = neptuneClient.describeDBInstances(request); - List instances = response.dbInstances(); - if (instances.isEmpty()) { - System.out.print("\r❌ No instance found with ID: " + instanceId + " \n"); - break; - } - - String status = instances.get(0).dbInstanceStatus(); - lastStatus = status; - - if ("available".equalsIgnoreCase(status)) { - String doneLine = String.format( - "\r✅ Neptune instance is now available after %s. \n", - formatElapsedTime(elapsedSeconds) - ); - System.out.print(doneLine); - isReady = true; - } - } - - } catch (NeptuneException e) { - System.err.println("\n❌ Error checking instance status: " + e.awsErrorDetails().errorMessage()); - throw e; - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - throw new RuntimeException("Thread interrupted while waiting", e); - } + if (desiredStatus.equalsIgnoreCase(currentStatus)) { + System.out.printf("\r✅ Neptune instance reached desired status '%s' after %s.\n", desiredStatus, formatElapsedTime((int) elapsedSeconds)); + future.complete(null); + } else { + CompletableFuture.delayedExecutor(20, TimeUnit.SECONDS) + .execute(() -> checkStatusRecursive(instanceId, desiredStatus, startTime, future)); + } + }); } + // snippet-start:[neptune.java2.describe.dbinstance.main] + private String formatElapsedTime(int seconds) { int minutes = seconds / 60; @@ -201,67 +402,117 @@ private String formatElapsedTime(int seconds) { } } + // snippet-start:[neptune.java2.create.dbinstance.main] + + /** + * Creates a new Amazon Neptune DB instance asynchronously. + * + * @param dbInstanceId the identifier for the new DB instance + * @param dbClusterId the identifier for the DB cluster that the new instance will be a part of + * @return a {@link CompletableFuture} that completes with the identifier of the newly created DB instance + * @throws CompletionException if the operation fails, with a cause of either: + * - {@link ServiceQuotaExceededException} if the request would exceed the maximum quota, or + * - a general exception with the failure message + */ + public CompletableFuture createDBInstanceAsync(String dbInstanceId, String dbClusterId) { + CreateDbInstanceRequest request = CreateDbInstanceRequest.builder() + .dbInstanceIdentifier(dbInstanceId) + .dbInstanceClass("db.r5.large") + .engine("neptune") + .dbClusterIdentifier(dbClusterId) + // .availabilityZone("us-east-1c") + .build(); - - - - public String createDBInstance(String dbInstanceId, String dbClusterId) { - try { - CreateDbInstanceRequest request = CreateDbInstanceRequest.builder() - .dbInstanceIdentifier(dbInstanceId) - .dbInstanceClass("db.r5.large") - .engine("neptune") - .dbClusterIdentifier(dbClusterId) - .availabilityZone("us-east-1b") - .build(); - - CreateDbInstanceResponse response = neptuneClient.createDBInstance(request); - System.out.println("Created Neptune DB Instance: " + response.dbInstance().dbInstanceIdentifier()); - return response.dbInstance().dbInstanceIdentifier(); - - } catch (NeptuneException e) { - System.err.println("Failed to create Neptune DB instance: " + e.awsErrorDetails().errorMessage()); - return ""; - } + return getAsyncClient().createDBInstance(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + if (cause instanceof ServiceQuotaExceededException) { + throw new CompletionException("The operation was denied because the request would exceed the maximum quota.", cause); + } + throw new CompletionException("Failed to create Neptune DB instance: " + exception.getMessage(), exception); + } + }) + .thenApply(response -> { + String instanceId = response.dbInstance().dbInstanceIdentifier(); + logger.info("Created Neptune DB Instance: " + instanceId); + return instanceId; + }); } + // snippet-end:[neptune.java2.create.dbinstance.main] + + + // snippet-start:[neptune.java2.create.cluster.main] + + /** + * Creates a new Amazon Neptune DB cluster asynchronously. + * + * @param dbName the name of the DB cluster to be created + * @return a CompletableFuture that, when completed, provides the ID of the created DB cluster + * @throws CompletionException if the operation fails for any reason, including if the request would exceed the maximum quota + */ + public CompletableFuture createDBClusterAsync(String dbName) { + CreateDbClusterRequest request = CreateDbClusterRequest.builder() + .dbClusterIdentifier(dbName) + .engine("neptune") + .deletionProtection(false) + .backupRetentionPeriod(1) + .build(); - public String createDBCluster(String dbName) { - try { - CreateDbClusterRequest request = CreateDbClusterRequest.builder() - .dbClusterIdentifier(dbName) - .engine("neptune") - .deletionProtection(false) - .backupRetentionPeriod(1) - .build(); - - CreateDbClusterResponse response = neptuneClient.createDBCluster(request); - System.out.println("DB Cluster created: " + response.dbCluster().dbClusterIdentifier()); - return response.dbCluster().dbClusterIdentifier(); - - } catch (NeptuneException e) { - System.err.println("Failed to create Neptune DB cluster: " + e.awsErrorDetails().errorMessage()); - throw e; - } + return neptuneAsyncClient.createDBCluster(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + if (cause instanceof ServiceQuotaExceededException) { + throw new CompletionException("The operation was denied because the request would exceed the maximum quota.", cause); + } + throw new CompletionException("Failed to create Neptune DB cluster: " + exception.getMessage(), exception); + } + }) + .thenApply(response -> { + String clusterId = response.dbCluster().dbClusterIdentifier(); + logger.info("DB Cluster created: " + clusterId); + return clusterId; + }); } - - public String createSubnetGroup(String vpcId, String groupName) { + // snippet-end:[neptune.java2.create.cluster.main] + + // snippet-start:[neptune.java2.create.subnet.main] + + /** + * Creates a new DB subnet group asynchronously. + * + * @param vpcId the ID of the VPC for which to create the subnet group + * @param groupName the name of the subnet group to create + * @return a CompletableFuture that, when completed, returns the Amazon Resource Name (ARN) of the created subnet group + * @throws CompletionException if the operation fails, with a cause that may be a ServiceQuotaExceededException if the request would exceed the maximum quota + */ + public CompletableFuture createSubnetGroupAsync(String vpcId, String groupName) { List subnetList = getSubnetIds(vpcId); - try { - CreateDbSubnetGroupRequest request = CreateDbSubnetGroupRequest.builder() - .dbSubnetGroupName(groupName) - .dbSubnetGroupDescription("Subnet group for Neptune cluster") - .subnetIds(subnetList) - .build(); - - CreateDbSubnetGroupResponse response = neptuneClient.createDBSubnetGroup(request); - System.out.println("Subnet group created: " + response.dbSubnetGroup().dbSubnetGroupName()); - return response.dbSubnetGroup().dbSubnetGroupArn(); + CreateDbSubnetGroupRequest request = CreateDbSubnetGroupRequest.builder() + .dbSubnetGroupName(groupName) + .dbSubnetGroupDescription("Subnet group for Neptune cluster") + .subnetIds(subnetList) + .build(); - } catch (NeptuneException e) { - System.err.println("Error creating subnet group: " + e.awsErrorDetails().errorMessage()); - return ""; - } + return getAsyncClient().createDBSubnetGroup(request) + .whenComplete((response, exception) -> { + if (exception != null) { + Throwable cause = exception.getCause(); + if (cause instanceof ServiceQuotaExceededException) { + throw new CompletionException("The operation was denied because the request would exceed the maximum quota.", cause); + } + throw new CompletionException("Failed to create subnet group: " + exception.getMessage(), exception); + } + }) + .thenApply(response -> { + String name = response.dbSubnetGroup().dbSubnetGroupName(); + String arn = response.dbSubnetGroup().dbSubnetGroupArn(); + logger.info("Subnet group created: " + name); + return arn; + }); } + // snippet-end:[neptune.java2.create.subnet.main] private List getSubnetIds(String vpcId) { try (Ec2Client ec2 = Ec2Client.builder().region(region).build()) { diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java index 036894ba4fd..36f2e8925e5 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java @@ -3,23 +3,26 @@ package com.example.neptune.scenerio; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + import java.util.Scanner; //TIP To Run code, press or // click the icon in the gutter. public class NeptuneScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); - + private static final Logger logger = LoggerFactory.getLogger(NeptuneScenario.class); static Scanner scanner = new Scanner(System.in); static NeptuneActions neptuneActions = new NeptuneActions(); public static void main(String[] args) { - String subnetGroupName = "neptuneSubnetGroup28" ; + String subnetGroupName = "neptuneSubnetGroup56" ; String vpcId = "vpc-e97a4393" ; - String clusterName = "neptuneCluster28" ; - String dbInstanceId = "neptuneDB28" ; + String clusterName = "neptuneCluster56" ; + String dbInstanceId = "neptuneDB56" ; - System.out.println(""" + logger.info(""" Amazon Neptune is a fully managed graph database service by AWS, designed specifically for handling complex relationships and connected @@ -50,98 +53,109 @@ property graphs (via openCypher and Gremlin) and RDF } public static void runScenario(String subnetGroupName, String vpcId, String dbInstanceId, String clusterName) { - System.out.println(DASHES); - System.out.println("1. Create a Neptune DB Subnet Group"); - System.out.println("The Neptune DB subnet group is used when launching a Neptune cluster"); + logger.info(DASHES); + logger.info("1. Create a Neptune DB Subnet Group"); + logger.info("The Neptune DB subnet group is used when launching a Neptune cluster"); waitForInputToContinue(scanner); - String groupARN = neptuneActions.createSubnetGroup(vpcId, subnetGroupName); + neptuneActions.createSubnetGroupAsync(vpcId, subnetGroupName).join(); waitForInputToContinue(scanner); - System.out.println(DASHES); + logger.info(DASHES); - System.out.println(DASHES); - System.out.println("2. Create a Neptune Cluster"); - System.out.println("A Neptune Cluster allows you to store and query highly connected datasets with low latency."); + logger.info(DASHES); + logger.info("2. Create a Neptune Cluster"); + logger.info("A Neptune Cluster allows you to store and query highly connected datasets with low latency."); waitForInputToContinue(scanner); - String dbClusterId = neptuneActions.createDBCluster(clusterName); + String dbClusterId = neptuneActions.createDBClusterAsync(clusterName).join(); waitForInputToContinue(scanner); - System.out.println(DASHES); + logger.info(DASHES); - System.out.println(DASHES); - System.out.println("3. Create a Neptune DB Instance"); - System.out.println("In this step, we add a new database instance to the Neptune cluster"); + logger.info(DASHES); + logger.info("3. Create a Neptune DB Instance"); + logger.info("In this step, we add a new database instance to the Neptune cluster"); waitForInputToContinue(scanner); - neptuneActions.createDBInstance(dbInstanceId, dbClusterId); + neptuneActions.createDBInstanceAsync(dbInstanceId, dbClusterId).join(); waitForInputToContinue(scanner); - System.out.println(DASHES); + logger.info(DASHES); - System.out.println(DASHES); - System.out.println("4. Check the status of the Neptune DB Instance"); - System.out.println(""" + logger.info(DASHES); + logger.info("4. Check the status of the Neptune DB Instance"); + logger.info(""" In this step, we will wait until the DB instance becomes available. This may take around 10 minutes. """); waitForInputToContinue(scanner); - neptuneActions.isNeptuneInstanceReady(dbInstanceId); + neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); waitForInputToContinue(scanner); - System.out.println(DASHES); + logger.info(DASHES); - System.out.println(DASHES); - System.out.println("5. Tag the Amazon Neptune Resource"); + logger.info(DASHES); + logger.info("5.Show Neptune Cluster details"); waitForInputToContinue(scanner); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("6.Show Neptune Cluster details"); + neptuneActions.describeDBClustersAsync(clusterName).join(); waitForInputToContinue(scanner); - neptuneActions.describeDBClusters(clusterName); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("6. Stop the Amazon Neptune cluster"); + logger.info(""" + Once stopped, this step polls the status + until the cluster is in a stopped state. + """); waitForInputToContinue(scanner); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("7.Show Neptune Instance details"); + neptuneActions.stopDBCluster(dbClusterId); + neptuneActions.waitForClusterStatus(dbClusterId,"stopped"); waitForInputToContinue(scanner); - neptuneActions.describeDBInstances(dbInstanceId); + logger.info(DASHES); + + logger.info(DASHES); + logger.info("7. Start the Amazon Neptune cluster"); + logger.info(""" + Once started, this step polls the clusters + status until it's in an available state. + We will also poll the instance status. + """); waitForInputToContinue(scanner); - System.out.println(DASHES); - - System.out.println(DASHES); - System.out.println("8. Delete the Neptune Assets"); - System.out.println("Would you like to delete the Neptune Assets? (y/n)"); + neptuneActions.startDBCluster(dbClusterId); + neptuneActions.waitForClusterStatus(dbClusterId,"available"); + neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); + logger.info(DASHES); + logger.info(DASHES); + logger.info("8. Delete the Neptune Assets"); + logger.info("Would you like to delete the Neptune Assets? (y/n)"); String delAns = scanner.nextLine().trim(); if (delAns.equalsIgnoreCase("y")) { - System.out.println("You selected to delete the Neptune assets."); - neptuneActions.deleteDBInstance(dbInstanceId); - neptuneActions.deleteDBCluster(dbClusterId); - neptuneActions.deleteDBSubnetGroup(subnetGroupName); + logger.info("You selected to delete the Neptune assets."); + neptuneActions.deleteNeptuneResourcesAsync(dbInstanceId, clusterName, subnetGroupName); + } else { - System.out.println("You selected not to delete Neptune assets."); + logger.info("You selected not to delete Neptune assets."); } waitForInputToContinue(scanner); - System.out.println(DASHES); + logger.info(DASHES); - System.out.println(DASHES); - System.out.println( + logger.info(DASHES); + logger.info( """ Thank you for checking out the Amazon Neptune Service Use demo. We hope you learned something new, or got some inspiration for your own apps today. For more AWS code examples, have a look at: https://docs.aws.amazon.com/code-library/latest/ug/what-is-code-library.html """); - System.out.println(DASHES); + logger.info(DASHES); } private static void waitForInputToContinue(Scanner scanner) { while (true) { - System.out.println(""); - System.out.println("Enter 'c' followed by to continue:"); + logger.info(""); + logger.info("Enter 'c' followed by to continue:"); String input = scanner.nextLine(); if (input.trim().equalsIgnoreCase("c")) { - System.out.println("Continuing with the program..."); - System.out.println(""); + logger.info("Continuing with the program..."); + logger.info(""); break; } else { - System.out.println("Invalid input. Please try again."); + logger.info("Invalid input. Please try again."); } } } diff --git a/javav2/example_code/neptune/src/main/resources/log4j2.xml b/javav2/example_code/neptune/src/main/resources/log4j2.xml new file mode 100644 index 00000000000..914470047e7 --- /dev/null +++ b/javav2/example_code/neptune/src/main/resources/log4j2.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/javav2/example_code/neptune/src/test/java/NeptuneTest.java b/javav2/example_code/neptune/src/test/java/NeptuneTest.java new file mode 100644 index 00000000000..9b250dc0d7d --- /dev/null +++ b/javav2/example_code/neptune/src/test/java/NeptuneTest.java @@ -0,0 +1,108 @@ +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 + +import com.example.neptune.scenerio.NeptuneActions; +import org.junit.jupiter.api.MethodOrderer; +import org.junit.jupiter.api.Order; +import org.junit.jupiter.api.Tag; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.api.TestMethodOrder; + +import static org.junit.jupiter.api.Assertions.*; + +@TestInstance(TestInstance.Lifecycle.PER_METHOD) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class NeptuneTest { + private static String subnetGroupName = "neptuneSubnetGroupTest" ; + private static String vpcId = "vpc-e97a4393" ; + private static String clusterName = "neptuneClusterTest" ; + private static String dbInstanceId = "neptuneDBTest" ; + private static NeptuneActions neptuneActions = new NeptuneActions(); + private static String dbClusterId = ""; + + @Test + @Tag("IntegrationTest") + @Order(1) + public void testCreateSubnetGroup() { + assertDoesNotThrow(() -> { + neptuneActions.createSubnetGroupAsync(vpcId, subnetGroupName).join(); + //assertTrue(signalCatalogArn.startsWith("arn:"), "The ARN should start with 'arn:'"); + }); + System.out.println("Test 1 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(2) + public void testCreateCluster() { + assertDoesNotThrow(() -> { + dbClusterId = neptuneActions.createDBClusterAsync(clusterName).join(); + assertFalse(dbClusterId.trim().isEmpty(), "DB Cluster ID should not be empty"); + }); + System.out.println("Test 2 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(3) + public void testCreateDBInstance() { + assertDoesNotThrow(() -> { + neptuneActions.createDBInstanceAsync(dbInstanceId, dbClusterId).join(); + }); + System.out.println("Test 3 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(4) + public void testCheckInstance() { + assertDoesNotThrow(() -> { + neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); + }); + System.out.println("Test 4 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(5) + public void testDescribeDBCluster() { + assertDoesNotThrow(() -> { + neptuneActions.describeDBClustersAsync(clusterName).join(); + }); + System.out.println("Test 5 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(6) + public void testStopDBCluster() { + assertDoesNotThrow(() -> { + neptuneActions.stopDBCluster(dbClusterId); + neptuneActions.waitForClusterStatus(dbClusterId,"stopped"); + }); + System.out.println("Test 6 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(7) + public void testStartDBCluster() { + assertDoesNotThrow(() -> { + neptuneActions.startDBCluster(dbClusterId); + neptuneActions.waitForClusterStatus(dbClusterId,"available"); + neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); + }); + System.out.println("Test 7 passed"); + } + + @Test + @Tag("IntegrationTest") + @Order(8) + public void testDeleteResources() { + assertDoesNotThrow(() -> { + neptuneActions.deleteNeptuneResourcesAsync(dbInstanceId, clusterName, subnetGroupName); + }); + System.out.println("Test 8 passed"); + } +} diff --git a/scenarios/basics/neptune/README.md b/scenarios/basics/neptune/README.md new file mode 100644 index 00000000000..5c3da3454c2 --- /dev/null +++ b/scenarios/basics/neptune/README.md @@ -0,0 +1,39 @@ +## Overview +This AWS IoT Fleetwise basic scenario demonstrates how to interact with the AWS IoT FleetWise service using an AWS SDK. The scenario covers various operations such as creating a collection of standardized signals, creating a model manifest, creating a vehicle, and so on. + +## Key Operations + +1. **Create an AWS Fleetwise signal catalog**: + - This step creates an AWS Fleetwise signal catalog by invoking the `createSignalCatalog`method. + +2. **Create an AWS IoT Fleetwise fleet**: + - This operation creates an AWS Fleetwise fleet by invoking the `createFleet`method. + +3. **Create a model manifest**: + - This operation creates an AWS Fleetwise model manifest by invoking the `createModelManifest`method. + +4. **Create a decoder manifest**: + - This operation creates an AWS Fleetwise decoder manifest by invoking the `createDecoderManifest`method. + +5. **Create a vehicle**: + - This operation creates an AWS Fleetwise vehicle by invoking the `createVehicle`method. + +**Note** See the [Engineering specification](SPECIFICATION.md) for a full listing of operations. + +## Resources + +This Basics scenario does not require any additional AWS resources. + +## Implementations + +This scenario example will be implemented in the following languages: + +- Java +- JavaScript +- Kotlin + +## Additional Reading + +- [AWS IoT Fleetwise Documentation](https://docs.aws.amazon.com/iot-fleetwise/latest/developerguide/what-is-iotfleetwise.html) + +Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 diff --git a/scenarios/basics/neptune/SPECIFICATION.md b/scenarios/basics/neptune/SPECIFICATION.md new file mode 100644 index 00000000000..b09a7564414 --- /dev/null +++ b/scenarios/basics/neptune/SPECIFICATION.md @@ -0,0 +1,265 @@ +# Amazon Neptune Service Scenario Specification + +## Overview +This SDK Basics scenario demonstrates how to interact with Amazon Neptune using an AWS SDK. +It demonstrates various tasks such as creating a Neptune DB Subnet Group, creating a Neptune Cluster, +creating a Neptune DB Instance, and so on. Finally this scenario demonstrates how +to clean up resources. Its purpose is to demonstrate how to get up and running with Amazon Neptune and an AWS SDK. + +## Resources +This Basics scenario does not require any additional AWS resources. + +## Hello Amazon Neptune +This program is intended for users not familiar with the Amazon Neptune Service to easily get up and running. The program invokes `describeDBSubnetGroupsPaginator`to iterate through subnet groups. + +## Basics Scenario Program Flow +The Amazon Neptune Basics scenario executes the following operations. + +1. **Create a Neptune DB Subnet Group**: + - Description: Creates a Neptune DB Subnet Group by invoking `createDBSubnetGroup`. + - Exception Handling: Check to see if a `ServiceQuotaExceededException` is thrown. + If so, display the message and end the program. + +2. **Create a Neptune Cluster**: + - Description: Creates a Neptune Cluster by invoking `createDBCluster`. + - Exception Handling: Check to see if a `???` is thrown. If it is thrown, if so, display the message and end the program. + +3. **Create a Neptune DB Instance**: + - Description: Creates a Neptune DB Instance by invoking `createDBInstance`. + - Exception Handling: Check to see if an `???` is thrown. If so, display the message and end the program. + +4. **Check the status of the Neptune DB Instance**: + - Description: Check the status of the DB instance by invoking `describeDBInstances`. Poll the instance until it reaches an `availbale`state. + - Exception Handling: Check to see if a `???` is thrown. If so, display the message and end the program. + +5. **Show Neptune Cluster details**: + - Description: Shows the details of the cluster by invoking `describeDBClusters`. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. + +6. **Stop the Cluster**: + - Description: Stop the cluster by invoking `stopDBCluster`. Poll the cluster until it reaches a `stopped`state. + - Exception Handling: Check to see if a `ResourceAlreadyExistsException` is thrown. If so, display the message and end the program. + +7. **Start the cluster**: + - Description: Start the cluster by invoking `startBCluster`. Poll the cluster until it reaches an `available`state. + - Exception Handling: Check to see if a `ResourceNotFoundException` is thrown. If so, display the message and end the program. + + +8. **Delete the Neptune Assets**: + - Description: Delete the various resources. + - Exception Handling: Check to see if an `ResourceNotFoundException` is thrown. If so, display the message and end the program. + +### Program execution +The following shows the output of the Amazon Neptune Basics scenario. + +``` + Amazon Neptune is a fully managed graph + database service by AWS, designed specifically + for handling complex relationships and connected + datasets at scale. It supports two popular graph models: + property graphs (via openCypher and Gremlin) and RDF + graphs (via SPARQL). This makes Neptune ideal for + use cases such as knowledge graphs, fraud detection, + social networking, recommendation engines, and + network management, where relationships between + entities are central to the data. + +Being fully managed, Neptune handles database +provisioning, patching, backups, and replication, +while also offering high availability and durability +within AWS's infrastructure. + +For developers, programming with Neptune allows +for building intelligent, relationship-aware +applications that go beyond traditional tabular +databases. Developers can use the AWS SDK for Java +V2 to automate infrastructure operations +(via NeptuneClient). + +Let's get started... + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +1. Create a Neptune DB Subnet Group +The Neptune DB subnet group is used when launching a Neptune cluster + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Subnet group created: neptunesubnetgroup56 + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +2. Create a Neptune Cluster +A Neptune Cluster allows you to store and query highly connected datasets with low latency. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +DB Cluster created: neptunecluster56 + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +3. Create a Neptune DB Instance +In this step, we add a new database instance to the Neptune cluster + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Created Neptune DB Instance: neptunedb56 + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +4. Check the status of the Neptune DB Instance +In this step, we will wait until the DB instance +becomes available. This may take around 10 minutes. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +✅ Neptune instance reached desired status 'available' after 10 mins, 29 secs. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +5.Show Neptune Cluster details + +Enter 'c' followed by to continue: +c +Continuing with the program... + +Cluster Identifier: neptunecluster56 +Status: available +Engine: neptune +Engine Version: 1.4.5.0 +Endpoint: neptunecluster56.cluster-csf1if1wwrox.us-east-1.neptune.amazonaws.com +Reader Endpoint: neptunecluster56.cluster-ro-csf1if1wwrox.us-east-1.neptune.amazonaws.com +Availability Zones: [us-east-1f, us-east-1c, us-east-1a] +Subnet Group: default +VPC Security Groups: + - sg-dd2e43f0 +Storage Encrypted: false +IAM DB Auth Enabled: false +Backup Retention Period: 1 days +Preferred Backup Window: 04:54-05:24 +Preferred Maintenance Window: sat:03:37-sat:04:07 +------ + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +6. Stop the Amazon Neptune cluster +Once stopped, this step polls the status +until the cluster is in a stopped state. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +DB Cluster Stopped +🔍 Waiting for cluster 'neptunecluster56' to reach status 'stopped'... +✅ Neptune cluster reached desired status 'stopped' after 12 mins, 10 secs. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +7. Start the Amazon Neptune cluster +Once started, this step polls the clusters +status until it's in an available state. +We will also poll the instance status. + + +Enter 'c' followed by to continue: +c +Continuing with the program... + +🚀 DB Cluster starting... +🔍 Waiting for cluster 'neptunecluster56' to reach status 'available'... +✅ Neptune cluster reached desired status 'available' after 10 mins, 28 secs. +✅ Neptune instance reached desired status 'available' after 0 secs. +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +8. Delete the Neptune Assets +Would you like to delete the Neptune Assets? (y/n) +y +You selected to delete the Neptune assets. +🗑️ Deleting DB Instance: neptuneDB56 +✅ Instance neptuneDB56 deleted after 750s +🗑️ Deleting DB Cluster: neptuneCluster56 +🗑️ Deleting Subnet Group: neptuneSubnetGroup56 +✅ Neptune resources deleted successfully. + +Enter 'c' followed by to continue: +c +Continuing with the program... + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- +Thank you for checking out the Amazon Neptune Service Use demo. We hope you +learned something new, or got some inspiration for your own apps today. +For more AWS code examples, have a look at: +https://docs.aws.amazon.com/code-library/latest/ug/what-is-code-library.html + +-------------------------------------------------------------------------------- +``` + +## SOS Tags + +The following table describes the metadata used in this Basics Scenario. The metadata file is `neptune_metadata.yaml`. + + +| action | metadata key | +|------------------------|------------------------------------- | +|`createSignalCatalog` | iotfleetwise_CreateSignalCatalog | +|`createFleet` | iotfleetwise_CreateFleet | +|`createModelManifest` | iotfleetwise_CreateModelManifest | +|`createDecoderManifest` | iotfleetwise_CreateDecoderManifest | +|`updateModelManifest` | iotfleetwise_UpdateModelManifest | +| `createPortal` | iotfleetwise_CreatePortal | +|`waitForModelManifest` | iotfleetwise_WaitForModelManifest | +|`updateDecoderManifest` | iotfleetwise_updateDecoder | +| `describeAssetModel` | iotfleetwise_DescribeAssetModel | +| `waitForDecoder ` | otfleetwise_WaitForDecoder | +| `createVehicle` |iotfleetwise_CreateVehicle | +| `getVehicle` |iotfleetwise_GetVehicle | +| `deleteVehicle ` |iotfleetwise_DeleteVehicle | +|`deleteDecoderManifest` |iotfleetwise_DeleteDecoder | +| `deleteFleet ` |iotfleetwise_DeleteFleet | +| `deleteModel` |iotfleetwise_DeleteModel | +| `deleteSignalCatalog ` |otfleetwise_DeleteSignalCatalog | +| `scenario` |iotfleetwise_Scenario | +| `hello` |iotfleetwise_Hello | + + + From ca11debd1bdc051adcc2989d607fc624a38d90ec Mon Sep 17 00:00:00 2001 From: Macdonald Date: Thu, 22 May 2025 14:54:29 -0400 Subject: [PATCH 03/10] updated the spec --- scenarios/basics/neptune/SPECIFICATION.md | 38 +++++++++++------------ 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/scenarios/basics/neptune/SPECIFICATION.md b/scenarios/basics/neptune/SPECIFICATION.md index b09a7564414..38e7cba6bcd 100644 --- a/scenarios/basics/neptune/SPECIFICATION.md +++ b/scenarios/basics/neptune/SPECIFICATION.md @@ -241,25 +241,25 @@ The following table describes the metadata used in this Basics Scenario. The met | action | metadata key | |------------------------|------------------------------------- | -|`createSignalCatalog` | iotfleetwise_CreateSignalCatalog | -|`createFleet` | iotfleetwise_CreateFleet | -|`createModelManifest` | iotfleetwise_CreateModelManifest | -|`createDecoderManifest` | iotfleetwise_CreateDecoderManifest | -|`updateModelManifest` | iotfleetwise_UpdateModelManifest | -| `createPortal` | iotfleetwise_CreatePortal | -|`waitForModelManifest` | iotfleetwise_WaitForModelManifest | -|`updateDecoderManifest` | iotfleetwise_updateDecoder | -| `describeAssetModel` | iotfleetwise_DescribeAssetModel | -| `waitForDecoder ` | otfleetwise_WaitForDecoder | -| `createVehicle` |iotfleetwise_CreateVehicle | -| `getVehicle` |iotfleetwise_GetVehicle | -| `deleteVehicle ` |iotfleetwise_DeleteVehicle | -|`deleteDecoderManifest` |iotfleetwise_DeleteDecoder | -| `deleteFleet ` |iotfleetwise_DeleteFleet | -| `deleteModel` |iotfleetwise_DeleteModel | -| `deleteSignalCatalog ` |otfleetwise_DeleteSignalCatalog | -| `scenario` |iotfleetwise_Scenario | -| `hello` |iotfleetwise_Hello | +|`createDBSubnetGroup` | neptune_CreateDBSubnetGroup | +|`createDBCluster` | neptune_CreateDBCluster | +|`createDBInstance` | neptune_CreateDBInstance | +|`describeDBInstances ` | neptune_DescribeDBInstances | +|`describeDBClusters` | neptune_DescribeDBClusters | +| `stopDBCluster` | neptune_StopDBCluster | +|`startDBCluster ` | neptune_StartDBCluster | +|`updateDecoderManifest` | neptune_updateDecoder | +| `describeAssetModel` | neptune_DescribeAssetModel | +| `waitForDecoder ` | neptune_WaitForDecoder | +| `createVehicle` | neptune_CreateVehicle | +| `getVehicle` | neptune_GetVehicle | +| `deleteVehicle ` | neptune_DeleteVehicle | +|`deleteDecoderManifest` | neptunee_DeleteDecoder | +| `deleteFleet ` | neptune_DeleteFleet | +| `deleteModel` | neptune_DeleteModel | +| `deleteSignalCatalog ` | neptune_DeleteSignalCatalog | +| `scenario` | neptune_Scenario | +| `hello` | neptune_Hello | From 1193a570c3d60d41390791a26cc2342efebb96fd Mon Sep 17 00:00:00 2001 From: Macdonald Date: Thu, 22 May 2025 15:49:25 -0400 Subject: [PATCH 04/10] updated the spec --- scenarios/basics/neptune/SPECIFICATION.md | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/scenarios/basics/neptune/SPECIFICATION.md b/scenarios/basics/neptune/SPECIFICATION.md index 38e7cba6bcd..8092f17f7d6 100644 --- a/scenarios/basics/neptune/SPECIFICATION.md +++ b/scenarios/basics/neptune/SPECIFICATION.md @@ -248,18 +248,11 @@ The following table describes the metadata used in this Basics Scenario. The met |`describeDBClusters` | neptune_DescribeDBClusters | | `stopDBCluster` | neptune_StopDBCluster | |`startDBCluster ` | neptune_StartDBCluster | -|`updateDecoderManifest` | neptune_updateDecoder | -| `describeAssetModel` | neptune_DescribeAssetModel | -| `waitForDecoder ` | neptune_WaitForDecoder | -| `createVehicle` | neptune_CreateVehicle | -| `getVehicle` | neptune_GetVehicle | -| `deleteVehicle ` | neptune_DeleteVehicle | -|`deleteDecoderManifest` | neptunee_DeleteDecoder | -| `deleteFleet ` | neptune_DeleteFleet | -| `deleteModel` | neptune_DeleteModel | -| `deleteSignalCatalog ` | neptune_DeleteSignalCatalog | -| `scenario` | neptune_Scenario | -| `hello` | neptune_Hello | +|`deleteDBInstance ` | neptune_DeleteDBInstance | +| `deleteDBCluster` | neptune_DeleteDBCluster | +| `deleteDBSubnetGroup `| neptune_DeleteDBSubnetGroup | +| `scenario` | neptune_Scenario | +| `hello` | neptune_Hello | From 467518ce5145b5da594eaf1017d896cc6fa845e3 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 11:42:58 -0400 Subject: [PATCH 05/10] added SOS --- .doc_gen/metadata/neptune_metadata.yaml | 14 ++ .../com/example/neptune/HelloNeptune.java | 127 ++++++------------ .../analytics/CreateNeptuneGraphExample.java | 53 -------- .../NeptuneAnalyticsQueryExample.java | 89 ------------ .../data/GremlinProfileQueryExample.java | 81 ----------- ...eptuneGremlinExplainAndProfileExample.java | 111 --------------- .../data/NeptuneGremlinQueryExample.java | 93 ------------- .../data/OpenCypherExplainExample.java | 82 ----------- ...eptuneGremlinExplainAndProfileExample.java | 106 --------------- scenarios/basics/neptune/SPECIFICATION.md | 7 +- 10 files changed, 58 insertions(+), 705 deletions(-) create mode 100644 .doc_gen/metadata/neptune_metadata.yaml delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java delete mode 100644 javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java diff --git a/.doc_gen/metadata/neptune_metadata.yaml b/.doc_gen/metadata/neptune_metadata.yaml new file mode 100644 index 00000000000..4d036fb6005 --- /dev/null +++ b/.doc_gen/metadata/neptune_metadata.yaml @@ -0,0 +1,14 @@ +# zexi 0.4.0 +neptune_Hello: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.hello.main + services: + neptune: {DescribeDBClustersPaginator} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java index 6b2d8ddb86d..c9a520b4704 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java @@ -1,107 +1,60 @@ -package com.example.neptune; +// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. +// SPDX-License-Identifier: Apache-2.0 -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; +package com.example.neptune; -import java.net.URI; -import java.time.Duration; +import software.amazon.awssdk.core.async.SdkPublisher; +import software.amazon.awssdk.services.neptune.NeptuneAsyncClient; +import software.amazon.awssdk.services.neptune.model.DescribeDbClustersRequest; +import software.amazon.awssdk.services.neptune.model.DescribeDbClustersResponse; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +// snippet-start:[neptune.java2.hello.main] /** - * This example demonstrates how to run a Gremlin Explain and Profile query on an Amazon Neptune database - * using the AWS SDK for Java V2. - * - * VPC NETWORKING REQUIREMENT: - * ---------------------------------------------------------------------- - * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. - * It does not expose a public endpoint. This means: - * - * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, - * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. - * - * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) - * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. - * - * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** - * from the instance or environment where this Java code runs. + * Before running this Java V2 code example, set up your development + * environment, including your credentials. * - * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. + * For more information, see the following documentation topic: * - * TIP: - * You can test connectivity using `curl` or `telnet` from your instance to: - * curl https://:8182/status - * If this fails, it’s likely a networking or security group issue. - * - * ---------------------------------------------------------------------- + * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class HelloNeptune { private static final String NEPTUNE_ENDPOINT = "https://[Specify-Your-Endpoint]:8182"; public static void main(String[] args) { - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - runExplainQuery(client); - runProfileQuery(client); - } catch (NeptunedataException e) { - System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } + NeptuneAsyncClient neptuneClient = NeptuneAsyncClient.create(); + describeDbCluster(neptuneClient); } - private static void runExplainQuery(NeptunedataClient client) { - System.out.println("Running Gremlin EXPLAIN query..."); - - ExecuteGremlinExplainQueryRequest explainRequest = ExecuteGremlinExplainQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") + /** + * Describes the Amazon Neptune DB clusters using a paginator. + * + * @param neptuneClient the Amazon Neptune asynchronous client + */ + public static void describeDbCluster(NeptuneAsyncClient neptuneClient) { + DescribeDbClustersRequest request = DescribeDbClustersRequest.builder() + .maxRecords(20) // Optional: limit per page .build(); - ExecuteGremlinExplainQueryResponse explainResponse = client.executeGremlinExplainQuery(explainRequest); - - System.out.println("Explain Query Result:"); - if (explainResponse.output() != null) { - System.out.println(explainResponse.output()); - } else { - System.out.println("No explain output returned."); - } - } - - private static void runProfileQuery(NeptunedataClient client) { - System.out.println("Running Gremlin PROFILE query..."); + SdkPublisher paginator= neptuneClient.describeDBClustersPaginator(request); + CompletableFuture future = paginator + .subscribe(response -> { + for (var cluster : response.dbClusters()) { + System.out.println("Cluster Identifier: " + cluster.dbClusterIdentifier()); + System.out.println("Status: " + cluster.status()); + } + }); - ExecuteGremlinProfileQueryRequest profileRequest = ExecuteGremlinProfileQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") - .build(); - - ExecuteGremlinProfileQueryResponse profileResponse = client.executeGremlinProfileQuery(profileRequest); - - System.out.println("Profile Query Result:"); - if (profileResponse.output() != null) { - System.out.println(profileResponse.output()); - } else { - System.out.println("No profile output returned."); + // Wait for completion and handle errors + try { + future.get(); // Waits for all pages to be processed + } catch (InterruptedException | ExecutionException e) { + System.err.println("Failed to describe DB clusters: " + e.getMessage()); + } finally { + neptuneClient.close(); } } } +// snippet-end:[neptune.java2.hello.main] \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java deleted file mode 100644 index 02c043bd252..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/CreateNeptuneGraphExample.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.example.neptune.analytics; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunegraph.NeptuneGraphClient; -import software.amazon.awssdk.services.neptunegraph.model.CreateGraphRequest; -import software.amazon.awssdk.services.neptunegraph.model.CreateGraphResponse; -import software.amazon.awssdk.services.neptunegraph.model.GraphStatus; -import software.amazon.awssdk.services.neptunegraph.model.NeptuneGraphException; - -public class CreateNeptuneGraphExample { - - public static void main(String[] args) { - // Set the desired region - Region region = Region.US_EAST_1; - - // Set the name for your new graph - String graphName = "sample-analytics-graph"; - - // Create the NeptuneGraph client - NeptuneGraphClient client = NeptuneGraphClient.builder() - .region(region) - .credentialsProvider(DefaultCredentialsProvider.create()) - .build(); - - try { - // Create the graph request - CreateGraphRequest request = CreateGraphRequest.builder() - .graphName(graphName) - .provisionedMemory(16) - .build(); - - // Create the graph - CreateGraphResponse response = client.createGraph(request); - - // Extract the graph name and ARN - String createdGraphName = response.name(); - String graphArn = response.arn(); - String graphEndpoint = response.endpoint(); - - System.out.println("Graph created successfully!"); - System.out.println("Graph Name: " + createdGraphName); - System.out.println("Graph ARN: " + graphArn); - System.out.println("Graph Endpoint: " +graphEndpoint ); - - } catch (NeptuneGraphException e) { - System.err.println("Failed to create graph: " + e.awsErrorDetails().errorMessage()); - } finally { - client.close(); - } - } -} - diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java deleted file mode 100644 index 3ea5afd03dc..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/analytics/NeptuneAnalyticsQueryExample.java +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.neptune.analytics; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.ResponseInputStream; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunegraph.NeptuneGraphClient; -import software.amazon.awssdk.services.neptunegraph.model.ExecuteQueryRequest; -import software.amazon.awssdk.services.neptunegraph.model.ExecuteQueryResponse; -import software.amazon.awssdk.services.neptunegraph.model.NeptuneGraphException; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.time.Duration; -import java.util.stream.Collectors; - -/** - * This Java example demonstrates how to query Amazon Neptune Analytics (Neptune Graph) using the AWS SDK for Java V2. - * - * VPC NETWORKING REQUIREMENT: - * ---------------------------------------------------------------------- - * Amazon Neptune Analytics must be accessed from within an Amazon VPC. This means: - * - * 1. Your application must run within a VPC environment such as EC2, Lambda, ECS, Cloud9, or an AWS managed notebook. - * 2. You **cannot run this code from your local machine** unless you are connected via a VPN or Direct Connect. - * 3. Ensure that your Neptune Graph cluster endpoint is accessible and security groups allow inbound access from your client. - * 4. Always use the HTTPS endpoint when setting the `endpointOverride()` value. - * - * You can test access by running: - * curl https://:8182/status - * ---------------------------------------------------------------------- - */ - -public class NeptuneAnalyticsQueryExample { - - public static void main(String[] args) { - - // Replace with your Neptune Analytics graph endpoint (including port 8182) - // You can get the Endpoint value by running CreateNeptuneGraphExample - String neptuneAnalyticsEndpoint = "https://:8182"; - String graphId = ""; - - NeptuneGraphClient client = NeptuneGraphClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(neptuneAnalyticsEndpoint)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(0)) // No socket timeout (read_timeout=None) - ) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(0)) // No total timeout - .retryPolicy(b -> b.numRetries(0)) // Disable retries (total_max_attempts=1) - .build()) - .build(); - - try { - System.out.println("Running openCypher query on Neptune Analytics..."); - - ExecuteQueryRequest request = ExecuteQueryRequest.builder() - .graphIdentifier(graphId) - .queryString("MATCH (n {code: 'ANC'}) RETURN n") - .language("OPEN_CYPHER") - .build(); - - ResponseInputStream response = client.executeQuery(request); - try (BufferedReader reader = new BufferedReader(new InputStreamReader(response, StandardCharsets.UTF_8))) { - String result = reader.lines().collect(Collectors.joining("\n")); - System.out.println("Query Result:"); - System.out.println(result); - } catch (Exception e) { - System.err.println("Error reading response: " + e.getMessage()); - } - - } catch (NeptuneGraphException e) { - System.err.println("NeptuneGraph error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } -} - diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java deleted file mode 100644 index 95d339597f3..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/GremlinProfileQueryExample.java +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.neptune.data; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; - -import java.net.URI; -import java.time.Duration; - -/** - * Example: Running a Gremlin Profile query using the AWS SDK for Java V2. - * - * ---------------------------------------------------------------------------------- - * VPC Networking Requirement: - * ---------------------------------------------------------------------------------- - * Amazon Neptune must be accessed from **within the same VPC** as the Neptune cluster. - * It does not expose a public endpoint, so this code must be executed from: - * - An EC2 instance, Lambda function, ECS task, Cloud9 IDE, or - * - A connected environment (VPN, Direct Connect, or peered VPC). - * - * Notes: - * - Ensure Neptune's security group allows inbound traffic on port 8182. - * - Replace the endpoint below with your Neptune cluster's HTTPS endpoint. - * - To verify access, run: curl https://:8182/status - * ---------------------------------------------------------------------------------- - */ -public class GremlinProfileQueryExample { - - // Specify the endpoint. You can obtain an endpoint by running - // the main scenario. - private static final String NEPTUNE_ENDPOINT = "https://:8182"; - - public static void main(String[] args) { - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - executeGremlinProfileQuery(client); - } catch (NeptunedataException e) { - System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } - - private static void executeGremlinProfileQuery(NeptunedataClient client) { - System.out.println("Executing Gremlin PROFILE query..."); - - ExecuteGremlinProfileQueryRequest request = ExecuteGremlinProfileQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") - .build(); - - ExecuteGremlinProfileQueryResponse response = client.executeGremlinProfileQuery(request); - if (response.output() != null) { - System.out.println("Query Profile Output:"); - System.out.println(response.output()); - } else { - System.out.println("No output returned from the profile query."); - } - } -} \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java deleted file mode 100644 index 92c1b815789..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinExplainAndProfileExample.java +++ /dev/null @@ -1,111 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.neptune.data; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinExplainQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinProfileQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; -import java.net.URI; -import java.time.Duration; - -/** - * This example demonstrates how to run a Gremlin Explain and Profile query on an Amazon Neptune database - * using the AWS SDK for Java V2. - * - * VPC NETWORKING REQUIREMENT: - * ---------------------------------------------------------------------- - * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. - * It does not expose a public endpoint. This means: - * - * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, - * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. - * - * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) - * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. - * - * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** - * from the instance or environment where this Java code runs. - * - * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. - * - * TIP: - * You can test connectivity using `curl` or `telnet` from your instance to: - * curl https://:8182/status - * If this fails, it’s likely a networking or security group issue. - * - * ---------------------------------------------------------------------- - */ -public class NeptuneGremlinExplainAndProfileExample { - - // Specify the endpoint. You can obtain an endpoint by running - // the main scenario. - private static final String NEPTUNE_ENDPOINT = "https://[Specify-Your-Endpoint]:8182"; - - public static void main(String[] args) { - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - runExplainQuery(client); - runProfileQuery(client); - } catch (NeptunedataException e) { - System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } - - private static void runExplainQuery(NeptunedataClient client) { - System.out.println("Running Gremlin EXPLAIN query..."); - - ExecuteGremlinExplainQueryRequest explainRequest = ExecuteGremlinExplainQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") - .build(); - - ExecuteGremlinExplainQueryResponse explainResponse = client.executeGremlinExplainQuery(explainRequest); - - System.out.println("Explain Query Result:"); - if (explainResponse.output() != null) { - System.out.println(explainResponse.output()); - } else { - System.out.println("No explain output returned."); - } - } - - private static void runProfileQuery(NeptunedataClient client) { - System.out.println("Running Gremlin PROFILE query..."); - - ExecuteGremlinProfileQueryRequest profileRequest = ExecuteGremlinProfileQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") - .build(); - - ExecuteGremlinProfileQueryResponse profileResponse = client.executeGremlinProfileQuery(profileRequest); - - System.out.println("Profile Query Result:"); - if (profileResponse.output() != null) { - System.out.println(profileResponse.output()); - } else { - System.out.println("No profile output returned."); - } - } -} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java deleted file mode 100644 index 2194d0e1080..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/NeptuneGremlinQueryExample.java +++ /dev/null @@ -1,93 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.neptune.data; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteGremlinQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; - -import java.net.URI; -import java.time.Duration; - -/** - * This example demonstrates how to execute a Gremlin query on an Amazon Neptune database using the AWS SDK for Java V2. - * - * VPC NETWORKING REQUIREMENT: - * ---------------------------------------------------------------------- - * Amazon Neptune is designed to be **accessed from within an Amazon VPC**. - * It does not expose a public endpoint. This means: - * - * 1. Your Java application must run **within the same VPC** (e.g., via an EC2 instance, Lambda function, ECS task, - * or AWS Cloud9 environment), or from a peered VPC that has network access to Neptune. - * - * 2. You cannot run this example directly from your local machine (e.g., via IntelliJ or PyCharm on your laptop) - * unless you set up a VPN or AWS Direct Connect that bridges your local environment to your VPC. - * - * 3. You must ensure the **VPC Security Group** attached to your Neptune cluster allows **inbound access on port 8182** - * from the instance or environment where this Java code runs. - * - * 4. The `endpointOverride()` must use the **HTTPS Neptune endpoint** including the `:8182` port. - * - * TIP: - * You can test connectivity using `curl` or `telnet` from your instance to: - * curl https://:8182/status - * If this fails, it’s likely a networking or security group issue. - * - * ---------------------------------------------------------------------- - */ - -public class NeptuneGremlinQueryExample { - - public static void main(String[] args) { - - - // Specify the endpoint. You can obtain an endpoint by running - // the main scenario. - String neptuneEndpoint = "https://[Specify Endpoint]:8182"; - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(neptuneEndpoint)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - System.out.println("Querying Neptune..."); - - ExecuteGremlinQueryRequest request = ExecuteGremlinQueryRequest.builder() - .gremlinQuery("g.V().has('code', 'ANC')") - .build(); - - ExecuteGremlinQueryResponse response = client.executeGremlinQuery(request); - - System.out.println("Full Response:"); - System.out.println(response); - - // Retrieve and print the result - if (response.result() != null) { - System.out.println("Query Result:"); - System.out.println(response.result().toString()); - } else { - System.out.println("No result returned from the query."); - } - } catch (NeptunedataException e) { - System.err.println("Error calling Neptune: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } -} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java deleted file mode 100644 index f563d1ae9e6..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/OpenCypherExplainExample.java +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.example.neptune.data; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherExplainQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherExplainQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; - -import java.net.URI; -import java.time.Duration; - -/** - * Example: Running an OpenCypher EXPLAIN query on Amazon Neptune using AWS SDK for Java V2. - * - * ------------------------------------------------------------------------------ - * VPC NETWORKING REQUIREMENT: - * ------------------------------------------------------------------------------ - * Amazon Neptune must be accessed from within an Amazon VPC. It does not expose - * a public endpoint. - * - * 1. This Java application must run from an environment inside the same VPC as the Neptune cluster, - * such as EC2, ECS, AWS Lambda, AWS Cloud9, or a connected network via VPN or Direct Connect. - * - * 2. Ensure the Neptune cluster’s security group allows inbound access on port 8182 from the host - * running this application. - * - * 3. Use the Neptune HTTPS endpoint with port 8182 in `endpointOverride()`. - * - * Test connectivity with: - * curl https://:8182/status - * ------------------------------------------------------------------------------ - */ -public class OpenCypherExplainExample { - - private static final String NEPTUNE_ENDPOINT = "https://:8182"; - - public static void main(String[] args) { - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - System.out.println("Executing OpenCypher EXPLAIN query..."); - - ExecuteOpenCypherExplainQueryRequest request = ExecuteOpenCypherExplainQueryRequest.builder() - .openCypherQuery("MATCH (n {code: 'ANC'}) RETURN n") - .explainMode("debug") - .build(); - - ExecuteOpenCypherExplainQueryResponse response = client.executeOpenCypherExplainQuery(request); - - if (response.results() != null) { - System.out.println("Explain Results:"); - System.out.println(response.results().asUtf8String()); - } else { - System.out.println("No explain results returned."); - } - - } catch (NeptunedataException e) { - System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } -} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java deleted file mode 100644 index b9c0849d460..00000000000 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/data/eptuneGremlinExplainAndProfileExample.java +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. -// SPDX-License-Identifier: Apache-2.0 - - -package com.example.neptune.data; - -import software.amazon.awssdk.auth.credentials.DefaultCredentialsProvider; -import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration; -import software.amazon.awssdk.http.apache.ApacheHttpClient; -import software.amazon.awssdk.regions.Region; -import software.amazon.awssdk.services.neptunedata.NeptunedataClient; -import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherQueryRequest; -import software.amazon.awssdk.services.neptunedata.model.ExecuteOpenCypherQueryResponse; -import software.amazon.awssdk.services.neptunedata.model.NeptunedataException; - -import java.net.URI; -import java.time.Duration; -import java.util.Map; - -/** - * Example: Running OpenCypher queries on Amazon Neptune using AWS SDK for Java V2. - * - * ------------------------------------------------------------------------------ - * VPC NETWORKING REQUIREMENT: - * ------------------------------------------------------------------------------ - * Amazon Neptune is accessible only within an Amazon VPC. This means: - * - * 1. This Java code must run within the same VPC as your Neptune cluster. - * Options include EC2, ECS, Lambda, AWS Cloud9, or a VPC-connected environment. - * - * 2. You must allow inbound access on port 8182 to Neptune from the host where this - * Java program runs (via the cluster's Security Group). - * - * 3. The endpoint used must be the Neptune HTTPS endpoint (e.g., https://your-neptune-endpoint:8182). - * - * To test network access from your environment: - * curl https://:8182/status - * ------------------------------------------------------------------------------ - */ -public class eptuneGremlinExplainAndProfileExample { - - // Specify the endpoint. You can obtain an endpoint by running - // the main scenario. - private static final String NEPTUNE_ENDPOINT = "https://:8182"; - - public static void main(String[] args) { - - NeptunedataClient client = NeptunedataClient.builder() - .credentialsProvider(DefaultCredentialsProvider.create()) - .region(Region.US_EAST_1) - .endpointOverride(URI.create(NEPTUNE_ENDPOINT)) - .httpClientBuilder(ApacheHttpClient.builder() - .connectionTimeout(Duration.ofSeconds(10)) - .socketTimeout(Duration.ofSeconds(30))) - .overrideConfiguration(ClientOverrideConfiguration.builder() - .apiCallAttemptTimeout(Duration.ofSeconds(30)) - .build()) - .build(); - - try { - runOpenCypherWithoutParameters(client); - runOpenCypherWithParameters(client); - } catch (NeptunedataException e) { - System.err.println("Neptune error: " + e.awsErrorDetails().errorMessage()); - } catch (Exception e) { - System.err.println("Unexpected error: " + e.getMessage()); - } finally { - client.close(); - } - } - - private static void runOpenCypherWithoutParameters(NeptunedataClient client) { - System.out.println("\nExecuting OpenCypher query WITHOUT parameters..."); - - ExecuteOpenCypherQueryRequest request = ExecuteOpenCypherQueryRequest.builder() - .openCypherQuery("MATCH (n {code: 'ANC'}) RETURN n") - .build(); - - ExecuteOpenCypherQueryResponse response = client.executeOpenCypherQuery(request); - - if (response.results() != null) { - System.out.println("Results:"); - System.out.println(response.results()); - } else { - System.out.println("No results returned."); - } - } - - private static void runOpenCypherWithParameters(NeptunedataClient client) { - System.out.println("\nExecuting OpenCypher query WITH parameters..."); - - ExecuteOpenCypherQueryRequest request = ExecuteOpenCypherQueryRequest.builder() - .openCypherQuery("MATCH (n {code: $code}) RETURN n") - .parameters(Map.of("code", "ANC").toString()) - .build(); - - ExecuteOpenCypherQueryResponse response = client.executeOpenCypherQuery(request); - - if (response.results() != null) { - System.out.println("Results:"); - System.out.println(response.results()); - } else { - System.out.println("No results returned."); - } - } -} diff --git a/scenarios/basics/neptune/SPECIFICATION.md b/scenarios/basics/neptune/SPECIFICATION.md index 8092f17f7d6..c7f22d05f20 100644 --- a/scenarios/basics/neptune/SPECIFICATION.md +++ b/scenarios/basics/neptune/SPECIFICATION.md @@ -3,14 +3,15 @@ ## Overview This SDK Basics scenario demonstrates how to interact with Amazon Neptune using an AWS SDK. It demonstrates various tasks such as creating a Neptune DB Subnet Group, creating a Neptune Cluster, -creating a Neptune DB Instance, and so on. Finally this scenario demonstrates how -to clean up resources. Its purpose is to demonstrate how to get up and running with Amazon Neptune and an AWS SDK. +creating a Neptune DB Instance, and so on. + +Finally this scenario demonstrates how to clean up resources. Its purpose is to demonstrate how to get up and running with Amazon Neptune and an AWS SDK. ## Resources This Basics scenario does not require any additional AWS resources. ## Hello Amazon Neptune -This program is intended for users not familiar with the Amazon Neptune Service to easily get up and running. The program invokes `describeDBSubnetGroupsPaginator`to iterate through subnet groups. +This program is intended for users not familiar with Amazon Neptune to easily get up and running. The program invokes `describeDBSubnetGroupsPaginator`to iterate through subnet groups. ## Basics Scenario Program Flow The Amazon Neptune Basics scenario executes the following operations. From 4ff54a9dcca7ea7c7c01addba4784d00e3eb671d Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 12:09:53 -0400 Subject: [PATCH 06/10] added SOS --- .../main/java/com/example/neptune/scenerio/NeptuneActions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java index 99a84934177..f1b85edd6bd 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -387,7 +387,7 @@ private void checkStatusRecursive(String instanceId, String desiredStatus, long } }); } - // snippet-start:[neptune.java2.describe.dbinstance.main] + // snippet-end:[neptune.java2.describe.dbinstance.main] private String formatElapsedTime(int seconds) { From beb69e21f2a263c98129ea2649ffc4e1a8599f9d Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 12:20:53 -0400 Subject: [PATCH 07/10] added SOS --- .../main/java/com/example/neptune/scenerio/NeptuneActions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java index f1b85edd6bd..040d28441ad 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -290,7 +290,7 @@ public void stopDBCluster(String clusterIdentifier) { neptuneClient.stopDBCluster(clusterRequest); logger.info("DB Cluster Stopped"); } - // snippet-stop:[neptune.java2.stop.cluster.main] + // snippet-end:[neptune.java2.stop.cluster.main] // snippet-start:[neptune.java2.describe.cluster.main] From bd651d622f0753373c7d8c88b898a14878369b4f Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 14:14:15 -0400 Subject: [PATCH 08/10] added all SOS snippet tags --- .doc_gen/metadata/neptune_metadata.yaml | 169 ++++++++++++++++++ .../neptune/scenerio/NeptuneActions.java | 3 +- .../neptune/scenerio/NeptuneScenario.java | 7 +- scenarios/basics/neptune/README.md | 25 ++- 4 files changed, 185 insertions(+), 19 deletions(-) diff --git a/.doc_gen/metadata/neptune_metadata.yaml b/.doc_gen/metadata/neptune_metadata.yaml index 4d036fb6005..46e080181fd 100644 --- a/.doc_gen/metadata/neptune_metadata.yaml +++ b/.doc_gen/metadata/neptune_metadata.yaml @@ -12,3 +12,172 @@ neptune_Hello: - neptune.java2.hello.main services: neptune: {DescribeDBClustersPaginator} +neptune_DeleteDBSubnetGroup: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.delete.subnet.group.main + services: + neptune: {DeleteDBSubnetGroup} +neptune_DeleteDBCluster: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.delete.cluster.main + services: + neptune: {DeleteDBCluster} +neptune_DeleteDBInstance: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.delete.instance.main + services: + neptune: {DeleteDBInstance} +neptune_StartDBCluster: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.start.cluster.main + services: + neptune: {StartDBCluster} +neptune_StopDBCluster: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.stop.cluster.main + services: + neptune: {StopDBCluster} +neptune_DescribeDBClusters: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.describe.cluster.main + services: + neptune: {DescribeDBClusters} +neptune_DescribeDBInstances: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.describe.dbinstance.main + services: + neptune: {DescribeDBInstances} +neptune_CreateDBInstance: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.create.dbinstance.main + services: + neptune: {CreateDBInstance} +neptune_CreateDBCluster: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.create.cluster.main + services: + neptune: {CreateDBCluster} +neptune_CreateDBSubnetGroup: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.create.subnet.main + services: + neptune: {CreateDBSubnetGroup} +neptune_CreateDBSubnetGroup: + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: + snippet_tags: + - neptune.java2.create.subnet.main + services: + neptune: {CreateDBSubnetGroup} +neptune_Scenario: + synopsis_list: + - Create an &neptunelong; Subnet Group. + - Create an &neptune; Cluster. + - Create an &neptune; Instance. + - Check the status of the &neptune; Instance. + - Show &neptune; cluster details. + - Stop the &neptune; cluster. + - Start the &neptune; cluster. + - Delete the &neptune; Assets. + category: Basics + languages: + Java: + versions: + - sdk_version: 2 + github: javav2/example_code/neptune + sdkguide: + excerpts: + - description: Run an interactive scenario demonstrating &neptune; features. + snippet_tags: + - neptune.java2.scenario.main + - description: A wrapper class for &neptune; SDK methods. + snippet_tags: + - neptune.java2.actions.main + services: + neptune: {} diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java index 040d28441ad..7a898506ce6 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -41,6 +41,7 @@ import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; +// snippet-start:[neptune.java2.actions.main] public class NeptuneActions { private CompletableFuture instanceCheckFuture; private long instanceCheckStartTime; @@ -420,7 +421,6 @@ public CompletableFuture createDBInstanceAsync(String dbInstanceId, Stri .dbInstanceClass("db.r5.large") .engine("neptune") .dbClusterIdentifier(dbClusterId) - // .availabilityZone("us-east-1c") .build(); return getAsyncClient().createDBInstance(request) @@ -527,3 +527,4 @@ private List getSubnetIds(String vpcId) { } } } +// snippet-end:[neptune.java2.actions.main] \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java index 36f2e8925e5..bbaf12ff2f7 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java @@ -5,11 +5,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; - import java.util.Scanner; -//TIP To Run code, press or -// click the icon in the gutter. +// snippet-start:[neptune.java2.scenario.main] public class NeptuneScenario { public static final String DASHES = new String(new char[80]).replace("\0", "-"); private static final Logger logger = LoggerFactory.getLogger(NeptuneScenario.class); @@ -159,4 +157,5 @@ private static void waitForInputToContinue(Scanner scanner) { } } } -} \ No newline at end of file +} +// snippet-end:[neptune.java2.scenario.main] \ No newline at end of file diff --git a/scenarios/basics/neptune/README.md b/scenarios/basics/neptune/README.md index 5c3da3454c2..35e834aff99 100644 --- a/scenarios/basics/neptune/README.md +++ b/scenarios/basics/neptune/README.md @@ -1,22 +1,19 @@ ## Overview -This AWS IoT Fleetwise basic scenario demonstrates how to interact with the AWS IoT FleetWise service using an AWS SDK. The scenario covers various operations such as creating a collection of standardized signals, creating a model manifest, creating a vehicle, and so on. +This Amazon Neptune basic scenario demonstrates how to interact with Amazon Neptune using an AWS SDK. The scenario covers various operations such as creating a cluster, creating an instance, starting and stopping the cluster, and so on. ## Key Operations -1. **Create an AWS Fleetwise signal catalog**: - - This step creates an AWS Fleetwise signal catalog by invoking the `createSignalCatalog`method. +1. **Create a Neptune DB Subnet Group**: + - Creates a Neptune DB Subnet Group by invoking `createDBSubnetGroup`. -2. **Create an AWS IoT Fleetwise fleet**: - - This operation creates an AWS Fleetwise fleet by invoking the `createFleet`method. +2. **Create a Neptune Cluster**: + - Description: Creates a Neptune Cluster by invoking `createDBCluster`. -3. **Create a model manifest**: - - This operation creates an AWS Fleetwise model manifest by invoking the `createModelManifest`method. +3. **Create a Neptune DB Instance**: + - Description: Creates a Neptune DB Instance by invoking `createDBInstance`. -4. **Create a decoder manifest**: - - This operation creates an AWS Fleetwise decoder manifest by invoking the `createDecoderManifest`method. - -5. **Create a vehicle**: - - This operation creates an AWS Fleetwise vehicle by invoking the `createVehicle`method. +4. **Check the status of the Neptune DB Instance**: + - Description: Check the status of the DB instance by invoking `describeDBInstances`. Poll the instance until it reaches an `availbale`state. **Note** See the [Engineering specification](SPECIFICATION.md) for a full listing of operations. @@ -29,11 +26,11 @@ This Basics scenario does not require any additional AWS resources. This scenario example will be implemented in the following languages: - Java -- JavaScript +- Python - Kotlin ## Additional Reading -- [AWS IoT Fleetwise Documentation](https://docs.aws.amazon.com/iot-fleetwise/latest/developerguide/what-is-iotfleetwise.html) +- [Amazon Neptune Documentation](https://docs.aws.amazon.com/neptune/latest/userguide/intro.html) Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. SPDX-License-Identifier: Apache-2.0 From 1ccb2212592a3c9ba9d449639cf2e6d298137403 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 15:55:36 -0400 Subject: [PATCH 09/10] updated Actions --- .../com/example/neptune/HelloNeptune.java | 68 ++++++----- .../neptune/scenerio/NeptuneActions.java | 45 ++++++-- .../neptune/scenerio/NeptuneScenario.java | 109 ++++++++++-------- 3 files changed, 137 insertions(+), 85 deletions(-) diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java index c9a520b4704..60b1b462b62 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/HelloNeptune.java @@ -3,12 +3,13 @@ package com.example.neptune; +import org.reactivestreams.Subscriber; +import org.reactivestreams.Subscription; import software.amazon.awssdk.core.async.SdkPublisher; import software.amazon.awssdk.services.neptune.NeptuneAsyncClient; import software.amazon.awssdk.services.neptune.model.DescribeDbClustersRequest; import software.amazon.awssdk.services.neptune.model.DescribeDbClustersResponse; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutionException; // snippet-start:[neptune.java2.hello.main] /** @@ -20,41 +21,52 @@ * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html */ public class HelloNeptune { - - private static final String NEPTUNE_ENDPOINT = "https://[Specify-Your-Endpoint]:8182"; - public static void main(String[] args) { NeptuneAsyncClient neptuneClient = NeptuneAsyncClient.create(); - describeDbCluster(neptuneClient); + describeDbCluster(neptuneClient).join(); // This ensures the async code runs to completion } - /** - * Describes the Amazon Neptune DB clusters using a paginator. - * - * @param neptuneClient the Amazon Neptune asynchronous client - */ - public static void describeDbCluster(NeptuneAsyncClient neptuneClient) { + public static CompletableFuture describeDbCluster(NeptuneAsyncClient neptuneClient) { DescribeDbClustersRequest request = DescribeDbClustersRequest.builder() - .maxRecords(20) // Optional: limit per page + .maxRecords(20) .build(); - SdkPublisher paginator= neptuneClient.describeDBClustersPaginator(request); - CompletableFuture future = paginator - .subscribe(response -> { - for (var cluster : response.dbClusters()) { - System.out.println("Cluster Identifier: " + cluster.dbClusterIdentifier()); - System.out.println("Status: " + cluster.status()); - } + SdkPublisher paginator = neptuneClient.describeDBClustersPaginator(request); + CompletableFuture future = new CompletableFuture<>(); + + paginator.subscribe(new Subscriber() { + private Subscription subscription; + + @Override + public void onSubscribe(Subscription s) { + this.subscription = s; + s.request(Long.MAX_VALUE); // request all items + } + + @Override + public void onNext(DescribeDbClustersResponse response) { + response.dbClusters().forEach(cluster -> { + System.out.println("Cluster Identifier: " + cluster.dbClusterIdentifier()); + System.out.println("Status: " + cluster.status()); }); + } + + @Override + public void onError(Throwable t) { + future.completeExceptionally(t); + } + + @Override + public void onComplete() { + future.complete(null); + } + }); - // Wait for completion and handle errors - try { - future.get(); // Waits for all pages to be processed - } catch (InterruptedException | ExecutionException e) { - System.err.println("Failed to describe DB clusters: " + e.getMessage()); - } finally { + return future.whenComplete((result, throwable) -> { neptuneClient.close(); - } + if (throwable != null) { + System.err.println("Error describing DB clusters: " + throwable.getMessage()); + } + }); } -} -// snippet-end:[neptune.java2.hello.main] \ No newline at end of file +}// snippet-end:[neptune.java2.hello.main] \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java index 7a898506ce6..d1df4a1d5a4 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneActions.java @@ -13,28 +13,28 @@ import software.amazon.awssdk.services.ec2.Ec2Client; import software.amazon.awssdk.services.ec2.model.DescribeSubnetsRequest; import software.amazon.awssdk.services.ec2.model.DescribeSubnetsResponse; +import software.amazon.awssdk.services.ec2.model.DescribeVpcsRequest; +import software.amazon.awssdk.services.ec2.model.Filter; +import software.amazon.awssdk.services.ec2.model.DescribeVpcsResponse; import software.amazon.awssdk.services.ec2.model.Subnet; +import software.amazon.awssdk.services.ec2.model.Vpc; import software.amazon.awssdk.services.neptune.NeptuneAsyncClient; import software.amazon.awssdk.services.neptune.NeptuneClient; import software.amazon.awssdk.services.neptune.model.*; import software.amazon.awssdk.services.neptune.model.CreateDbClusterRequest; -import software.amazon.awssdk.services.neptune.model.CreateDbClusterResponse; import software.amazon.awssdk.services.neptune.model.CreateDbInstanceRequest; -import software.amazon.awssdk.services.neptune.model.CreateDbInstanceResponse; import software.amazon.awssdk.services.neptune.model.CreateDbSubnetGroupRequest; -import software.amazon.awssdk.services.neptune.model.CreateDbSubnetGroupResponse; import software.amazon.awssdk.services.neptune.model.DBCluster; import software.amazon.awssdk.services.neptune.model.DBInstance; import software.amazon.awssdk.services.neptune.model.DeleteDbClusterRequest; import software.amazon.awssdk.services.neptune.model.DeleteDbInstanceRequest; import software.amazon.awssdk.services.neptune.model.DeleteDbSubnetGroupRequest; -import software.amazon.awssdk.services.neptune.model.DescribeDbClustersResponse; import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesRequest; -import software.amazon.awssdk.services.neptune.model.DescribeDbInstancesResponse; import software.amazon.awssdk.services.neptune.model.DescribeDbClustersRequest; import software.amazon.awssdk.services.neptunegraph.model.ServiceQuotaExceededException; import java.time.Duration; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionException; @@ -44,13 +44,11 @@ // snippet-start:[neptune.java2.actions.main] public class NeptuneActions { private CompletableFuture instanceCheckFuture; - private long instanceCheckStartTime; private static NeptuneAsyncClient neptuneAsyncClient; private final Region region = Region.US_EAST_1; private static final Logger logger = LoggerFactory.getLogger(NeptuneActions.class); private final NeptuneClient neptuneClient = NeptuneClient.builder().region(region).build(); - /** * Retrieves an instance of the NeptuneAsyncClient. *

@@ -487,7 +485,10 @@ public CompletableFuture createDBClusterAsync(String dbName) { * @return a CompletableFuture that, when completed, returns the Amazon Resource Name (ARN) of the created subnet group * @throws CompletionException if the operation fails, with a cause that may be a ServiceQuotaExceededException if the request would exceed the maximum quota */ - public CompletableFuture createSubnetGroupAsync(String vpcId, String groupName) { + public CompletableFuture createSubnetGroupAsync(String vpcId2, String groupName) { + + // Get the Amazon Virtual Private Cloud (VPC) where the Neptune cluster and resources will be created + String vpcId = getDefaultVpcId(); List subnetList = getSubnetIds(vpcId); CreateDbSubnetGroupRequest request = CreateDbSubnetGroupRequest.builder() .dbSubnetGroupName(groupName) @@ -526,5 +527,33 @@ private List getSubnetIds(String vpcId) { .collect(Collectors.toList()); } } + + public static String getDefaultVpcId() { + Ec2Client ec2 = Ec2Client.builder() + .region(Region.US_EAST_1) + .build(); + + Filter myFilter = Filter.builder() + .name("isDefault") + .values("true") + .build(); + + List filterList = new ArrayList<>(); + filterList.add(myFilter); + + DescribeVpcsRequest request = DescribeVpcsRequest.builder() + .filters(filterList) + .build(); + + + DescribeVpcsResponse response = ec2.describeVpcs(request); + if (!response.vpcs().isEmpty()) { + Vpc defaultVpc = response.vpcs().get(0); + return defaultVpc.vpcId(); + } else { + throw new RuntimeException("No default VPC found in this region."); + } + } } + // snippet-end:[neptune.java2.actions.main] \ No newline at end of file diff --git a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java index bbaf12ff2f7..1341f740a33 100644 --- a/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java +++ b/javav2/example_code/neptune/src/main/java/com/example/neptune/scenerio/NeptuneScenario.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import java.util.Scanner; // snippet-start:[neptune.java2.scenario.main] @@ -15,42 +16,52 @@ public class NeptuneScenario { static NeptuneActions neptuneActions = new NeptuneActions(); public static void main(String[] args) { - String subnetGroupName = "neptuneSubnetGroup56" ; - String vpcId = "vpc-e97a4393" ; - String clusterName = "neptuneCluster56" ; - String dbInstanceId = "neptuneDB56" ; + final String usage = + """ + Usage: + + + Where: + subnetGroupName - The name of an existing Neptune DB subnet group that includes subnets in at least two Availability Zones. + vpcId - The ID of the Amazon Virtual Private Cloud (VPC) where the Neptune cluster and resources will be created. + clusterName - The unique identifier for the Neptune DB cluster. + dbInstanceId - The identifier for a specific Neptune DB instance within the cluster. + """; + String subnetGroupName = "neptuneSubnetGroup56"; + String clusterName = "neptuneCluster56"; + String dbInstanceId = "neptuneDB56"; logger.info(""" - Amazon Neptune is a fully managed graph - database service by AWS, designed specifically - for handling complex relationships and connected - datasets at scale. It supports two popular graph models: - property graphs (via openCypher and Gremlin) and RDF - graphs (via SPARQL). This makes Neptune ideal for - use cases such as knowledge graphs, fraud detection, - social networking, recommendation engines, and - network management, where relationships between - entities are central to the data. - - Being fully managed, Neptune handles database - provisioning, patching, backups, and replication, - while also offering high availability and durability - within AWS's infrastructure. - - For developers, programming with Neptune allows - for building intelligent, relationship-aware - applications that go beyond traditional tabular - databases. Developers can use the AWS SDK for Java - V2 to automate infrastructure operations - (via NeptuneClient). - - Let's get started... - """); + Amazon Neptune is a fully managed graph + database service by AWS, designed specifically + for handling complex relationships and connected + datasets at scale. It supports two popular graph models: + property graphs (via openCypher and Gremlin) and RDF + graphs (via SPARQL). This makes Neptune ideal for + use cases such as knowledge graphs, fraud detection, + social networking, recommendation engines, and + network management, where relationships between + entities are central to the data. + + Being fully managed, Neptune handles database + provisioning, patching, backups, and replication, + while also offering high availability and durability + within AWS's infrastructure. + + For developers, programming with Neptune allows + for building intelligent, relationship-aware + applications that go beyond traditional tabular + databases. Developers can use the AWS SDK for Java + V2 to automate infrastructure operations + (via NeptuneClient). + + Let's get started... + """); waitForInputToContinue(scanner); - runScenario(subnetGroupName, vpcId, dbInstanceId, clusterName); + runScenario(subnetGroupName, vpcId, dbInstanceId, clusterName); } - public static void runScenario(String subnetGroupName, String vpcId, String dbInstanceId, String clusterName) { + public static void runScenario(String subnetGroupName, String vpcId, String dbInstanceId, String clusterName) { logger.info(DASHES); logger.info("1. Create a Neptune DB Subnet Group"); logger.info("The Neptune DB subnet group is used when launching a Neptune cluster"); @@ -78,9 +89,9 @@ public static void runScenario(String subnetGroupName, String vpcId, String dbI logger.info(DASHES); logger.info("4. Check the status of the Neptune DB Instance"); logger.info(""" - In this step, we will wait until the DB instance - becomes available. This may take around 10 minutes. - """); + In this step, we will wait until the DB instance + becomes available. This may take around 10 minutes. + """); waitForInputToContinue(scanner); neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); waitForInputToContinue(scanner); @@ -96,25 +107,25 @@ public static void runScenario(String subnetGroupName, String vpcId, String dbI logger.info(DASHES); logger.info("6. Stop the Amazon Neptune cluster"); logger.info(""" - Once stopped, this step polls the status - until the cluster is in a stopped state. - """); + Once stopped, this step polls the status + until the cluster is in a stopped state. + """); waitForInputToContinue(scanner); neptuneActions.stopDBCluster(dbClusterId); - neptuneActions.waitForClusterStatus(dbClusterId,"stopped"); + neptuneActions.waitForClusterStatus(dbClusterId, "stopped"); waitForInputToContinue(scanner); logger.info(DASHES); logger.info(DASHES); logger.info("7. Start the Amazon Neptune cluster"); logger.info(""" - Once started, this step polls the clusters - status until it's in an available state. - We will also poll the instance status. - """); + Once started, this step polls the clusters + status until it's in an available state. + We will also poll the instance status. + """); waitForInputToContinue(scanner); neptuneActions.startDBCluster(dbClusterId); - neptuneActions.waitForClusterStatus(dbClusterId,"available"); + neptuneActions.waitForClusterStatus(dbClusterId, "available"); neptuneActions.checkInstanceStatus(dbInstanceId, "available").join(); logger.info(DASHES); logger.info(DASHES); @@ -133,12 +144,12 @@ public static void runScenario(String subnetGroupName, String vpcId, String dbI logger.info(DASHES); logger.info( - """ - Thank you for checking out the Amazon Neptune Service Use demo. We hope you - learned something new, or got some inspiration for your own apps today. - For more AWS code examples, have a look at: - https://docs.aws.amazon.com/code-library/latest/ug/what-is-code-library.html - """); + """ + Thank you for checking out the Amazon Neptune Service Use demo. We hope you + learned something new, or got some inspiration for your own apps today. + For more AWS code examples, have a look at: + https://docs.aws.amazon.com/code-library/latest/ug/what-is-code-library.html + """); logger.info(DASHES); } From 46b7eb6357921d382d0fc676ecc36cf2c20067f5 Mon Sep 17 00:00:00 2001 From: Macdonald Date: Fri, 23 May 2025 16:17:40 -0400 Subject: [PATCH 10/10] updated Actions --- .github/workflows/validate-doc-metadata.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-doc-metadata.yml b/.github/workflows/validate-doc-metadata.yml index 1d79b9753de..099b7565567 100644 --- a/.github/workflows/validate-doc-metadata.yml +++ b/.github/workflows/validate-doc-metadata.yml @@ -16,7 +16,7 @@ jobs: - name: checkout repo content uses: actions/checkout@v4 - name: validate metadata - uses: awsdocs/aws-doc-sdk-examples-tools@2025.16.2 + uses: awsdocs/aws-doc-sdk-examples-tools@2025.20.1 with: doc_gen_only: "False" strict_titles: "True"