io.ignitr.dispatchr.manager.core.data.TopicRepository.java Source code

Java tutorial

Introduction

Here is the source code for io.ignitr.dispatchr.manager.core.data.TopicRepository.java

Source

/*
 * Copyright 2016 Greg Whitaker
 *
 * 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://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License 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 io.ignitr.dispatchr.manager.core.data;

import com.amazonaws.services.dynamodbv2.AmazonDynamoDBClient;
import com.amazonaws.services.dynamodbv2.document.DynamoDB;
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.ItemCollection;
import com.amazonaws.services.dynamodbv2.document.ScanOutcome;
import com.amazonaws.services.dynamodbv2.document.Table;
import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec;
import com.amazonaws.services.dynamodbv2.model.AttributeDefinition;
import com.amazonaws.services.dynamodbv2.model.CreateTableRequest;
import com.amazonaws.services.dynamodbv2.model.KeySchemaElement;
import com.amazonaws.services.dynamodbv2.model.KeyType;
import com.amazonaws.services.dynamodbv2.model.ProvisionedThroughput;
import com.amazonaws.services.dynamodbv2.model.ScalarAttributeType;
import com.amazonaws.services.dynamodbv2.util.TableUtils;
import io.ignitr.dispatchr.manager.core.error.TopicAlreadyRegisteredException;
import io.ignitr.dispatchr.manager.core.error.TopicNotFoundException;
import io.ignitr.dispatchr.manager.domain.internal.Topic;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import rx.Observable;

import javax.annotation.PostConstruct;
import java.util.Arrays;

/**
 * Repository responsible for managing data about registered topics in DynamoDB.
 */
@Component
public class TopicRepository {
    private static final Logger LOG = LoggerFactory.getLogger(TopicRepository.class);
    private static final String TOPIC_TABLE_NAME = "Dispatchr_Topic";

    private final AmazonDynamoDBClient dynamoDBClient;
    private final DynamoDB dynamoDB;

    @Autowired
    public TopicRepository(AmazonDynamoDBClient dynamoDBClient) {
        this.dynamoDBClient = dynamoDBClient;
        this.dynamoDB = new DynamoDB(dynamoDBClient);
    }

    @PostConstruct
    private void initialize() throws Exception {
        LOG.info("Initializing DynamoDB tables for TopicRepository...");

        CreateTableRequest request = new CreateTableRequest(
                Arrays.asList(new AttributeDefinition("name", ScalarAttributeType.S)), TOPIC_TABLE_NAME,
                Arrays.asList(new KeySchemaElement("name", KeyType.HASH)), new ProvisionedThroughput(4L, 1L));

        if (TableUtils.createTableIfNotExists(dynamoDBClient, request)) {
            LOG.info("Creating DynamoDB table '{}'...", TOPIC_TABLE_NAME);
        } else {
            LOG.debug("DynamoDB table '{}' already exists!  Skipping table creation.", TOPIC_TABLE_NAME);
        }

        LOG.info("Waiting for DynamoDB table '{}' to become active...", TOPIC_TABLE_NAME);
        TableUtils.waitUntilActive(dynamoDBClient, TOPIC_TABLE_NAME);
        LOG.info("DynamoDB table '{}' is active", TOPIC_TABLE_NAME);
    }

    /**
     * Finds the metadata for all of the topics.
     *
     * @return an {@link Observable} of {@link Topic} containing the metadata about the topic
     */
    public Observable<Topic> findAll() {
        return Observable.create(subscriber -> {
            Table table = dynamoDB.getTable(TOPIC_TABLE_NAME);

            ItemCollection<ScanOutcome> results = table.scan(new ScanSpec());

            results.forEach(item -> {
                Topic metadata = new Topic();
                metadata.setName(item.getString("name"));
                metadata.setArn(item.getString("arn"));
                metadata.setRegistered(true);

                subscriber.onNext(metadata);
            });

            subscriber.onCompleted();
        });
    }

    /**
     * Finds the metadata for single topic.
     *
     * @param topicName name of the topic
     * @return an {@link Observable} of {@link Topic} containing the metadata about the topic
     */
    public Observable<Topic> findOne(String topicName) {
        return Observable.create(subscriber -> {
            Table table = dynamoDB.getTable(TOPIC_TABLE_NAME);

            Item item = table.getItem("name", topicName);

            if (item == null) {
                throw new TopicNotFoundException(topicName);
            } else {
                Topic metadata = new Topic();
                metadata.setName(item.getJSON("name"));
                metadata.setArn(item.getJSON("arn"));
                metadata.setRegistered(true);

                subscriber.onNext(metadata);
                subscriber.onCompleted();
            }
        });
    }

    /**
     * Saves the metadata about a registered topic.
     *
     * @param topicName name of the topic
     * @param topicArn arn of the topic
     * @return an {@link Observable} of {@link Topic} containing the metadata about the topic that was saved
     */
    public Observable<Topic> save(String topicName, String topicArn) {
        return Observable.create(subscriber -> {
            Topic metadata = new Topic();
            metadata.setName(topicName);
            metadata.setArn(topicArn);
            metadata.setRegistered(true);

            Table table = dynamoDB.getTable(TOPIC_TABLE_NAME);

            if (table.getItem("name", metadata.getName()) != null) {
                throw new TopicAlreadyRegisteredException(metadata.getName());
            }

            table.putItem(new Item().withPrimaryKey("name", metadata.getName()).withString("arn", metadata.getArn())
                    .withLong("register_timestamp", System.currentTimeMillis()));

            subscriber.onNext(metadata);
            subscriber.onCompleted();
        });
    }

    /**
     * Deletes the metadata about a registered topic.
     *
     * @param topicName name of the topic
     * @param topicArn arn of the topic
     * @return an {@link Observable} of {@link Topic} containing the metadata about the topic that was deleted
     */
    public Observable<Topic> delete(String topicName, String topicArn) {
        return Observable.create(subscriber -> {
            Topic metadata = new Topic();
            metadata.setName(topicName);
            metadata.setArn(topicArn);
            metadata.setRegistered(false);

            Table table = dynamoDB.getTable(TOPIC_TABLE_NAME);

            if (table.getItem("name", metadata.getName()) == null) {
                throw new TopicNotFoundException(metadata.getName());
            }

            table.deleteItem("name", metadata.getName());

            subscriber.onNext(metadata);
            subscriber.onCompleted();
        });
    }
}