Using Amazon SimpleDB services from a Java program

Amazon SimpleDB is a highly available and flexible NoSQL data store. Unlike schema-driven relational databases, SimpleDB's flexibility allows you to change your data model on the fly. The infrastructure provisioning, software installation and maintenance, and high availability feature for SimpleDB is managed by AWS; thereby, alleviating the need for typical database administration tasks.

SimpleDB consists of domains where each domain stores a set of records or items. Each of the items has a unique key, and is described by a set of attribute/value pairs. It is not necessary for the items to contain all the attributes. The data in a domain is automatically indexed by each of the attributes, hence enabling access by any one or more attributes. There is no need for a predefined schema and schema changes, in response new attributes are added later on. However, you can run queries on the data stored within a specific domain only. You can also choose between consistent and eventually consistent read requests for additional flexibility in meeting the specific performance versus consistency requirements of your application.

You can store, query, and update data items via API/web service calls. SimpleDB provides SDKs to access the stored data from several programming languages. SimpleDB integrates with other AWS services such as EC2, S3, and IAM to provide you with a complete environment to develop secure web-scale applications.

Typical use cases include storing your application logs, centrally, versus storing them on each of your running servers. This is a significant benefit for monitoring and troubleshooting issues in an autoscaled environment. Another good use case for SimpleDB usage is to store Simple Storage Service (S3) metadata information. SimpleDB can easily provide storage, indexing, and querying abilities on this metadata. For example, you can store your videos on S3 and the associated metadata, including the pointers to the S3 object locations on SimpleDB.

How to do it…

In this section, we present a recipe to use SimpleDB services from a Java program. Follow the steps listed below:

  1. Install AWS Java SDK.

    In your Maven dependency section, add the following dependency for AWS Java SDK Version 1.9.28.1:

    <dependency>
        <groupId>com.amazonaws</groupId>
        <artifactId>aws-java-sdk</artifactId>
        <version>1.9.28.1</version>
    </dependency>
  2. Initialize SimpleDB client.

    The following code initializes and returns a SimpleDB client:

        // Initialize SimpleDB client.
            public static AmazonSimpleDBClient Initialize() {
    
        // Create BasicAWSCredentials with Access Key Id and Secret Access Key.
            BasicAWSCredentials credentials = new BasicAWSCredentials(
                    "Access Key Id",
                    "Secret Access Key");
    
    // Create SimpleDB client.
            AmazonSimpleDBClient simpleDBClient = new AmazonSimpleDBClient(
                    credentials);
    
    // Set endpoint.
            simpleDBClient.setEndpoint("sdb.ap-southeast- 1.amazonaws.com");
    
    // Return client.
            return simpleDBClient;
        }
  3. Create a domain.

    The following code creates a domain with the name "user":

        // Create SimpleDB domain.
            public static void CreateDomain() {
    
        // Get SimpleDB client.
            AmazonSimpleDBClient simpleDBClient = Initialize();
    
        // Create domain request.
            CreateDomainRequest request = new CreateDomainRequest(
                "user");
    
        // Creates domain.
            simpleDBClient.createDomain(request);
        }
  4. Insert data into SimpleDB domain.

    The following code inserts a single user item with the item name "Andrew" in the "user" domain:

        // Insert item.
            public static void InsertItem() {
    
        // Get SimpleDB client.
            AmazonSimpleDBClient simpleDBClient = Initialize();
    
        // Name attribute.
            ReplaceableAttribute nameAttribute = new ReplaceableAttribute();
            nameAttribute.setName("Name");
            nameAttribute.setValue("Andrew");
    
        // Age attribute.
            ReplaceableAttribute ageAttribute = new ReplaceableAttribute();
            ageAttribute.setName("Age");
            ageAttribute.setValue("28");
    
        // City attribute.
            ReplaceableAttribute cityAttribute = new ReplaceableAttribute();
            cityAttribute.setName("City");
            cityAttribute.setValue("San Francisco");
    
        // Create collection for attributes.
            Collection<ReplaceableAttribute> item = new ArrayList<>();
            item.add(nameAttribute);
            item.add(ageAttribute);
            item.add(cityAttribute);
    
        // Put request.
            PutAttributesRequest request = new PutAttributesRequest();
    
        // Set domain name.
            request.setDomainName("user");
    
        // Set item name.
            request.setItemName("andrew");
        // Set item attributes.
            request.setAttributes(item);
    
        // Insert item into domain.
            simpleDBClient.putAttributes(request);
        }
  5. Retrieve the item from the domain.

    The following code retrieves the item with item name "Andrew":

        // Retrieve item.
            public static void GetItem() {
    
        // Get SimpleDB client.
            AmazonSimpleDBClient simpleDBClient = Initialize();
    
        // Prepare get request.
            GetAttributesRequest request = new GetAttributesRequest();
    
        // Set domain name.
            request.setDomainName("user");
    
        // Set item name.
            request.setItemName("andrew");
    
        // Get item from domain.
            GetAttributesResult result = simpleDBClient.getAttributes(request);
    
        // Iterate through all attributes.
            for (Attribute attribute : result.getAttributes()) {
    
        // Get attribute name.
            String name = attribute.getName();
    
        // Get attribute value.
            String value = attribute.getValue();
            }
        }

