com.amediamanager.dao.DynamoDbUserDaoImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.amediamanager.dao.DynamoDbUserDaoImpl.java

Source

/*
 * Copyright 2014 Amazon Technologies, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 *
 *    http://aws.amazon.com/apache2.0
 *
 * This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES
 * OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and
 * limitations under the License.
 */
package com.amediamanager.dao;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.annotation.PostConstruct;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.web.multipart.commons.CommonsMultipartFile;

import com.amazonaws.AmazonServiceException;
import com.amazonaws.services.dynamodbv2.AmazonDynamoDB;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.dynamodbv2.model.GetItemRequest;
import com.amazonaws.services.dynamodbv2.model.GetItemResult;
import com.amazonaws.services.dynamodbv2.model.PutItemRequest;
import com.amazonaws.services.dynamodbv2.model.ResourceNotFoundException;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.CannedAccessControlList;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.amazonaws.services.s3.model.PutObjectRequest;
import com.amediamanager.config.ConfigurationSettings;
import com.amediamanager.config.ConfigurationSettings.ConfigProps;
import com.amediamanager.domain.User;
import com.amediamanager.exceptions.DataSourceTableDoesNotExistException;
import com.amediamanager.exceptions.UserExistsException;

public class DynamoDbUserDaoImpl implements UserDao {

    private static final Logger LOG = LoggerFactory.getLogger(DynamoDbUserDaoImpl.class);

    @Autowired
    protected ConfigurationSettings config;

    @Autowired
    protected AmazonDynamoDB dynamoClient;

    @Autowired
    protected AmazonS3 s3Client;

    /** Attribute names **/
    public static final String HASH_KEY_NAME = "EMail";
    public static final String EMAIL_ATTR = HASH_KEY_NAME;
    public static final String PASSWORD_ATTR = "Password";
    public static final String NICKNAME_ATTR = "Nickname";
    public static final String TAGLINE_ATTR = "Tagline";
    public static final String PROFILE_PIC_KEY_ATTR = "ProfilePicKey";
    public static final String ALERT_ON_NEW_CONTENT_ATTR = "AlertOnNewContent";

    @PostConstruct
    public void init() {
    }

