Working with the AWS CDK in Java - AWS Cloud Development Kit (AWS CDK) v2

This is the AWS CDK v2 Developer Guide. The older CDK v1 entered maintenance on June 1, 2022 and ended support on June 1, 2023.

Working with the AWS CDK in Java

Java is a fully-supported client language for the AWS CDK and is considered stable. You can develop AWS CDK applications in Java using familiar tools, including the JDK (Oracle's, or an OpenJDK distribution such as Amazon Corretto) and Apache Maven.

The AWS CDK supports Java 8 and later. We recommend using the latest version you can, however, because later versions of the language include improvements that are particularly convenient for developing AWS CDK applications. For example, Java 9 introduces the Map.of() method (a convenient way to declare hashmaps that would be written as object literals in TypeScript). Java 10 introduces local type inference using the var keyword.

Note

Most code examples in this Developer Guide work with Java 8. A few examples use Map.of(); these examples include comments noting that they require Java 9.

You can use any text editor, or a Java IDE that can read Maven projects, to work on your AWS CDK apps. We provide Eclipse hints in this Guide, but IntelliJ IDEA, NetBeans, and other IDEs can import Maven projects and can be used for developing AWS CDK applications in Java.

It is possible to write AWS CDK applications in JVM-hosted languages other than Java (for example, Kotlin, Groovy, Clojure, or Scala), but the experience may not be particularly idiomatic, and we are unable to provide any support for these languages.

Get started with Java

To work with the AWS CDK, you must have an AWS account and credentials and have installed Node.js and the AWS CDK Toolkit. See Getting started with the AWS CDK.

Java AWS CDK applications require Java 8 (v1.8) or later. We recommend Amazon Corretto, but you can use any OpenJDK distribution or Oracle's JDK. You will also need Apache Maven 3.5 or later. You can also use tools such as Gradle, but the application skeletons generated by the AWS CDK Toolkit are Maven projects.

Note

Third-party language deprecation: language version is only supported until its EOL (End Of Life) shared by the vendor or community and is subject to change with prior notice.

Creating a project

You create a new AWS CDK project by invoking cdk init in an empty directory. Use the --language option and specify java:

mkdir my-project cd my-project cdk init app --language java

cdk init uses the name of the project folder to name various elements of the project, including classes, subfolders, and files. Hyphens in the folder name are converted to underscores. However, the name should otherwise follow the form of a Java identifier; for example, it should not start with a number or contain spaces.

The resulting project includes a reference to the software.amazon.awscdk Maven package. It and its dependencies are automatically installed by Maven.

If you are using an IDE, you can now open or import the project. In Eclipse, for example, choose File > Import > Maven > Existing Maven Projects. Make sure that the project settings are set to use Java 8 (1.8).

Managing AWS Construct Library modules

Use Maven to install AWS Construct Library packages, which are in the group software.amazon.awscdk. Most constructs are in the artifact aws-cdk-lib, which is added to new Java projects by default. Modules for services whose higher-level CDK support is still being developed are in separate "experimental" packages, named with a short version (no AWS or Amazon prefix) of their service's name. Search the Maven Central Repository to find the names of all AWS CDK and AWS Construct Module libraries.

Note

The Java edition of the CDK API Reference also shows the package names.

Some services' AWS Construct Library support is in more than one namespace. For example, Amazon Route 53 has its functionality divided into software.amazon.awscdk.route53, route53-patterns, route53resolver, and route53-targets.

The main AWS CDK package is imported in Java code as software.amazon.awscdk. Modules for the various services in the AWS Construct Library live under software.amazon.awscdk.services and are named similarly to their Maven package name. For example, the Amazon S3 module's namespace is software.amazon.awscdk.services.s3.

We recommend writing a separate Java import statement for each AWS Construct Library class you use in each of your Java source files, and avoiding wildcard imports. You can always use a type's fully-qualified name (including its namespace) without an import statement.

If your application depends on an experimental package, edit your project's pom.xml and add a new <dependency> element in the <dependencies> container. For example, the following <dependency> element specifies the CodeStar experimental construct library module:

<dependency> <groupId>software.amazon.awscdk</groupId> <artifactId>codestar-alpha</artifactId> <version>2.0.0-alpha.10</version> </dependency>
Tip

If you use a Java IDE, it probably has features for managing Maven dependencies. We recommend editing pom.xml directly, however, unless you are absolutely sure the IDE's functionality matches what you'd do by hand.

Managing dependencies in Java

In Java, dependencies are specified in pom.xml and installed using Maven. The <dependencies> container includes a <dependency> element for each package. Following is a section of pom.xml for a typical CDK Java app.

<dependencies> <dependency> <groupId>software.amazon.awscdk</groupId> <artifactId>aws-cdk-lib</artifactId> <version>2.14.0</version> </dependency> <dependency> <groupId>software.amazon.awscdk</groupId> <artifactId>appsync-alpha</artifactId> <version>2.10.0-alpha.0</version> </dependency> </dependencies>
Tip

Many Java IDEs have integrated Maven support and visual pom.xml editors, which you may find convenient for managing dependencies.

Maven does not support dependency locking. Although it's possible to specify version ranges in pom.xml, we recommend you always use exact versions to keep your builds repeatable.

Maven automatically installs transitive dependencies, but there can only be one installed copy of each package. The version that is specified highest in the POM tree is selected; applications always have the last word in what version of packages get installed.

Maven automatically installs or updates your dependencies whenever you build (mvn compile) or package (mvn package) your project. The CDK Toolkit does this automatically every time you run it, so generally there is no need to manually invoke Maven.

AWS CDK idioms in Java

Props

All AWS Construct Library classes are instantiated using three arguments: the scope in which the construct is being defined (its parent in the construct tree), an id, and props, a bundle of key/value pairs that the construct uses to configure the resources it creates. Other classes and methods also use the "bundle of attributes" pattern for arguments.

In Java, props are expressed using the Builder pattern. Each construct type has a corresponding props type; for example, the Bucket construct (which represents an Amazon S3 bucket) takes as its props an instance of BucketProps.

The BucketProps class (like every AWS Construct Library props class) has an inner class called Builder. The BucketProps.Builder type offers methods to set the various properties of a BucketProps instance. Each method returns the Builder instance, so the method calls can be chained to set multiple properties. At the end of the chain, you call build() to actually produce the BucketProps object.

Bucket bucket = new Bucket(this, "MyBucket", new BucketProps.Builder() .versioned(true) .encryption(BucketEncryption.KMS_MANAGED) .build());

Constructs, and other classes that take a props-like object as their final argument, offer a shortcut. The class has a Builder of its own that instantiates it and its props object in one step. This way, you don't need to explicitly instantiate (for example) both BucketProps and a Bucket—and you don't need an import for the props type.

Bucket bucket = Bucket.Builder.create(this, "MyBucket") .versioned(true) .encryption(BucketEncryption.KMS_MANAGED) .build();

When deriving your own construct from an existing construct, you may want to accept additional properties. We recommend that you follow these builder patterns. However, this isn't as simple as subclassing a construct class. You must provide the moving parts of the two new Builder classes yourself. You may prefer to simply have your construct accept one or more additional arguments. You should provide additional constructors when an argument is optional.

Generic structures

In some APIs, the AWS CDK uses JavaScript arrays or untyped objects as input to a method. (See, for example, AWS CodeBuild's BuildSpec.fromObject() method.) In Java, these objects are represented as java.util.Map<String, Object>. In cases where the values are all strings, you can use Map<String, String>.

Java does not provide a way to write literals for such containers like some other languages do. In Java 9 and later, you can use java.util.Map.of() to conveniently define maps of up to ten entries inline with one of these calls.

java.util.Map.of( "base-directory", "dist", "files", "LambdaStack.template.json" )

To create maps with more than ten entries, use java.util.Map.ofEntries().

If you are using Java 8, you could provide your own methods similar to to these.

JavaScript arrays are represented as List<Object> or List<String> in Java. The method java.util.Arrays.asList is convenient for defining short Lists.

List<String> cmds = Arrays.asList("cd lambda", "npm install", "npm install typescript")

Missing values

In Java, missing values in AWS CDK objects such as props are represented by null. You must explicitly test any value that could be null to make sure it contains a value before doing anything with it. Java does not have "syntactic sugar" to help handle null values as some other languages do. You may find Apache ObjectUtil's defaultIfNull and firstNonNull useful in some situations. Alternatively, write your own static helper methods to make it easier to handle potentially null values and make your code more readable.

Building, synthesizing, and deploying

The AWS CDK automatically compiles your app before running it. However, it can be useful to build your app manually to check for errors and to run tests. You can do this in your IDE (for example, press Control-B in Eclipse) or by issuing mvn compile at a command prompt while in your project's root directory.

Run any tests you've written by running mvn test at a command prompt.

The stacks defined in your AWS CDK app can be synthesized and deployed individually or together using the commands below. Generally, you should be in your project's main directory when you issue them.

  • cdk synth: Synthesizes a AWS CloudFormation template from one or more of the stacks in your AWS CDK app.

  • cdk deploy: Deploys the resources defined by one or more of the stacks in your AWS CDK app to AWS.

You can specify the names of multiple stacks to be synthesized or deployed in a single command. If your app defines only one stack, you do not need to specify it.

cdk synth # app defines single stack cdk deploy Happy Grumpy # app defines two or more stacks; two are deployed

You may also use the wildcards * (any number of characters) and ? (any single character) to identify stacks by pattern. When using wildcards, enclose the pattern in quotes. Otherwise, the shell may try to expand it to the names of files in the current directory before they are passed to the AWS CDK Toolkit.

cdk synth "Stack?" # Stack1, StackA, etc. cdk deploy "*Stack" # PipeStack, LambdaStack, etc.
Tip

You don't need to explicitly synthesize stacks before deploying them; cdk deploy performs this step for you to make sure your latest code gets deployed.

For full documentation of the cdk command, see AWS CDK Toolkit (cdk command).