1. Overview

In this article, we’ll learn to control EC2 resources using the Java SDK. If you’re new to EC2 (Elastic Cloud Compute) – this is a platform which provides compute capacity in Amazon’s cloud.

2. Prerequisites

The Maven dependencies, AWS account settings and client connection needed to use the Amazon AWS SDK for EC2 are the same as in this article here.

Assuming we’ve created an instance of AWSCredentials, as described in the previous article, we can go ahead and create our EC2 client:

Ec2Client ec2Client = Ec2Client.builder()
    .credentialsProvider(ProfileCredentialsProvider.create("default"))
    .region(Region.US_EAST_1)
    .build();

3. Creating an EC2 Instance

Using the SDK, we can quickly set up what we need to start our first EC2 instance.

3.1. Creating a Security Group

Security groups control the network traffic to our EC2 instances. We’re able to use one security group for several EC2 instances.

Let’s create a security group:

CreateSecurityGroupRequest createSecurityGroupRequest = CreateSecurityGroupRequest.builder()
    .groupName("BaeldungSecurityGroup")
    .description("Baeldung Security Group")
    .build();

ec2Client.createSecurityGroup(createSecurityGroupRequest);

Since security groups don’t allow any network traffic by default, we’ll have to configure our security group to allow traffic.

Let’s allow HTTP traffic coming from any IP address:

IpRange ipRange1 = IpRange.builder()
    .cidrIp("0.0.0.0/0")
    .build();

IpPermission ipPermission1 = IpPermission.builder()
    .ipRanges(Arrays.asList(ipRange1))
    .ipProtocol("tcp")
    .fromPort(80)
    .toPort(80)
    .build();

Finally, we must attach the ipRange instance to an AuthorizeSecurityGroupIngressRequest and make the request using our EC2 client:

AuthorizeSecurityGroupIngressRequest authorizeSecurityGroupIngressRequest = AuthorizeSecurityGroupIngressRequest
    .builder()
    .groupName("BaeldungSecurityGroup")
    .ipPermissions(ipPermission1, ipPermission2)
    .build();

ec2Client.authorizeSecurityGroupIngress(authorizeSecurityGroupIngressRequest);

3.2. Creating a Key Pair

When launching an EC2 instance, we need to specify a key pair. We can create a key pair using the SDK:

CreateKeyPairRequest createKeyPairRequest = CreateKeyPairRequest.builder()
    .keyName("baeldung-key-pair")
    .build();

CreateKeyPairResponse createKeyPairResponse = ec2Client.createKeyPair(createKeyPairRequest);
String privateKey = createKeyPairResponse.keyMaterial();

We’ve got to make sure to keep this key somewhere secure and safe. If we lose it, we won’t be able to it back (Amazon doesn’t keep it). It’s the only way we can connect to our EC2 instance.

3.3. Creating the EC2 Instance

To create the EC2, we’ll use a RunInstancesRequest:

RunInstancesRequest runInstancesRequest = RunInstancesRequest.builder()
    .imageId("ami-97785bed")
    .instanceType("t2.micro") 
    .minCount(1)
    .maxCount(1)
    .keyName("baeldung-key-pair")
    .securityGroups("BaeldungSecurityGroup")
    .build();

Image Id is the AMI image that this instance will use.

An instance type defines the specifications of the instance.

The key name is optional; if it’s not specified, then we can’t connect to our instance. This is fine if we’re confident we’ve set up our instance correctly, and won’t need to connect.

Min and max count give bounds as to how many instances will be created. This depends on the availability zone: if AWS cannot create at least the minimum number of instances in the zone, it won’t create any.

Conversely, if AWS can’t create the maximum number of instances, it will try to create fewer, provided that this number is higher than the minimum number of instances we’ve specified.

Now we can execute the request using the runInstances() method and retrieve the id of the instance created:

RunInstancesResponse runInstancesResponse = ec2Client.runInstances(runInstancesRequest);
String yourInstanceId = runInstancesResponse.instances().get(0).instanceId();

4. Managing an EC2 Instance

Using the SDK, we can start, stop, reboot, describe and configure monitoring for our EC2 instances.

4.1. Starting, Stopping and Rebooting an EC2 Instance

Starting, stopping and rebooting an instance is relatively straightforward.

Starting an instance:

StartInstancesRequest startInstancesRequest = StartInstancesRequest.builder()
    .instanceIds(yourInstanceId)
    .build();

StartInstancesResponse startInstancesResponse = ec2Client.startInstances(startInstancesRequest);

Stopping an instance:

StopInstancesRequest stopInstancesRequest = StopInstancesRequest.builder()
    .instanceIds(yourInstanceId)
    .build();

ec2Client.stopInstances(stopInstancesRequest);

Rebooting an instance:

RebootInstancesRequest rebootInstancesRequest = RebootInstancesRequest.builder()
    .instanceIds(yourInstanceId)
    .build();

ec2Client.rebootInstances(rebootInstancesRequest);

From each of these requests, it’s possible to interrogate the previous state of the instance:

ec2Client.stopInstances(stopInstancesRequest)
    .stoppingInstances()
    .get(0)
    .previousState()
    .name();

4.2. Monitoring an EC2 Instance

Let’s see how to start and stop monitoring our EC2 instances:

MonitorInstancesRequest monitorInstancesRequest = MonitorInstancesRequest.builder()
    .instanceIds(yourInstanceId)
    .build();

ec2Client.monitorInstances(monitorInstancesRequest);

UnmonitorInstancesRequest unmonitorInstancesRequest = UnmonitorInstancesRequest.builder()
    .instanceIds(yourInstanceId)
    .build();

ec2Client.unmonitorInstances(unmonitorInstancesRequest);

4.3. Describing an EC2 Instance

Finally, we can describe our EC2 instances:

DescribeInstancesRequest describeInstancesRequest = DescribeInstancesRequest.builder().build();
DescribeInstancesResponse response = ec2Client.describeInstances(describeInstancesRequest);

EC2 instances are grouped into reservations. Reservations are the StartInstancesRequest calls which were used to create one or more EC2 instances:

response.reservations()

From here we can get the actual instances. Let’s get the first instance in the first reservation:

response.reservations().get(0).instances().get(0)

Now, we can describe our instance:

// ...
.imageId()
.subnetId()
.instanceId()
.instanceType()
.state().name()
.monitoring().state()
.kernelId()
.keyName()

5. Conclusion

In this quick tutorial, we showed how to manage Amazon EC2 instances using the Java SDK.

As usual, code snippets can be found over on GitHub.