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

Working with the AWS CDK in Java

Java is a fully-supported client platform 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 modules comprising the AWS Construct Library are distributed via the Maven Central Repository.

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 will work fine 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 we are unable to provide support for these languages.

Prerequisites

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 AWS CDK Prerequisites.

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.

Creating a project

You create a new AWS CDK project by invoking cdk init in an empty directory.

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.

The resulting project includes a reference to the software.amazon.awscdk.core 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 and named with a short version (no AWS or Amazon prefix) of their service's name. For example, the Maven artifact ID for Amazon S3 is s3. 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 module. For example, Amazon Route 53 has the three modules in addition to the main software.amazon.awscdk.route53 module, named route53-patterns, route53resolver, and route53-targets.

The AWS CDK's core module, which you'll need in most AWS CDK apps, is imported in Java code as software.amazon.awscdk.core. 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.

Important

All AWS Construct Library modules used in your project must be the same version.

Specify the modules that your application depends on by editing pom.xml and adding a new <dependency> element in the <dependencies> container. For example, the following <dependency> element specifies the Amazon S3 construct library module:

<dependency> <groupId>software.amazon.awscdk</groupId> <artifactId>s3</artifactId> <version>${cdk.version}</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.

The default pom.xml defines the variable cdk.version to be the version of the AWS CDK that created the project. You can easily update the version required by updating the value of this variable, which keeps all AWS Construct Library module versions in sync.

<cdk.version>1.XX.Y</cdk.version>

This value can be any valid Maven version specifier. For example, [1.XX.Y,2.0) indicates that any version between the current version 1.XX.Y (inclusive) and 2.0 (exclusive), may be installed. However, to avoid mismatched versions, we recommend using a fixed version like 1.XX and updating it when moving a new AWS CDK release.

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), a name, 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. Given this fact, you may prefer to simply have your construct accept additional arguments. In this case, provide additional constructors when an argument is optional.

Generic structures

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

new HashMap<String, String>() {{ put("base-directory", "dist"); put("files", "LambdaStack.template.json"); }};
Note

The double-brace notation (which technically declares an anonymous inner class) is sometimes considered an anti-pattern. However, its disadvantages are not very relevant to this use case, and it is a reasonably compact way to write what would be object or dictionary literals in other languages.

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

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 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).