    @Override
    public void save(User user) throws UserExistsException, DataSourceTableDoesNotExistException {
        try {
            // See if User item exists
            User existing = this.find(user.getEmail());

            // If the user exists, throw an exception
            if (existing != null) {
                throw new UserExistsException();
            }

            // Convert the User object to a Map. The DynamoDB PutItemRequest object
            // requires the Item to be in the Map<String, AttributeValue> structure
            Map<String, AttributeValue> userItem = getMapFromUser(user);

            // Create a request to save and return the user
            PutItemRequest putItemRequest = new PutItemRequest()
                    .withTableName(config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE))
                    .withItem(userItem);

            // Save user
            dynamoClient.putItem(putItemRequest);
        } catch (ResourceNotFoundException rnfe) {
            throw new DataSourceTableDoesNotExistException(
                    config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE));
        } catch (AmazonServiceException ase) {
            throw ase;
        }
    }

    @Override
    public void update(User user) throws DataSourceTableDoesNotExistException {
        try {
            // If the object includes a profile pic file, upload it to S3
            if (user.getprofilePicData() != null && user.getprofilePicData().getSize() > 0) {
                try {
                    String profilePicUrl = this.uploadFileToS3(user.getprofilePicData());
                    user.setProfilePicKey(profilePicUrl);
                } catch (IOException e) {
                    LOG.error("Error uploading profile pic to S3", e);
                }
            }

            // Convert the User object to a Map
            Map<String, AttributeValue> userItem = getMapFromUser(user);

            // Create a request to save and return the user
            PutItemRequest putItemRequest = new PutItemRequest().withItem(userItem)
                    .withTableName(config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE));

            // Save user
            dynamoClient.putItem(putItemRequest);
        } catch (ResourceNotFoundException rnfe) {
            throw new DataSourceTableDoesNotExistException(
                    config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE));
        } catch (AmazonServiceException ase) {
            throw ase;
        }

    }

    @Override
    public User find(String email) throws DataSourceTableDoesNotExistException {
        try {

            User user = null;

            // Create a request to find a User by email address
            GetItemRequest getItemRequest = new GetItemRequest()
                    .withTableName(config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE))
                    .addKeyEntry(HASH_KEY_NAME, new AttributeValue(email));

            // Issue the request to find the User in DynamoDB
            GetItemResult getItemResult = dynamoClient.getItem(getItemRequest);

            // If an item was found
            if (getItemResult.getItem() != null) {
                // Marshal the Map<String, AttributeValue> structure returned in
                // the
                // GetItemResult to a User object
                user = getUserFromMap(getItemResult.getItem());
            }

            return user;

        } catch (ResourceNotFoundException rnfe) {

            // The ResourceNotFoundException method is thrown by the getItem()
            // method
            // if the DynamoDB table doesn't exist. This exception is re-thrown
            // as a
            // custom, more specific DataSourceTableDoesNotExistException that
            // users
            // of this DAO understand.
            throw new DataSourceTableDoesNotExistException(
                    config.getProperty(ConfigurationSettings.ConfigProps.DDB_USERS_TABLE));
        }
    }

    /**
     * Marshal a Map<String, AttributeValue> object (representing an Item
     * retrieved from DynamoDB) to a User.
     *
     * @return
     */
    public User getUserFromMap(Map<String, AttributeValue> userItem) {
        // Create a new user from the minimum required values. As the password
        // is stored
        // hashed, the last parameter is false to indicate.
        User user = new User();

        user.setEmail(userItem.get(EMAIL_ATTR).getS());
        user.setPassword(userItem.get(PASSWORD_ATTR).getS());
        user.setId(userItem.get(EMAIL_ATTR).getS());

        // Look for other optional attributes and set them for the object if
        // they exist.
        if (null != userItem.get(NICKNAME_ATTR))
            user.setNickname(userItem.get(NICKNAME_ATTR).getS());

        if (null != userItem.get(TAGLINE_ATTR))
            user.setTagline(userItem.get(TAGLINE_ATTR).getS());

        if (null != userItem.get(PROFILE_PIC_KEY_ATTR))
            user.setProfilePicKey((userItem.get(PROFILE_PIC_KEY_ATTR).getS()));

        return user;
    }

    /**
      * Marshal a User object to a Map<String, AttributeValue> suitable for inserting
      * as an item into a DynamoDB table.
      *
      * @param user
      * @return
      */
    public Map<String, AttributeValue> getMapFromUser(User user) {
        // Create a Map object from the User
        Map<String, AttributeValue> userItem = new HashMap<String, AttributeValue>();

        // Add items to the Map
        userItem.put(EMAIL_ATTR, new AttributeValue(user.getEmail()));
        userItem.put(PASSWORD_ATTR, new AttributeValue(user.getPassword()));

        // Ensure User properties are neither null nor empty strings
        if (null != user.getNickname() && true != user.getNickname().isEmpty())
            userItem.put(NICKNAME_ATTR, new AttributeValue(user.getNickname()));

        if (null != user.getTagline() && true != user.getTagline().isEmpty())
            userItem.put(TAGLINE_ATTR, new AttributeValue(user.getTagline()));

        if (null != user.getProfilePicKey() && true != user.getProfilePicKey().isEmpty())
            userItem.put(PROFILE_PIC_KEY_ATTR, new AttributeValue(user.getProfilePicKey()));

        return userItem;
    }

    /**
     * Upload the profile pic to S3 and return it's URL
     * @param profilePic
     * @return The fully-qualified URL of the photo in S3
     * @throws IOException
     */
    public String uploadFileToS3(CommonsMultipartFile profilePic) throws IOException {

        // Profile pic prefix
        String prefix = config.getProperty(ConfigProps.S3_PROFILE_PIC_PREFIX);

        // Date string
        String dateString = new SimpleDateFormat("ddMMyyyy").format(new java.util.Date());
        String s3Key = prefix + "/" + dateString + "/" + UUID.randomUUID().toString() + "_"
                + profilePic.getOriginalFilename();

        // Get bucket
        String s3bucket = config.getProperty(ConfigProps.S3_UPLOAD_BUCKET);

        // Create a ObjectMetadata instance to set the ACL, content type and length
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentType(profilePic.getContentType());
        metadata.setContentLength(profilePic.getSize());

        // Create a PutRequest to upload the image
        PutObjectRequest putObject = new PutObjectRequest(s3bucket, s3Key, profilePic.getInputStream(), metadata);

        // Put the image into S3
        s3Client.putObject(putObject);
        s3Client.setObjectAcl(s3bucket, s3Key, CannedAccessControlList.PublicRead);

        return "http://" + s3bucket + ".s3.amazonaws.com/" + s3Key;
    }
}