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.AttributeUpdate; 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.UpdateItemOutcome; import com.amazonaws.services.dynamodbv2.document.spec.ScanSpec; import com.amazonaws.services.dynamodbv2.document.spec.UpdateItemSpec; 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.ClientAlreadyRegisteredException; import io.ignitr.dispatchr.manager.core.error.ClientNotFoundException; import io.ignitr.dispatchr.manager.domain.internal.Client; 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 storing and retrieving information about Dispatchr clients in DynamoDB. */ @Component public class ClientRepository { private static final Logger LOG = LoggerFactory.getLogger(ClientRepository.class); private static final String CLIENT_TABLE_NAME = "Dispatchr_Client"; private final AmazonDynamoDBClient dynamoDBClient; private final DynamoDB dynamoDB; @Autowired public ClientRepository(AmazonDynamoDBClient dynamoDBClient) { this.dynamoDBClient = dynamoDBClient; this.dynamoDB = new DynamoDB(dynamoDBClient); } /** * Creates the DynamoDB tables that are used by this repository. * * @throws Exception */ @PostConstruct private void initialize() throws Exception { LOG.info("Initializing DynamoDB tables for TopicRepository..."); CreateTableRequest clientRequest = new CreateTableRequest( Arrays.asList(new AttributeDefinition("clientId", ScalarAttributeType.S)), CLIENT_TABLE_NAME, Arrays.asList(new KeySchemaElement("clientId", KeyType.HASH)), new ProvisionedThroughput(4L, 1L)); if (TableUtils.createTableIfNotExists(dynamoDBClient, clientRequest)) { LOG.info("Creating DynamoDB table '{}'...", CLIENT_TABLE_NAME); } else { LOG.debug("DynamoDB table '{}' already exists! Skipping table creation.", CLIENT_TABLE_NAME); } LOG.info("Waiting for DynamoDB table '{}' to become active...", CLIENT_TABLE_NAME); TableUtils.waitUntilActive(dynamoDBClient, CLIENT_TABLE_NAME); LOG.info("DynamoDB table '{}' is active", CLIENT_TABLE_NAME); } /** * Saves a new client in DynamoDB. * * @param clientId client identifier * @param ownerName name of the person who owns the client * @param ownerEmail email of the person who owns the client * @return an {@link Observable} that emits the newly saved client */ public Observable<Client> save(String clientId, String ownerName, String ownerEmail) { return Observable.create(subscriber -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); if (clientTable.getItem("clientId", clientId) != null) { throw new ClientAlreadyRegisteredException(clientId); } Client client = new Client(); client.setClientId(clientId); client.setOwnerName(ownerName); client.setOwnerEmail(ownerEmail); clientTable.putItem(new Item().withPrimaryKey("clientId", client.getClientId()) .withString("ownerName", client.getOwnerName()) .withString("ownerEmail", client.getOwnerEmail())); subscriber.onNext(client); subscriber.onCompleted(); }); } /** * Deletes a client from DynamoDB. * * @param clientId client identifier * @return an {@link Observable} that emits <code>true</code> if the delete was successful; otherwise <code>false</code> */ public Observable<Boolean> delete(String clientId) { return findOne(clientId).flatMap(client -> Observable.create(subscriber -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); clientTable.deleteItem("clientId", client.getClientId()); subscriber.onNext(true); subscriber.onCompleted(); })); } /** * Finds all clients in DynamoDB. * * @param offset number of records to offset when paginating * @param limit number of records to return when paginating * @param sortDir the direction to sort returned records when paginating * @param active a boolean flag indicating whether or not to return only "active" clients * @return an {@link Observable} that emits all clients */ public Observable<Client> findAll(long offset, long limit, String sortDir, boolean active) { return Observable.create(subscriber -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); ItemCollection<ScanOutcome> results = clientTable.scan(new ScanSpec()); results.forEach(item -> subscriber.onNext(convertFromItem(item))); subscriber.onCompleted(); }); } /** * Finds a single client by id in DynamoDB. * * @param clientId client identifier * @return an {@link Observable} that emits the client */ public Observable<Client> findOne(String clientId) { return Observable.create(subscriber -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); Item item = clientTable.getItem("clientId", clientId); if (item == null) { throw new ClientNotFoundException(clientId); } else { subscriber.onNext(convertFromItem(item)); subscriber.onCompleted(); } }); } /** * Checks whether or not a client with the supplied id exists in DynamoDB. * * @param clientId client identifier * @return an {@link Observable} that emits <code>true</code> if the delete was successful; otherwise <code>false</code> */ public Observable<Boolean> exists(String clientId) { return Observable.create(subscriber -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); Item item = clientTable.getItem("clientId", clientId); if (item == null) { subscriber.onNext(false); } else { subscriber.onNext(true); } subscriber.onCompleted(); }); } /** * * @param newClient * @return */ public Observable<Client> update(Client newClient) { return findOne(newClient.getClientId()).last().map(oldClient -> { Table clientTable = dynamoDB.getTable(CLIENT_TABLE_NAME); UpdateItemOutcome outcome = clientTable .updateItem(new UpdateItemSpec().withPrimaryKey("clientId", oldClient.getClientId()) .withAttributeUpdate(new AttributeUpdate("ownerName").put(newClient.getOwnerName())) .withAttributeUpdate(new AttributeUpdate("ownerEmail").put(newClient.getOwnerEmail()))); Item item = outcome.getItem(); return convertFromItem(item); }); } /** * * @param item * @return */ public Client convertFromItem(Item item) { Client client = new Client(); client.setClientId(item.getString("clientId")); client.setOwnerName(item.getString("ownerName")); client.setOwnerEmail(item.getString("ownerEmail")); return client; } }