Java tutorial
/* * 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(); }); } }