How it works…

In the first step, we downloaded AWS Java SDK. This SDK helps us access AWS services from Java applications. Before interacting with SimpleDB, we need to specify the access key ID and secret access key of our AWS account. Instead of hardcoding AWS credentials in our Java code, we can create an IAM role with SimpleDB access permissions and launch the instance with that role.

Next, we create the SimpleDB client object that is used to interact with SimpleDB service.

Note

All service calls made using the SimpleDB client are blocking calls, and it will not return until the service call is completed.

SimpleDB domains are like database tables. You must create a domain before inserting data into it. So, in the next step, we created a SimpleDB domain. The createDomain operation creates a new domain. The domain name should be unique among all the domains associated with the access key. The client can create a maximum of up to 100 domains per account. If additional domains are required, then they need to be specifically requested from Amazon.

In SimpleDB, items are like rows in a relational database table. Each item has an item name to uniquely identify the item in a given domain. Each item contains attributes, similar to columns. Each attribute has an attribute name and an attribute value. In the next step, we inserted an item using the putAttributes operation. The client may specify new attributes using a combination of name/value parameters. The attributes are also uniquely identified in an item by their name/value pairs. Note that you cannot have an empty string as an attribute name, and two attribute instances cannot have the same names and values. We create PutAttributesRequest as a container for our request, and then pass it to the putAttributes operation for inserting our item.

Lastly, we retrieved the newly inserted item to verify our insert into SimpleDB.

Note

As Amazon SimpleDB makes multiple copies of the data and uses an eventual consistency update model, an immediate getAttributes operation following a putAttributes operation may not return the requested data.

We use GetAttributesRequest as a container for our request, and then pass it to the getAttributes operation for retrieving our item.

There's more…

Relational databases are typically normalized to minimize duplication of data. These databases contain tables with primary and foreign keys to represent relationships between various tables in the database. We use joins to combine data from the tables to form the result sets for the queries. However, there is no equivalent join operation available in Amazon SimpleDB. Hence, if you need to access the data from multiple domains, you will typically need to execute multiple queries.

In order to avoid multiple queries, it is common to de-normalize your data to better reflect the nature of your queries. This is often achieved by combining the data from multiple domains into a single domain or duplicating the data across multiple domains to support your queries, efficiently. For example, if you have two separate domains for your employee and employee address, then you would need two separate queries to access a specific employee's name and the associated address information. In such a situation, you may want to combine the items in the two domains into one domain, and then pull the employee name and the associated address with a single query.

Similarly, if we had the employee and role information in two separate domains, then we may want to duplicate the employee data in the role domain and vice versa. This data duplication can help support queries, such as the role of a specific employee and employees in a specific role, more efficiently. You have to understand your data and queries really well in order to finalize the degree of de-normalization required in your design.

Data is stored as character strings in Amazon SimpleDB. This can present some challenges in your queries due to lexicographic comparisons. This is true especially for numeric and date data types. For resolving these issues for numeric values, you will need to pad them appropriately. For negative numbers, you will need to add offsets while storing them and subtract the same offset value during retrieval. To reduce your costs, you should do these operations only for the fields used in query comparisons. For resolving issues related to date comparisons, a good approach is to use the ISO 8601 format dates.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset