diff --git a/.doc_gen/metadata/controltower_metadata.yaml b/.doc_gen/metadata/controltower_metadata.yaml
index 083079b4db1..01f3fcfc2ab 100644
--- a/.doc_gen/metadata/controltower_metadata.yaml
+++ b/.doc_gen/metadata/controltower_metadata.yaml
@@ -4,6 +4,15 @@ controltower_Hello:
synopsis: get started using &CTower;.
category: Hello
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.hello.main
Python:
versions:
- sdk_version: 3
@@ -25,6 +34,15 @@ controltower_Hello:
controltower_ListBaselines:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.list_baselines.main
Python:
versions:
- sdk_version: 3
@@ -47,6 +65,15 @@ controltower_ListBaselines:
controltower_ListEnabledBaselines:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.list_enabled_baselines.main
Python:
versions:
- sdk_version: 3
@@ -69,6 +96,15 @@ controltower_ListEnabledBaselines:
controltower_EnableBaseline:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.enable_baseline.main
Python:
versions:
- sdk_version: 3
@@ -91,6 +127,15 @@ controltower_EnableBaseline:
controltower_ResetEnabledBaseline:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.reset_enabled_baseline.main
Python:
versions:
- sdk_version: 3
@@ -113,6 +158,15 @@ controltower_ResetEnabledBaseline:
controltower_DisableBaseline:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.disable_baseline.main
Python:
versions:
- sdk_version: 3
@@ -135,6 +189,15 @@ controltower_DisableBaseline:
controltower_ListEnabledControls:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.list_enabled_controls.main
Python:
versions:
- sdk_version: 3
@@ -157,6 +220,15 @@ controltower_ListEnabledControls:
controltower_EnableControl:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.enable_control.main
Python:
versions:
- sdk_version: 3
@@ -179,6 +251,15 @@ controltower_EnableControl:
controltower_GetControlOperation:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.get_control_operation.main
Python:
versions:
- sdk_version: 3
@@ -201,6 +282,15 @@ controltower_GetControlOperation:
controltower_DisableControl:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.disable_control.main
Python:
versions:
- sdk_version: 3
@@ -223,6 +313,15 @@ controltower_DisableControl:
controltower_ListLandingZones:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.list_landing_zones.main
Python:
versions:
- sdk_version: 3
@@ -245,6 +344,15 @@ controltower_ListLandingZones:
controltower_GetBaselineOperation:
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description:
+ snippet_tags:
+ - controltower.java2.list_landing_zones.main
Python:
versions:
- sdk_version: 3
@@ -272,6 +380,16 @@ controltower_Scenario:
- List, enable, get, and disable controls.
category: Basics
languages:
+ Java:
+ versions:
+ - sdk_version: 2
+ github: javav2/example_code/controltower
+ sdkguide:
+ excerpts:
+ - description: Run an interactive scenario demonstrating &CTowerlong; features.
+ snippet_tags:
+ - controltower.java2.controltower_scenario.main
+ - controltower.java2.controltower_actions.main
Python:
versions:
- sdk_version: 3
diff --git a/javav2/example_code/controltower/README.md b/javav2/example_code/controltower/README.md
new file mode 100644
index 00000000000..09d4fcc4a63
--- /dev/null
+++ b/javav2/example_code/controltower/README.md
@@ -0,0 +1,119 @@
+# AWS Control Tower code examples for the SDK for Java 2.x
+
+## Overview
+
+Shows how to use the AWS SDK for Java 2.x to work with AWS Control Tower.
+
+
+
+
+_AWS Control Tower enables you to enforce and manage governance rules for security, operations, and compliance at scale across all your organizations and accounts._
+
+## ⚠ Important
+
+* Running this code might result in charges to your AWS account. For more details, see [AWS Pricing](https://aws.amazon.com/pricing/) and [Free Tier](https://aws.amazon.com/free/).
+* Running the tests might result in charges to your AWS account.
+* We recommend that you grant your code least privilege. At most, grant only the minimum permissions required to perform the task. For more information, see [Grant least privilege](https://docs.aws.amazon.com/IAM/latest/UserGuide/best-practices.html#grant-least-privilege).
+* This code is not tested in every AWS Region. For more information, see [AWS Regional Services](https://aws.amazon.com/about-aws/global-infrastructure/regional-product-services).
+
+
+
+
+## Code examples
+
+### Prerequisites
+
+For prerequisites, see the [README](../../README.md#Prerequisites) in the `javav2` folder.
+
+
+
+
+
+### Get started
+
+- [Hello AWS Control Tower](src/main/java/com/example/controltower/HelloControlTower.java#L28) (`ListBaselines`)
+
+
+### Basics
+
+Code examples that show you how to perform the essential operations within a service.
+
+- [Learn the basics](src/main/java/com/example/controltower/ControlTowerActions.java)
+
+
+### Single actions
+
+Code excerpts that show you how to call individual service functions.
+
+- [DisableBaseline](src/main/java/com/example/controltower/ControlTowerActions.java#L241)
+- [DisableControl](src/main/java/com/example/controltower/ControlTowerActions.java#L431)
+- [EnableBaseline](src/main/java/com/example/controltower/ControlTowerActions.java#L188)
+- [EnableControl](src/main/java/com/example/controltower/ControlTowerActions.java#L377)
+- [GetBaselineOperation](src/main/java/com/example/controltower/ControlTowerActions.java#L38)
+- [GetControlOperation](src/main/java/com/example/controltower/ControlTowerActions.java#L474)
+- [ListBaselines](src/main/java/com/example/controltower/ControlTowerActions.java#L88)
+- [ListEnabledBaselines](src/main/java/com/example/controltower/ControlTowerActions.java#L138)
+- [ListEnabledControls](src/main/java/com/example/controltower/ControlTowerActions.java#L324)
+- [ListLandingZones](src/main/java/com/example/controltower/ControlTowerActions.java#L38)
+- [ResetEnabledBaseline](src/main/java/com/example/controltower/ControlTowerActions.java#L548)
+
+
+
+
+
+## Run the examples
+
+### Instructions
+
+
+
+
+
+#### Hello AWS Control Tower
+
+This example shows you how to get started using AWS Control Tower.
+
+
+#### Learn the basics
+
+This example shows you how to do the following:
+
+- List landing zones.
+- List, enable, get, reset, and disable baselines.
+- List, enable, get, and disable controls.
+
+
+
+
+
+
+
+
+
+### Tests
+
+⚠ Running tests might result in charges to your AWS account.
+
+
+To find instructions for running these tests, see the [README](../../README.md#Tests)
+in the `javav2` folder.
+
+
+
+
+
+
+## Additional resources
+
+- [AWS Control Tower User Guide](https://docs.aws.amazon.com/controltower/latest/userguide/what-is-control-tower.html)
+- [AWS Control Tower API Reference](https://docs.aws.amazon.com/controltower/latest/APIReference/Welcome.html)
+- [SDK for Java 2.x AWS Control Tower reference](https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/controltower/package-summary.html)
+
+
+
+
+---
+
+Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/javav2/example_code/controltower/pom.xml b/javav2/example_code/controltower/pom.xml
new file mode 100644
index 00000000000..a7f0363c5a6
--- /dev/null
+++ b/javav2/example_code/controltower/pom.xml
@@ -0,0 +1,94 @@
+
+
+ 4.0.0
+ aws.example
+ controltower
+ 1.0-SNAPSHOT
+
+ 17
+ 17
+ UTF-8
+
+
+
+
+ software.amazon.awssdk
+ bom
+ 2.28.11
+ pom
+ import
+
+
+
+
+
+ software.amazon.awssdk
+ controltower
+
+
+ software.amazon.awssdk
+ controlcatalog
+
+
+ org.slf4j
+ slf4j-api
+ 2.0.7
+
+
+ ch.qos.logback
+ logback-classic
+ 1.4.8
+
+
+ software.amazon.awssdk
+ organizations
+
+
+
+ software.amazon.awssdk
+ url-connection-client
+ 2.36.2
+ compile
+
+
+ software.amazon.awssdk
+ sdk-core
+
+
+ org.junit.jupiter
+ junit-jupiter-engine
+ 5.10.0
+ test
+
+
+ org.junit.jupiter
+ junit-jupiter-api
+ 5.10.0
+ test
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.11.0
+
+ 17
+ 17
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 3.1.0
+
+ com.example.controltower.ControlTowerScenario
+ us-east-1
+
+
+
+
+
\ No newline at end of file
diff --git a/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerActions.java b/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerActions.java
new file mode 100644
index 00000000000..a41a9c6ba46
--- /dev/null
+++ b/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerActions.java
@@ -0,0 +1,586 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package com.example.controltower;
+
+import software.amazon.awssdk.services.controltower.ControlTowerClient;
+import software.amazon.awssdk.services.controltower.model.*;
+import software.amazon.awssdk.services.controltower.paginators.ListBaselinesIterable;
+import software.amazon.awssdk.services.controltower.paginators.ListEnabledBaselinesIterable;
+import software.amazon.awssdk.services.controltower.paginators.ListEnabledControlsIterable;
+import software.amazon.awssdk.services.controltower.paginators.ListLandingZonesIterable;
+import software.amazon.awssdk.services.controlcatalog.ControlCatalogClient;
+import software.amazon.awssdk.services.controlcatalog.paginators.ListControlsIterable;
+import software.amazon.awssdk.core.exception.SdkException;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Before running this Java V2 code example, set up your development
+ * environment, including your credentials.
+ *
+ * For more information, see the following documentation topic:
+ *
+ * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
+ *
+ * This Java code example shows how to perform AWS Control Tower operations.
+ */
+
+// snippet-start:[controltower.java2.controltower_actions.main]
+public class ControlTowerActions {
+
+ // snippet-start:[controltower.java2.list_landing_zones.main]
+ /**
+ * Lists all landing zones using pagination to retrieve complete results.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @return a list of all landing zones
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static List listLandingZones(ControlTowerClient controlTowerClient) {
+ try {
+ List landingZones = new ArrayList<>();
+
+ String nextToken = null;
+
+ do {
+ ListLandingZonesRequest.Builder requestBuilder = ListLandingZonesRequest.builder();
+ if (nextToken != null) {
+ requestBuilder.nextToken(nextToken);
+ }
+
+ ListLandingZonesResponse response = controlTowerClient.listLandingZones(requestBuilder.build());
+
+ if (response.landingZones() != null) {
+ landingZones.addAll(response.landingZones());
+ }
+
+ nextToken = response.nextToken();
+ } while (nextToken != null);
+
+ System.out.format("Retrieved {} landing zones", landingZones.size());
+ return landingZones;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "AccessDeniedException":
+ System.out.format("Access denied when listing landing zones: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error listing landing zones: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error listing landing zones: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.list_landing_zones.main]
+
+ // snippet-start:[controltower.java2.list_baselines.main]
+ /**
+ * Lists all available baselines using pagination to retrieve complete results.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @return a list of all baselines
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static List listBaselines(ControlTowerClient controlTowerClient) {
+ try {
+ List baselines = new ArrayList<>();
+
+ String nextToken = null;
+
+ do {
+ ListBaselinesRequest.Builder requestBuilder = ListBaselinesRequest.builder();
+ if (nextToken != null) {
+ requestBuilder.nextToken(nextToken);
+ }
+
+ ListBaselinesResponse response = controlTowerClient.listBaselines(requestBuilder.build());
+
+ if (response.baselines() != null) {
+ baselines.addAll(response.baselines());
+ }
+
+ nextToken = response.nextToken();
+ } while (nextToken != null);
+
+ System.out.format("Retrieved {} baselines", baselines.size());
+ return baselines;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "AccessDeniedException":
+ System.out.format("Access denied when listing baselines: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error listing baselines: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error listing baselines: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.list_baselines.main]
+
+ // snippet-start:[controltower.java2.list_enabled_baselines.main]
+ /**
+ * Lists all enabled baselines using pagination to retrieve complete results.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @return a list of all enabled baselines
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static List listEnabledBaselines(ControlTowerClient controlTowerClient) {
+ try {
+ List enabledBaselines = new ArrayList<>();
+
+ String nextToken = null;
+
+ do {
+ ListEnabledBaselinesRequest.Builder requestBuilder = ListEnabledBaselinesRequest.builder();
+ if (nextToken != null) {
+ requestBuilder.nextToken(nextToken);
+ }
+
+ ListEnabledBaselinesResponse response = controlTowerClient.listEnabledBaselines(requestBuilder.build());
+
+ if (response.enabledBaselines() != null) {
+ enabledBaselines.addAll(response.enabledBaselines());
+ }
+
+ nextToken = response.nextToken();
+ } while (nextToken != null);
+
+ System.out.format("Retrieved {} enabled baselines", enabledBaselines.size());
+ return enabledBaselines;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ResourceNotFoundException":
+ System.out.format("Target not found when listing enabled baselines: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error listing enabled baselines: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error listing enabled baselines: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.list_enabled_baselines.main]
+
+ // snippet-start:[controltower.java2.enable_baseline.main]
+ /**
+ * Enables a baseline for a specified target.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param baselineIdentifier the identifier of the baseline to enable
+ * @param baselineVersion the version of the baseline to enable
+ * @param targetIdentifier the identifier of the target (e.g., OU ARN)
+ * @return the operation identifier
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static String enableBaseline(ControlTowerClient controlTowerClient,
+ String baselineIdentifier,
+ String baselineVersion,
+ String targetIdentifier) {
+ try {
+ EnableBaselineRequest request = EnableBaselineRequest.builder()
+ .baselineIdentifier(baselineIdentifier)
+ .baselineVersion(baselineVersion)
+ .targetIdentifier(targetIdentifier)
+ .build();
+
+ EnableBaselineResponse response = controlTowerClient.enableBaseline(request);
+ String operationId = response.operationIdentifier();
+
+ System.out.format("Enabled baseline with operation ID: {}", operationId);
+ return operationId;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ValidationException":
+ if (e.getMessage().contains("already enabled")) {
+ System.out.format("Baseline is already enabled for this target");
+ return null;
+ }
+ System.out.format("Validation error enabling baseline: {}", e.getMessage());
+ break;
+ case "ConflictException":
+ System.out.format("Conflict enabling baseline: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error enabling baseline: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error enabling baseline: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.enable_baseline.main]
+
+ // snippet-start:[controltower.java2.disable_baseline.main]
+ /**
+ * Disables a baseline for a specified target.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param enabledBaselineIdentifier the identifier of the enabled baseline to disable
+ * @return the operation identifier
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static String disableBaseline(ControlTowerClient controlTowerClient,
+ String enabledBaselineIdentifier) {
+ try {
+ DisableBaselineRequest request = DisableBaselineRequest.builder()
+ .enabledBaselineIdentifier(enabledBaselineIdentifier)
+ .build();
+
+ DisableBaselineResponse response = controlTowerClient.disableBaseline(request);
+ String operationId = response.operationIdentifier();
+
+ System.out.format("Disabled baseline with operation ID: {}", operationId);
+ return operationId;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ConflictException":
+ System.out.format("Conflict disabling baseline: {}", e.getMessage());
+ break;
+ case "ResourceNotFoundException":
+ System.out.format("Baseline not found for disabling: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error disabling baseline: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error disabling baseline: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.disable_baseline.main]
+
+ // snippet-start:[controltower.java2.get_baseline_operation.main]
+ /**
+ * Gets the status of a baseline operation.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param operationIdentifier the identifier of the operation
+ * @return the operation status
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static BaselineOperationStatus getBaselineOperation(ControlTowerClient controlTowerClient,
+ String operationIdentifier) {
+ try {
+ GetBaselineOperationRequest request = GetBaselineOperationRequest.builder()
+ .operationIdentifier(operationIdentifier)
+ .build();
+
+ GetBaselineOperationResponse response = controlTowerClient.getBaselineOperation(request);
+ BaselineOperationStatus status = response.baselineOperation().status();
+
+ System.out.format("Baseline operation status: {}", status);
+ return status;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ResourceNotFoundException":
+ System.out.format("Baseline operation not found: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error getting baseline operation status: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error getting baseline operation status: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.get_baseline_operation.main]
+
+ // snippet-start:[controltower.java2.list_enabled_controls.main]
+ /**
+ * Lists all enabled controls for a specific target using pagination.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param targetIdentifier the identifier of the target (e.g., OU ARN)
+ * @return a list of enabled controls
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static List listEnabledControls(ControlTowerClient controlTowerClient,
+ String targetIdentifier) {
+ try {
+ List enabledControls = new ArrayList<>();
+
+ // Use paginator to retrieve all results
+ ListEnabledControlsIterable listIterable = controlTowerClient.listEnabledControlsPaginator(
+ ListEnabledControlsRequest.builder()
+ .targetIdentifier(targetIdentifier)
+ .build()
+ );
+
+ listIterable.stream()
+ .flatMap(response -> response.enabledControls().stream())
+ .forEach(enabledControls::add);
+
+ System.out.format("Retrieved {} enabled controls for target {}", enabledControls.size(), targetIdentifier);
+ return enabledControls;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "AccessDeniedException":
+ System.out.format("Access denied when listing enabled controls: {}", e.getMessage());
+ break;
+ case "ResourceNotFoundException":
+ if (e.getMessage().contains("not registered with AWS Control Tower")) {
+ System.out.format("Control Tower must be enabled to work with controls");
+ } else {
+ System.out.format("Target not found when listing enabled controls: {}", e.getMessage());
+ }
+ break;
+ default:
+ System.out.format("Error listing enabled controls: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error listing enabled controls: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.list_enabled_controls.main]
+
+ // snippet-start:[controltower.java2.enable_control.main]
+ /**
+ * Enables a control for a specified target.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param controlIdentifier the identifier of the control to enable
+ * @param targetIdentifier the identifier of the target (e.g., OU ARN)
+ * @return the operation identifier
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static String enableControl(ControlTowerClient controlTowerClient,
+ String controlIdentifier,
+ String targetIdentifier) {
+ try {
+ EnableControlRequest request = EnableControlRequest.builder()
+ .controlIdentifier(controlIdentifier)
+ .targetIdentifier(targetIdentifier)
+ .build();
+
+ EnableControlResponse response = controlTowerClient.enableControl(request);
+ String operationId = response.operationIdentifier();
+
+ System.out.format("Enabled control with operation ID: {}", operationId);
+ return operationId;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ValidationException":
+ if (e.getMessage().contains("already enabled")) {
+ System.out.format("Control is already enabled for this target");
+ return null;
+ }
+ System.out.format("Validation error enabling control: {}", e.getMessage());
+ break;
+ case "ResourceNotFoundException":
+ if (e.getMessage().contains("not registered with AWS Control Tower")) {
+ System.out.format("Control Tower must be enabled to work with controls");
+ } else {
+ System.out.format("Control not found: {}", e.getMessage());
+ }
+ break;
+ default:
+ System.out.format("Error enabling control: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error enabling control: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.enable_control.main]
+
+ // snippet-start:[controltower.java2.disable_control.main]
+ /**
+ * Disables a control for a specified target.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param controlIdentifier the identifier of the control to disable
+ * @param targetIdentifier the identifier of the target (e.g., OU ARN)
+ * @return the operation identifier
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static String disableControl(ControlTowerClient controlTowerClient,
+ String controlIdentifier,
+ String targetIdentifier) {
+ try {
+ DisableControlRequest request = DisableControlRequest.builder()
+ .controlIdentifier(controlIdentifier)
+ .targetIdentifier(targetIdentifier)
+ .build();
+
+ DisableControlResponse response = controlTowerClient.disableControl(request);
+ String operationId = response.operationIdentifier();
+
+ System.out.format("Disabled control with operation ID: {}", operationId);
+ return operationId;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ResourceNotFoundException":
+ System.out.format("Control not found for disabling: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error disabling control: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error disabling control: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.disable_control.main]
+
+ // snippet-start:[controltower.java2.get_control_operation.main]
+ /**
+ * Gets the status of a control operation.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param operationIdentifier the identifier of the operation
+ * @return the operation status
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static ControlOperationStatus getControlOperation(ControlTowerClient controlTowerClient,
+ String operationIdentifier) {
+ try {
+ GetControlOperationRequest request = GetControlOperationRequest.builder()
+ .operationIdentifier(operationIdentifier)
+ .build();
+
+ GetControlOperationResponse response = controlTowerClient.getControlOperation(request);
+ ControlOperationStatus status = response.controlOperation().status();
+
+ System.out.format("Control operation status: {}", status);
+ return status;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ResourceNotFoundException":
+ System.out.format("Control operation not found: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Error getting control operation status: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error getting control operation status: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.get_control_operation.main]
+
+ // snippet-start:[controltower.java2.list_controls.main]
+ /**
+ * Lists all controls in the Control Tower control catalog.
+ *
+ * @param controlCatalogClient the Control Catalog client to use for the operation
+ * @return a list of controls
+ * @throws SdkException if a service-specific error occurs
+ */
+ public static List listControls(
+ ControlCatalogClient controlCatalogClient) {
+ try {
+ List controls = new ArrayList<>();
+
+ ListControlsIterable paginator = controlCatalogClient.listControlsPaginator(
+ software.amazon.awssdk.services.controlcatalog.model.ListControlsRequest.builder().build());
+
+ paginator.stream()
+ .flatMap(response -> response.controls().stream())
+ .forEach(controls::add);
+
+ System.out.format("Retrieved {} controls", controls.size());
+ return controls;
+
+ } catch (SdkException e) {
+ if (e.getMessage().contains("AccessDeniedException")) {
+ System.out.format("Access denied. Please ensure you have the necessary permissions.");
+ } else {
+ System.out.format("Couldn't list controls. Here's why: {}", e.getMessage());
+ }
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.list_controls.main]
+
+ // snippet-start:[controltower.java2.reset_enabled_baseline.main]
+ /**
+ * Resets an enabled baseline for a specific target.
+ *
+ * @param controlTowerClient the Control Tower client to use for the operation
+ * @param enabledBaselineIdentifier the identifier of the enabled baseline to reset
+ * @return the operation identifier
+ * @throws ControlTowerException if a service-specific error occurs
+ * @throws SdkException if an SDK error occurs
+ */
+ public static String resetEnabledBaseline(ControlTowerClient controlTowerClient,
+ String enabledBaselineIdentifier) {
+ try {
+ ResetEnabledBaselineRequest request = ResetEnabledBaselineRequest.builder()
+ .enabledBaselineIdentifier(enabledBaselineIdentifier)
+ .build();
+
+ ResetEnabledBaselineResponse response = controlTowerClient.resetEnabledBaseline(request);
+ String operationId = response.operationIdentifier();
+
+ System.out.format("Reset enabled baseline with operation ID: {}", operationId);
+ return operationId;
+
+ } catch (ControlTowerException e) {
+ String errorCode = e.awsErrorDetails().errorCode();
+ switch (errorCode) {
+ case "ResourceNotFoundException":
+ System.out.format("Target not found: {}", e.getMessage());
+ break;
+ default:
+ System.out.format("Couldn't reset enabled baseline. Here's why: {}", e.getMessage());
+ }
+ throw e;
+ } catch (SdkException e) {
+ System.out.format("SDK error resetting enabled baseline: {}", e.getMessage());
+ throw e;
+ }
+ }
+ // snippet-end:[controltower.java2.reset_enabled_baseline.main]
+}
+// snippet-end:[controltower.java2.controltower_actions.main]
\ No newline at end of file
diff --git a/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerScenario.java b/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerScenario.java
new file mode 100644
index 00000000000..c7b771d524c
--- /dev/null
+++ b/javav2/example_code/controltower/src/main/java/com/example/controltower/ControlTowerScenario.java
@@ -0,0 +1,363 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package com.example.controltower;
+
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.awscore.exception.AwsServiceException;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.controlcatalog.ControlCatalogClient;
+import software.amazon.awssdk.services.controlcatalog.model.ControlSummary;
+import software.amazon.awssdk.services.organizations.OrganizationsClient;
+import software.amazon.awssdk.services.organizations.model.*;
+import software.amazon.awssdk.services.controltower.ControlTowerClient;
+import software.amazon.awssdk.services.controltower.model.*;
+import java.util.List;
+import java.util.Scanner;
+import java.util.Set;
+import java.util.stream.Collectors;
+import static java.lang.System.*;
+
+/**
+ * Before running this Java V2 code example, set up your development
+ * environment, including your credentials.
+ *
+ * For more information, see the following documentation topic:
+ *
+ * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
+ *
+ */
+
+public class ControlTowerScenario {
+
+ public static final String DASHES = new String(new char[80]).replace("\0", "-");
+ static Scanner scanner = new Scanner(in);
+
+ private OrganizationsClient orgClient;
+ private ControlCatalogClient catClient;
+ private String ouArn;
+ private String stack = null;
+ private String ouId = null;
+ private String accountId = null;
+ private String landingZoneArn = null;
+ private boolean useLandingZone = false;
+
+ public static void main(String[] args) {
+
+ out.println(DASHES);
+ out.println("Welcome to the AWS Control Tower basics scenario!");
+ out.println(DASHES);
+
+ try {
+ ControlTowerClient controlTowerClient = ControlTowerClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ OrganizationsClient orgClient = OrganizationsClient.builder()
+ .region(Region.AWS_GLOBAL)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ ControlCatalogClient catClient = ControlCatalogClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ ControlTowerScenario scenario = new ControlTowerScenario(orgClient, catClient);
+ scenario.runScenario(controlTowerClient);
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ // ----------------------------------------------------------
+ // Constructor: store orgClient for setupOrganization()
+ // ----------------------------------------------------------
+ public ControlTowerScenario(OrganizationsClient orgClient, ControlCatalogClient catClient) {
+ this.orgClient = orgClient;
+ this.catClient = catClient;
+ }
+
+ // ----------------------------------------------------------
+ // Main scenario flow
+ // ----------------------------------------------------------
+ private void runScenario(ControlTowerClient controlTowerClient) {
+ try {
+ out.println(DASHES);
+ System.out.println("""
+ Some demo operations require the use of a landing zone.
+ You can use an existing landing zone or opt out of these operations in the demo.
+ For instructions on how to set up a landing zone,
+ see https://docs.aws.amazon.com/controltower/latest/userguide/getting-started-from-console.html
+ """);
+
+ out.println("Step 1: Listing landing zones...");
+ waitForInputToContinue(scanner);
+
+ // CALL: ControlTowerActions.listLandingZones()
+ List landingZones =
+ ControlTowerActions.listLandingZones(controlTowerClient);
+
+ if (!landingZones.isEmpty()) {
+ System.out.println("\nAvailable Landing Zones:");
+
+ for (int i = 0; i < landingZones.size(); i++) {
+ LandingZoneSummary lz = landingZones.get(i);
+ System.out.printf("%d %s)%n", i + 1, lz.arn());
+ }
+
+ if (askYesNo(
+ "Do you want to use the first landing zone in the list (" +
+ landingZones.get(0).arn() + ")? (y/n): ")) {
+
+ useLandingZone = true;
+ landingZoneArn = landingZones.get(0).arn();
+
+ System.out.println("Using landing zone ID: " + landingZoneArn);
+
+ // CALL: setupOrganization()
+ String sandboxOuId = setupOrganization();
+ ouId = sandboxOuId;
+
+ } else if (askYesNo(
+ "Do you want to use a different existing Landing Zone for this demo? (y/n): ")) {
+
+ useLandingZone = true;
+
+ System.out.print("Enter landing zone id: ");
+ landingZoneArn = scanner.nextLine().trim();
+
+ // CALL: setupOrganization()
+ String sandboxOuId = setupOrganization();
+ ouId = sandboxOuId;
+ }
+ }
+ waitForInputToContinue(scanner);
+
+ // ----------------------------------------------------------
+ // CALL: ControlTowerActions.listBaselines()
+ // ----------------------------------------------------------
+ out.println(DASHES);
+ out.println("Step 2: Listing available baselines...");
+
+ List baselines =
+ ControlTowerActions.listBaselines(controlTowerClient);
+
+ baselines.forEach(b -> {
+ out.println("Baseline: " + b.name());
+ out.println(" ARN: " + b.arn());
+ });
+ waitForInputToContinue(scanner);
+
+ // ----------------------------------------------------------
+ // CALL: ControlTowerActions.listControls()
+ // ----------------------------------------------------------
+ out.println(DASHES);
+ out.println("Managing Controls:");
+
+ List controls =
+ ControlTowerActions.listControls(catClient);
+
+ out.println("\nListing first 5 available Controls:");
+
+ for (int i = 0; i < Math.min(5, controls.size()); i++) {
+ ControlSummary c = controls.get(i);
+ out.println(String.format("%d. %s - %s",
+ (i + 1), c.name(), c.arn()));
+ }
+
+ if (useLandingZone) {
+
+ String targetOu = ouArn;
+ waitForInputToContinue(scanner);
+
+ // ----------------------------------------------------------
+ // CALL: ControlTowerActions.listEnabledControls()
+ // ----------------------------------------------------------
+ List enabledControls =
+ ControlTowerActions.listEnabledControls(controlTowerClient, targetOu);
+
+ out.println("\nListing enabled controls:");
+
+ for (int i = 0; i < enabledControls.size(); i++) {
+ EnabledControlSummary ec = enabledControls.get(i);
+ out.println(String.format("%d. %s",
+ (i + 1), ec.controlIdentifier()));
+ }
+
+ // Determine first non-enabled control
+ Set enabledControlArns = enabledControls.stream()
+ .map(EnabledControlSummary::arn)
+ .collect(Collectors.toSet());
+
+ String controlArnToEnable = controls.stream()
+ .map(ControlSummary::arn)
+ .filter(arn -> !enabledControlArns.contains(arn))
+ .findFirst()
+ .orElse(null);
+
+ waitForInputToContinue(scanner);
+
+ // ----------------------------------------------------------
+ // CALL: ControlTowerActions.enableControl()
+ // ----------------------------------------------------------
+ if (controlArnToEnable != null &&
+ askYesNo("Do you want to enable the control "
+ + controlArnToEnable + "? (y/n): ")) {
+
+ out.println("\nEnabling control: " + controlArnToEnable);
+
+ String operationId =
+ ControlTowerActions.enableControl(
+ controlTowerClient, controlArnToEnable, targetOu);
+
+ if (operationId != null) {
+ out.println("Enabled control with operation id " + operationId);
+ }
+ }
+ waitForInputToContinue(scanner);
+
+ // ----------------------------------------------------------
+ // CALL: ControlTowerActions.disableControl()
+ // ----------------------------------------------------------
+ if (controlArnToEnable != null &&
+ askYesNo("Do you want to disable the control? (y/n): ")) {
+
+ out.println("\nDisabling control...");
+
+ String operationId =
+ ControlTowerActions.disableControl(
+ controlTowerClient, controlArnToEnable, targetOu);
+
+ out.println("Disable operation ID: " + operationId);
+ }
+ }
+
+ // Final pause
+ waitForInputToContinue(scanner);
+
+ out.println("\nThis concludes the example scenario.");
+ out.println("Thanks for watching!");
+ out.println(DASHES);
+ out.println(DASHES);
+ out.println("Scenario completed Successfully!");
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
+ public String setupOrganization() {
+ System.out.println("\nChecking organization status...");
+ String orgId;
+
+ // -------------------------------
+ // 1. Describe or create organization
+ // -------------------------------
+ try {
+ DescribeOrganizationResponse desc = orgClient.describeOrganization();
+ orgId = desc.organization().id();
+ System.out.println("Account is part of organization: " + orgId);
+
+ } catch (AwsServiceException e) {
+
+ if ("AWSOrganizationsNotInUseException".equals(e.awsErrorDetails().errorCode())) {
+
+ System.out.println("No organization found. Creating one...");
+
+ CreateOrganizationResponse create =
+ orgClient.createOrganization(
+ CreateOrganizationRequest.builder()
+ .featureSet("ALL")
+ .build()
+ );
+
+ orgId = create.organization().id();
+ System.out.println("Created organization: " + orgId);
+
+ // ✅ NO WAITERS — we simply proceed
+ // Organizations may take time to stabilize,
+ // but this method returns immediately.
+
+ } else {
+ throw e;
+ }
+ }
+
+ // -------------------------------
+ // 2. Locate or create Sandbox OU
+ // -------------------------------
+ String sandboxOuId = null;
+
+ ListRootsResponse roots = orgClient.listRoots();
+ String rootId = roots.roots().get(0).id();
+
+ System.out.println("Checking Sandbox OU...");
+
+ for (ListOrganizationalUnitsForParentResponse page :
+ orgClient.listOrganizationalUnitsForParentPaginator(
+ ListOrganizationalUnitsForParentRequest.builder()
+ .parentId(rootId)
+ .build()
+ )) {
+
+ for (OrganizationalUnit ou : page.organizationalUnits()) {
+ if ("Sandbox".equals(ou.name())) {
+ sandboxOuId = ou.id();
+ this.ouArn = ou.arn();
+ System.out.println("Found Sandbox OU: " + sandboxOuId);
+ break;
+ }
+ }
+
+ if (sandboxOuId != null) {
+ break;
+ }
+ }
+
+ // -------------------------------
+ // Create OU if missing
+ // -------------------------------
+ if (sandboxOuId == null) {
+ System.out.println("Creating Sandbox OU...");
+
+ CreateOrganizationalUnitResponse created =
+ orgClient.createOrganizationalUnit(
+ CreateOrganizationalUnitRequest.builder()
+ .parentId(rootId)
+ .name("Sandbox")
+ .build()
+ );
+
+ sandboxOuId = created.organizationalUnit().id();
+ this.ouArn = created.organizationalUnit().arn();
+
+ System.out.println("Created Sandbox OU: " + sandboxOuId);
+
+ // ✅ NO WAITER — return immediately
+ }
+
+ return sandboxOuId;
+ }
+
+ // ----------------------------------------------------------
+ // Utility methods
+ // ----------------------------------------------------------
+ private static boolean askYesNo(String msg) {
+ out.print(msg);
+ return scanner.nextLine().trim().toLowerCase().startsWith("y");
+ }
+
+ private static void waitForInputToContinue(Scanner sc) {
+ out.println("\nEnter 'c' then to continue:");
+ while (true) {
+ String in = sc.nextLine();
+ if ("c".equalsIgnoreCase(in.trim())) {
+ out.println("Continuing...");
+ break;
+ }
+ }
+ }
+}
diff --git a/javav2/example_code/controltower/src/main/java/com/example/controltower/HelloControlTower.java b/javav2/example_code/controltower/src/main/java/com/example/controltower/HelloControlTower.java
new file mode 100644
index 00000000000..b6478acf8a7
--- /dev/null
+++ b/javav2/example_code/controltower/src/main/java/com/example/controltower/HelloControlTower.java
@@ -0,0 +1,79 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+package com.example.controltower;
+
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.controltower.ControlTowerClient;
+import software.amazon.awssdk.services.controltower.model.ControlTowerException;
+import software.amazon.awssdk.services.controltower.model.ListBaselinesRequest;
+import software.amazon.awssdk.services.controltower.paginators.ListBaselinesIterable;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Before running this Java V2 code example, set up your development
+ * environment, including your credentials.
+ *
+ * For more information, see the following documentation topic:
+ *
+ * https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/get-started.html
+ *
+ * Use the AWS SDK for Java (v2) to create an AWS Control Tower client
+ * and list all available baselines.
+ * This example uses the default settings specified in your shared credentials
+ * and config files.
+ */
+
+// snippet-start:[controltower.java2.hello.main]
+public class HelloControlTower {
+
+ public static void main(String[] args) {
+ try {
+ ControlTowerClient controlTowerClient = ControlTowerClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build() ;
+ helloControlTower(controlTowerClient);
+ } catch (ControlTowerException e) {
+ System.err.println("Control Tower error occurred: " + e.awsErrorDetails().errorMessage());
+ }
+ }
+
+ /**
+ * Use the AWS SDK for Java (v2) to create an AWS Control Tower client
+ * and list all available baselines.
+ * This example uses the default settings specified in your shared credentials
+ * and config files.
+ *
+ * @param controlTowerClient A ControlTowerClient object. This object wraps
+ * the low-level AWS Control Tower service API.
+ */
+ public static void helloControlTower(ControlTowerClient controlTowerClient) {
+ System.out.println("Hello, AWS Control Tower! Let's list available baselines:\n");
+
+ ListBaselinesIterable paginator = controlTowerClient.listBaselinesPaginator(
+ ListBaselinesRequest.builder().build());
+ List baselineNames = new ArrayList<>();
+
+ try {
+ paginator.stream()
+ .flatMap(response -> response.baselines().stream())
+ .forEach(baseline -> baselineNames.add(baseline.name()));
+
+ System.out.println(baselineNames.size() + " baseline(s) retrieved.");
+ for (String baselineName : baselineNames) {
+ System.out.println("\t" + baselineName);
+ }
+
+ } catch (ControlTowerException e) {
+ if ("AccessDeniedException".equals(e.awsErrorDetails().errorCode())) {
+ System.out.println("Access denied. Please ensure you have the necessary permissions.");
+ } else {
+ System.out.println("An error occurred: " + e.getMessage());
+ }
+ }
+ }
+}
+// snippet-end:[controltower.java2.hello.main]
diff --git a/javav2/example_code/controltower/src/main/java/resources/config.properties b/javav2/example_code/controltower/src/main/java/resources/config.properties
new file mode 100644
index 00000000000..c18495c2f4c
--- /dev/null
+++ b/javav2/example_code/controltower/src/main/java/resources/config.properties
@@ -0,0 +1,3 @@
+dataAccessRoleArn =
+s3Uri =
+documentClassifier =
diff --git a/javav2/example_code/controltower/src/main/java/resources/logback.xml b/javav2/example_code/controltower/src/main/java/resources/logback.xml
new file mode 100644
index 00000000000..d705768de36
--- /dev/null
+++ b/javav2/example_code/controltower/src/main/java/resources/logback.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
diff --git a/javav2/example_code/controltower/src/test/java/ControlTowerTest.java b/javav2/example_code/controltower/src/test/java/ControlTowerTest.java
new file mode 100644
index 00000000000..3dfd0afcf98
--- /dev/null
+++ b/javav2/example_code/controltower/src/test/java/ControlTowerTest.java
@@ -0,0 +1,72 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+import com.example.controltower.ControlTowerActions;
+import com.example.controltower.HelloControlTower;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.MethodOrderer;
+import org.junit.jupiter.api.Order;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.TestInstance;
+import org.junit.jupiter.api.TestMethodOrder;
+import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
+import software.amazon.awssdk.regions.Region;
+import software.amazon.awssdk.services.controlcatalog.ControlCatalogClient;
+import software.amazon.awssdk.services.controltower.ControlTowerClient;
+import software.amazon.awssdk.services.organizations.OrganizationsClient;
+import software.amazon.awssdk.services.organizations.model.DescribeOrganizationResponse;
+import software.amazon.awssdk.services.organizations.model.ListOrganizationalUnitsForParentRequest;
+import software.amazon.awssdk.services.organizations.model.ListOrganizationalUnitsForParentResponse;
+
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+
+@TestInstance(TestInstance.Lifecycle.PER_METHOD)
+@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
+public class ControlTowerTest {
+ private static ControlTowerClient controlTowerClient;
+ private static OrganizationsClient orgClient;
+ private static ControlCatalogClient catClient ;
+
+ @BeforeAll
+ public static void setUp() {
+ controlTowerClient = ControlTowerClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ orgClient = OrganizationsClient.builder()
+ .region(Region.AWS_GLOBAL)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ catClient = ControlCatalogClient.builder()
+ .region(Region.US_EAST_1)
+ .credentialsProvider(ProfileCredentialsProvider.create("default"))
+ .build();
+
+ }
+
+ @Test
+ @Order(1)
+ public void testHelloService() {
+ assertDoesNotThrow(() -> {
+ HelloControlTower.helloControlTower(controlTowerClient);
+ });
+ System.out.println("Test 1 passed");
+ }
+
+ @Test
+ @Order(2)
+ public void testControlTowerActions() {
+ assertDoesNotThrow(() -> {
+ // SAFE: read-only, no admin role required
+ ControlTowerActions.listLandingZones(controlTowerClient);
+ ControlTowerActions.listBaselines(controlTowerClient);
+ ControlTowerActions.listControls(catClient);
+
+ });
+
+ System.out.println("Test 2 passed");
+ }
+
+}
\ No newline at end of file