类com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException源码实例Demo

下面列出了怎么用com.amazonaws.services.dynamodbv2.model.ConditionalCheckFailedException的API类实例代码及写法,或者点击链接到github查看源代码。

源代码1 项目: strongbox   文件: GenericDynamoDB.java
@Override
public void create(Entry entry) {
    readWriteLock.writeLock().lock();

    try {
        Map<String, AttributeValue> keys = createKey(entry);
        Map<String, AttributeValueUpdate> attributes = createAttributes(entry);
        Map<String, ExpectedAttributeValue> expected = expectNotExists();

        try {
            executeUpdate(keys, attributes, expected);
        } catch (ConditionalCheckFailedException e) {
            throw new AlreadyExistsException("DynamoDB store entry already exists:" + keys.toString());
        }
    } finally {
        readWriteLock.writeLock().unlock();
    }
}
 
源代码2 项目: strongbox   文件: GenericDynamoDB.java
@Override
public void update(Entry entry, Entry existingEntry) {
    readWriteLock.writeLock().lock();

    try {
        Map<String, AttributeValue> keys = createKey(entry);
        Map<String, AttributeValueUpdate> attributes = createAttributes(entry);
        Map<String, ExpectedAttributeValue> expected = expectExists(existingEntry);

        try {
            executeUpdate(keys, attributes, expected);
        } catch (ConditionalCheckFailedException e) {
            throw new DoesNotExistException("Precondition to update entry in DynamoDB failed:" + keys.toString());
        }
    } finally {
        readWriteLock.writeLock().unlock();
    }

}
 
源代码3 项目: strongbox   文件: GenericDynamoDBTest.java
@Test
public void testCreateEntryAlreadyExists() throws Exception {
    RawSecretEntry rawSecretEntry = constructRawEntry(SECRET_NAME);
    UpdateItemRequest expectedUpdateRequest = constructUpdateItemRequest(rawSecretEntry, false, Optional.empty());

    // Already exists will cause a check failed exception.
    when(mockDynamoDBClient.updateItem(expectedUpdateRequest)).thenThrow(
            new ConditionalCheckFailedException(""));

    boolean exceptionThrown = false;
    try {
        dynamoDB.create(rawSecretEntry);
    } catch (AlreadyExistsException e) {
        assertEquals(e.getMessage(), "DynamoDB store entry already exists:{1={S: secret1,}, 2={N: 1,}}");
        exceptionThrown = true;
    }
    assertTrue(exceptionThrown);
    verify(mockDynamoDBClient, times(1)).updateItem(expectedUpdateRequest);
}
 
源代码4 项目: strongbox   文件: GenericDynamoDBTest.java
@Test
public void testUpdateEntryDoesNotExist() throws Exception {
    RawSecretEntry rawSecretEntry = constructRawEntry(SECRET_NAME);
    RawSecretEntry alternativeRawSecretEntry = constructAlternativeRawSecretEntry(SECRET_NAME);

    UpdateItemRequest expectedUpdateRequest = constructUpdateItemRequest(rawSecretEntry, true, Optional.of(alternativeRawSecretEntry));

    when(mockDynamoDBClient.updateItem(expectedUpdateRequest)).thenThrow(
            new ConditionalCheckFailedException(""));

    boolean exceptionThrown = false;
    try {
        dynamoDB.update(rawSecretEntry, alternativeRawSecretEntry);
    } catch (DoesNotExistException e) {
        assertEquals(e.getMessage(), "Precondition to update entry in DynamoDB failed:{1={S: secret1,}, 2={N: 1,}}");
        exceptionThrown = true;
    }
    assertTrue(exceptionThrown);

    // Check all the expected calls to AWS were made.
    verify(mockDynamoDBClient, times(1)).updateItem(expectedUpdateRequest);
}
 
@Test
public void createVersionedItemWhenItemAlreadyExists() {
    ExampleVersionedHashKeyItem item1 = newVersionedItem();

    Transaction t1 = manager.newTransaction();
    t1.save(item1);
    t1.commit();
    assertItemNotLocked(INTEG_HASH_TABLE_NAME, item1.getKey(), item1.getExpectedValues(), true);

    ExampleVersionedHashKeyItem item2 = new ExampleVersionedHashKeyItem();
    item2.setId(item1.getId());
    Transaction t2 = manager.newTransaction();
    try {
        t2.save(item2);
        fail();
    } catch (ConditionalCheckFailedException e) {
        t2.rollback();
    }
    assertItemNotLocked(INTEG_HASH_TABLE_NAME, item1.getKey(), item1.getExpectedValues(), true);

    t1.delete(Long.MAX_VALUE);
    t2.delete(Long.MAX_VALUE);
}
 
源代码6 项目: dynamodb-transactions   文件: Transaction.java
/**
 * Deletes the transaction item from the database.
 * 
 * Does not throw if the item is gone, even if the conditional check to delete the item fails, and this method doesn't know what state
 * it was in when deleted.  The caller is responsible for guaranteeing that it was actually in "currentState" immediately before calling
 * this method.  
 */
protected void complete(final State expectedCurrentState) {
    try {
        txItem.complete(expectedCurrentState);
    } catch (ConditionalCheckFailedException e) {
        // Re-read state to ensure it was already completed
        try {
            txItem = new TransactionItem(txId, txManager, false);
            if(! txItem.isCompleted()) {
                throw new TransactionAssertionException(txId, "Expected the transaction to be completed (no item), but there was one.");
            }
        } catch (TransactionNotFoundException tnfe) {
            // expected - transaction record no longer exists
        }
    }
}
 
源代码7 项目: dynamodb-transactions   文件: TransactionItem.java
/**
 * Inserts a new transaction item into the table.  Assumes txKey is already initialized.
 * @return the txItem
 * @throws TransactionException if the transaction already exists
 */
private Map<String, AttributeValue> insert() {
    Map<String, AttributeValue> item = new HashMap<String, AttributeValue>();
    item.put(AttributeName.STATE.toString(), new AttributeValue(STATE_PENDING));
    item.put(AttributeName.VERSION.toString(), new AttributeValue().withN(Integer.toString(1)));
    item.put(AttributeName.DATE.toString(), txManager.getCurrentTimeAttribute());
    item.putAll(txKey);
    
    Map<String, ExpectedAttributeValue> expectNotExists = new HashMap<String, ExpectedAttributeValue>(2);
    expectNotExists.put(AttributeName.TXID.toString(), new ExpectedAttributeValue(false));
    expectNotExists.put(AttributeName.STATE.toString(), new ExpectedAttributeValue(false));
    
    PutItemRequest request = new PutItemRequest()
        .withTableName(txManager.getTransactionTableName())
        .withItem(item)
        .withExpected(expectNotExists);
    
    try {
        txManager.getClient().putItem(request);
        return item;
    } catch (ConditionalCheckFailedException e) {
        throw new TransactionException("Failed to create new transaction with id " + txId, e);
    }
}
 
/**
 * Checks a map of expected values against a map of actual values in a way
 * that's compatible with how the DynamoDB service interprets the Expected
 * parameter of PutItem, UpdateItem and DeleteItem.
 *
 * @param expectedValues
 *            A description of the expected values.
 * @param item
 *            The actual values.
 * @throws ConditionalCheckFailedException
 *             Thrown if the values do not match the expected values.
 */
public static void checkExpectedValues(Map<String, ExpectedAttributeValue> expectedValues, Map<String, AttributeValue> item) {
    for (Map.Entry<String, ExpectedAttributeValue> entry : expectedValues.entrySet()) {
        // if the attribute is expected to exist (null for isExists means
        // true)
        if ((entry.getValue().isExists() == null || entry.getValue().isExists() == true)
                // but the item doesn't
                && (item == null
                        // or the attribute doesn't
                        || item.get(entry.getKey()) == null
                        // or it doesn't have the expected value
                        || !expectedValueMatches(entry.getValue().getValue(), item.get(entry.getKey())))) {
            throw new ConditionalCheckFailedException(
                    "expected attribute(s) " + expectedValues
                            + " but found " + item);
        } else if (entry.getValue().isExists() != null
                && !entry.getValue().isExists()
                && item != null && item.get(entry.getKey()) != null) {
            // the attribute isn't expected to exist, but the item exists
            // and the attribute does too
            throw new ConditionalCheckFailedException(
                    "expected attribute(s) " + expectedValues
                            + " but found " + item);
        }
    }
}
 
private static void updateExistingAttributeConditionally() {
    try {

        HashMap<String, AttributeValue> key = new HashMap<String, AttributeValue>();
        key.put("Id", new AttributeValue().withN("120"));

        // Specify the desired price (25.00) and also the condition (price =
        // 20.00)

        Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
        expressionAttributeValues.put(":val1", new AttributeValue().withN("25.00"));
        expressionAttributeValues.put(":val2", new AttributeValue().withN("20.00"));

        ReturnValue returnValues = ReturnValue.ALL_NEW;

        UpdateItemRequest updateItemRequest = new UpdateItemRequest().withTableName(tableName).withKey(key)
            .withUpdateExpression("set Price = :val1").withConditionExpression("Price = :val2")
            .withExpressionAttributeValues(expressionAttributeValues).withReturnValues(returnValues);

        UpdateItemResult result = client.updateItem(updateItemRequest);

        // Check the response.
        System.out.println("Printing item after conditional update to new attribute...");
        printItem(result.getAttributes());
    }
    catch (ConditionalCheckFailedException cse) {
        // Reload object and retry code.
        System.err.println("Conditional check failed in " + tableName);
    }
    catch (AmazonServiceException ase) {
        System.err.println("Error updating item in " + tableName);
    }
}
 
源代码10 项目: ShedLock   文件: DynamoDBLockProvider.java
@Override
@NonNull
public Optional<SimpleLock> lock(@NonNull LockConfiguration lockConfiguration) {
    String nowIso = toIsoString(now());
    String lockUntilIso = toIsoString(lockConfiguration.getLockAtMostUntil());

    UpdateItemSpec request = new UpdateItemSpec()
            .withPrimaryKey(ID, lockConfiguration.getName())
            .withUpdateExpression(OBTAIN_LOCK_QUERY)
            .withConditionExpression(OBTAIN_LOCK_CONDITION)
            .withValueMap(new ValueMap()
                    .withString(":lockUntil", lockUntilIso)
                    .withString(":lockedAt", nowIso)
                    .withString(":lockedBy", hostname)
            )
            .withReturnValues(ReturnValue.UPDATED_NEW);

    try {
        // There are three possible situations:
        // 1. The lock document does not exist yet - it is inserted - we have the lock
        // 2. The lock document exists and lockUtil <= now - it is updated - we have the lock
        // 3. The lock document exists and lockUtil > now - ConditionalCheckFailedException is thrown
        table.updateItem(request);
        return Optional.of(new DynamoDBLock(table, lockConfiguration));
    } catch (ConditionalCheckFailedException e) {
        // Condition failed. This means there was a lock with lockUntil > now.
        return Optional.empty();
    }
}
 
private BackendException processDynamoDbApiException(final Throwable e, final String apiName, final String tableName) {
    Preconditions.checkArgument(apiName != null);
    Preconditions.checkArgument(!apiName.isEmpty());
    final String prefix;
    if (tableName == null) {
        prefix = apiName;
    } else {
        prefix = String.format("%s_%s", apiName, tableName);
    }
    final String message = String.format("%s %s", prefix, e.getMessage());
    if (e instanceof ResourceNotFoundException) {
        return new BackendNotFoundException(String.format("%s; table not found", message), e);
    } else if (e instanceof ConditionalCheckFailedException) {
        return new PermanentLockingException(message, e);
    } else if (e instanceof AmazonServiceException) {
        if (e.getMessage() != null
            && (e.getMessage().contains(HASH_RANGE_KEY_SIZE_LIMIT) || e.getMessage().contains(UPDATE_ITEM_SIZE_LIMIT))) {
            return new PermanentBackendException(message, e);
        } else {
            return new TemporaryBackendException(message, e);
        }
    } else if (e instanceof AmazonClientException) { //all client exceptions are retriable by default
        return new TemporaryBackendException(message, e);
    } else if (e instanceof SocketException) { //sometimes this doesn't get caught by SDK
        return new TemporaryBackendException(message, e);
    }
    // unknown exception type
    return new PermanentBackendException(message, e);
}
 
源代码12 项目: aws-dynamodb-encryption-java   文件: MetaStore.java
/**
 * This API retrieves the intermediate keys from the source region and replicates it in the target region.
 *
 * @param materialName material name of the encryption material.
 * @param version version of the encryption material.
 * @param targetMetaStore target MetaStore where the encryption material to be stored.
 */
public void replicate(final String materialName, final long version, final MetaStore targetMetaStore) {
    try {
        Map<String, AttributeValue> item = getMaterialItem(materialName, version);
        final Map<String, AttributeValue> plainText = getPlainText(item);
        final Map<String, AttributeValue> encryptedText = targetMetaStore.getEncryptedText(plainText);
        final PutItemRequest put = new PutItemRequest().withTableName(targetMetaStore.tableName).withItem(encryptedText)
                .withExpected(doesNotExist);
        targetMetaStore.ddb.putItem(put);
    } catch (ConditionalCheckFailedException e) {
        //Item already present.
    }
}
 
源代码13 项目: aws-dynamodb-encryption-java   文件: MetaStore.java
private Map<String, AttributeValue> conditionalPut(final Map<String, AttributeValue> item) {
    try {
        final PutItemRequest put = new PutItemRequest().withTableName(tableName).withItem(item)
                .withExpected(doesNotExist);
        ddb.putItem(put);
        return item;
    } catch (final ConditionalCheckFailedException ex) {
        final Map<String, AttributeValue> ddbKey = new HashMap<>();
        ddbKey.put(DEFAULT_HASH_KEY, item.get(DEFAULT_HASH_KEY));
        ddbKey.put(DEFAULT_RANGE_KEY, item.get(DEFAULT_RANGE_KEY));
        return ddbGet(ddbKey);
    }
}
 
源代码14 项目: Cheddar   文件: DynamoDocumentStoreTemplate.java
@Override
public <T extends Item> T update(final T item,
        final PersistenceExceptionHandler<?>... persistenceExceptionHandlers) {
    final ItemConfiguration itemConfiguration = getItemConfiguration(item.getClass());
    if (item.getVersion() == null) {
        return create(item);
    }

    final Expected expectedCondition = new Expected(VERSION_ATTRIBUTE).eq(item.getVersion());
    final Long newVersion = item.getVersion() + 1l;
    item.setVersion(newVersion);

    final String tableName = databaseSchemaHolder.schemaName() + "." + itemConfiguration.tableName();
    final String itemJson = itemToString(item);
    final PrimaryKey primaryKey = new PrimaryKey();
    final ItemId itemId = itemConfiguration.getItemId(item);
    final PrimaryKeyDefinition primaryKeyDefinition = itemConfiguration.primaryKeyDefinition();
    primaryKey.addComponent(primaryKeyDefinition.propertyName(), itemId.value());
    if (primaryKeyDefinition instanceof CompoundPrimaryKeyDefinition) {
        primaryKey.addComponent(((CompoundPrimaryKeyDefinition) primaryKeyDefinition).supportingPropertyName(),
                itemId.supportingValue());
    }
    final Table table = dynamoDBClient.getTable(tableName);
    final com.amazonaws.services.dynamodbv2.document.Item previousAwsItem = table.getItem(primaryKey);
    final String previousItemJson = previousAwsItem.toJSON();

    final String mergedJson = mergeJSONObjects(itemJson, previousItemJson);
    final com.amazonaws.services.dynamodbv2.document.Item awsItem = com.amazonaws.services.dynamodbv2.document.Item
            .fromJSON(mergedJson);
    final PutItemSpec putItemSpec = new PutItemSpec().withItem(awsItem).withExpected(expectedCondition);
    try {
        table.putItem(putItemSpec);
    } catch (final ConditionalCheckFailedException e) {
        throw new OptimisticLockException("Conflicting write detected while updating item");
    }
    return item;
}
 
源代码15 项目: Cheddar   文件: DynamoDocumentStoreTemplateTest.java
@Test
public void shouldNotUpdate_withPutItemException() {
    // Given
    final ItemId itemId = new ItemId(randomId());
    final StubItem stubItem = generateRandomStubItem(itemId);
    final StubItem previousStubItem = generateRandomStubItem(itemId);
    final ItemConfiguration itemConfiguration = new ItemConfiguration(StubItem.class, tableName);
    final Collection<ItemConfiguration> itemConfigurations = Arrays.asList(itemConfiguration);
    final Table mockTable = mock(Table.class);
    final Item mockTableItem = mock(Item.class);
    final PrimaryKey primaryKey = new PrimaryKey();
    primaryKey.addComponent("id", itemId.value());
    final Item previousItem = mock(Item.class);

    when(mockDatabaseSchemaHolder.itemConfigurations()).thenReturn(itemConfigurations);
    when(mockDynamoDBClient.getTable(schemaName + "." + tableName)).thenReturn(mockTable);
    when(mockTable.getItem(any(PrimaryKey.class))).thenReturn(previousItem);

    final DynamoDocumentStoreTemplate dynamoDocumentStoreTemplate = new DynamoDocumentStoreTemplate(
            mockDatabaseSchemaHolder);
    when(previousItem.toJSON()).thenReturn(dynamoDocumentStoreTemplate.itemToString(previousStubItem));
    when(mockTableItem.toJSON()).thenReturn(dynamoDocumentStoreTemplate.itemToString(stubItem));
    when(mockTable.putItem(any(PutItemSpec.class))).thenThrow(ConditionalCheckFailedException.class);

    dynamoDocumentStoreTemplate.initialize(mockAmazonDynamoDbClient);

    // When
    OptimisticLockException thrownException = null;
    try {
        dynamoDocumentStoreTemplate.update(stubItem);
    } catch (final OptimisticLockException optimisticLockException) {
        thrownException = optimisticLockException;
    }

    // Then
    assertNotNull(thrownException);
}
 
源代码16 项目: tutorials   文件: SavePersonHandler.java
private PutItemOutcome persistData(PersonRequest personRequest) throws ConditionalCheckFailedException {
    return this.dynamoDb.getTable(DYNAMODB_TABLE_NAME)
      .putItem(
        new PutItemSpec().withItem(new Item()
          .withNumber("id", personRequest.getId())
          .withString("firstName", personRequest.getFirstName())
          .withString("lastName", personRequest.getLastName())
          .withNumber("age", personRequest.getAge())
          .withString("address", personRequest.getAddress())));
}
 
private static void updateExistingAttributeConditionally() {
    try {
        

        HashMap<String, AttributeValue> key = new HashMap<String, AttributeValue>();
        key.put("Id", new AttributeValue().withN("120"));

        // Specify the desired price (25.00) and also the condition (price = 20.00)
       
        Map<String, AttributeValue> expressionAttributeValues = new HashMap<String, AttributeValue>();
        expressionAttributeValues.put(":val1", new AttributeValue().withN("25.00")); 
        expressionAttributeValues.put(":val2", new AttributeValue().withN("20.00")); 
        
        ReturnValue returnValues = ReturnValue.ALL_NEW;

        UpdateItemRequest updateItemRequest = new UpdateItemRequest()
            .withTableName(tableName)
            .withKey(key)
            .withUpdateExpression("set Price = :val1")
            .withConditionExpression("Price = :val2")
            .withExpressionAttributeValues(expressionAttributeValues)
            .withReturnValues(returnValues);

        UpdateItemResult result = client.updateItem(updateItemRequest);
        
        // Check the response.
        System.out.println("Printing item after conditional update to new attribute...");
        printItem(result.getAttributes());            
    } catch (ConditionalCheckFailedException cse) {
        // Reload object and retry code.
        System.err.println("Conditional check failed in " + tableName);
    } catch (AmazonServiceException ase) {
        System.err.println("Error updating item in " + tableName);
    }        
}
 
源代码18 项目: aws-dynamodb-examples   文件: MoviesItemOps02.java
public static void main(String[] args)  {

        AmazonDynamoDBClient client = new AmazonDynamoDBClient();
        client.setEndpoint("http://localhost:8000");
        DynamoDB dynamoDB = new DynamoDB(client);

        Table table = dynamoDB.getTable("Movies");

        int year = 2015;
        String title = "The Big New Movie";

        final Map<String, Object> infoMap = new HashMap<String, Object>();
        infoMap.put("plot",  "Nothing happens at all.");
        infoMap.put("rating",  0.0);
        Item item = new Item()
            .withPrimaryKey(new PrimaryKey("year", year, "title", title))
            .withMap("info", infoMap);
        
        // Attempt a conditional write.  We expect this to fail.

        PutItemSpec putItemSpec = new PutItemSpec()
            .withItem(item)
            .withConditionExpression("attribute_not_exists(#yr) and attribute_not_exists(title)")
            .withNameMap(new NameMap()
                .with("#yr", "year"));
        
        System.out.println("Attempting a conditional write...");
        try {
            table.putItem(putItemSpec);
            System.out.println("PutItem succeeded: " + table.getItem("year", year, "title", title).toJSONPretty());
        } catch (ConditionalCheckFailedException e) {
            e.printStackTrace(System.err);
            System.out.println("PutItem failed");
        }
    }
 
源代码19 项目: aws-dynamodb-examples   文件: MoviesItemOps05.java
public static void main(String[] args)  {

        AmazonDynamoDBClient client = new AmazonDynamoDBClient();
        client.setEndpoint("http://localhost:8000");
        DynamoDB dynamoDB = new DynamoDB(client);

        Table table = dynamoDB.getTable("Movies");
        
        int year = 2015;
        String title = "The Big New Movie";

        // Conditional update (will fail)

        UpdateItemSpec updateItemSpec = new UpdateItemSpec()
            .withPrimaryKey(new PrimaryKey("year", 2015, "title",  "The Big New Movie"))
            .withUpdateExpression("remove info.actors[0]")
            .withConditionExpression("size(info.actors) > :num")
            .withValueMap(new ValueMap().withNumber(":num", 3));

        System.out.println("Attempting a conditional update...");
        try {
            table.updateItem(updateItemSpec);
            System.out.println("UpdateItem succeeded: " + table.getItem("year", year, "title", title).toJSONPretty());
        } catch (ConditionalCheckFailedException e) {
            e.printStackTrace();
            System.out.println("UpdateItem failed");
        }

    }
 
@Test
public void deleteVersionedItemWithOutOfDateVersion() {
    ExampleVersionedHashKeyItem item1 = newVersionedItem();

    // establish the item with version 1
    Transaction t1 = manager.newTransaction();
    t1.save(item1);
    t1.commit();

    // update the item to version 2
    Transaction t2 = manager.newTransaction();
    ExampleVersionedHashKeyItem item2 = t2.load(item1);
    t2.save(item2);
    t2.commit();

    // try to delete with an outdated view of the item
    Transaction t3 = manager.newTransaction();
    try {
        t3.delete(item1);
        fail();
    } catch (ConditionalCheckFailedException e) {
        t3.rollback();
    }
    assertItemNotLocked(INTEG_HASH_TABLE_NAME, item2.getKey(), item2.getExpectedValues(), true);

    t1.delete(Long.MAX_VALUE);
    t2.delete(Long.MAX_VALUE);
    t3.delete(Long.MAX_VALUE);
}
 
@Test
public void reusingMapperInstanceWithOutOfDateVersionThrowsOnSave() {
    ExampleVersionedHashKeyItem item1 = newVersionedItem();

    // establish the item with version 1
    Transaction t1 = manager.newTransaction();
    t1.save(item1);
    t1.commit();

    // update the item to version 2 and save
    Transaction t2 = manager.newTransaction();
    ExampleVersionedHashKeyItem item2 = t2.load(item1);
    t2.save(item2);
    t2.commit();

    Transaction t3 = manager.newTransaction();
    t3.load(item1);
    try {
        t3.save(item1);
        fail();
    } catch (ConditionalCheckFailedException e) {
        t3.rollback();
    }
    assertItemNotLocked(INTEG_HASH_TABLE_NAME, item2.getKey(), item2.getExpectedValues(), true);

    t1.delete(Long.MAX_VALUE);
    t2.delete(Long.MAX_VALUE);
    t3.delete(Long.MAX_VALUE);
}
 
源代码22 项目: dynamodb-transactions   文件: Transaction.java
/**
 * Rolls back the transaction.  You can only roll back a transaction that is in the PENDING state (not yet committed).
 * <li>If you roll back a transaction in COMMITTED, this will continue committing the transaction if it isn't completed yet, 
 *      but you will get back a TransactionCommittedException. </li>
 * <li>If you roll back and already rolled back transaction, this will ensure the rollback completed, and return success</li>
 * <li>If the transaction no longer exists, you'll get back an UnknownCompletedTransactionException</li>   
 * 
 * @throws TransactionCommittedException - the transaction was committed by a concurrent overlapping transaction
 * @throws UnknownCompletedTransactionException - the transaction completed, but it is not known whether it was rolled back or committed
 */
public synchronized void rollback() throws TransactionCompletedException, UnknownCompletedTransactionException {
    State state = null;
    boolean alreadyRereadTxItem = false;
    try {
        txItem.finish(State.ROLLED_BACK, txItem.getVersion());  
        state = State.ROLLED_BACK;
    } catch (ConditionalCheckFailedException e) {         
        try {
            // Re-read state to see its actual state, since it wasn't in PENDING
            txItem = new TransactionItem(txId, txManager, false);
            alreadyRereadTxItem = true;
            state = txItem.getState();
        } catch (TransactionNotFoundException tnfe) {
            throw new UnknownCompletedTransactionException(txId, "In transaction " + State.ROLLED_BACK + " attempt, transaction either rolled back or committed");
        }
    }
    
    if(State.COMMITTED.equals(state)) {
        if(! txItem.isCompleted()) {
            doCommit();
        }
        throw new TransactionCommittedException(txId, "Transaction was committed");
    } else if(State.ROLLED_BACK.equals(state)) {
        if(! txItem.isCompleted()) {
            doRollback();
        }
        return;
    } else if (State.PENDING.equals(state)) {
        if (! alreadyRereadTxItem) {
            // The item was modified in the meantime (another request was added to it)
            // so make sure we re-read it, and then try the rollback again
            txItem = new TransactionItem(txId, txManager, false);
        }
        rollback();
        return;
    }
    throw new TransactionAssertionException(txId, "Unexpected state in rollback(): " + state);
}
 
源代码23 项目: dynamodb-transactions   文件: Transaction.java
/**
 * Releases the lock for the item.  If the item was inserted only to acquire the lock (if the item didn't exist before 
 * for a DeleteItem or LockItem), it will be deleted now.
 * 
 * Otherwise, all of the attributes uses for the transaction (tx id, transient flag, applied flag) will be removed.
 * 
 * Conditions on our transaction id owning the item
 * 
 * To be used once the transaction has committed only.
 * @param request
 */
protected void unlockItemAfterCommit(Request request) {
    try {
        Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>();
        expected.put(AttributeName.TXID.toString(), new ExpectedAttributeValue().withValue(new AttributeValue(txId)));
        
        if(request instanceof PutItem || request instanceof UpdateItem) {
            Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
            updates.put(AttributeName.TXID.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
            updates.put(AttributeName.TRANSIENT.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
            updates.put(AttributeName.APPLIED.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
            updates.put(AttributeName.DATE.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
            
            UpdateItemRequest update = new UpdateItemRequest()
                .withTableName(request.getTableName())
                .withKey(request.getKey(txManager))
                .withAttributeUpdates(updates)
                .withExpected(expected);
            txManager.getClient().updateItem(update);
        } else if(request instanceof DeleteItem) {
            DeleteItemRequest delete = new DeleteItemRequest()
                .withTableName(request.getTableName())
                .withKey(request.getKey(txManager))
                .withExpected(expected);
            txManager.getClient().deleteItem(delete);
        } else if(request instanceof GetItem) {
            releaseReadLock(request.getTableName(), request.getKey(txManager));
        } else {
            throw new TransactionAssertionException(txId, "Unknown request type: " + request.getClass());
        }
    } catch (ConditionalCheckFailedException e) {
        // ignore, unlock already happened
        // TODO if we really want to be paranoid we could condition on applied = 1, and then here
        //      we would have to read the item again and make sure that applied was 1 if we owned the lock (and assert otherwise) 
    }
}
 
源代码24 项目: dynamodb-transactions   文件: Transaction.java
protected static void releaseReadLock(String txId, TransactionManager txManager, String tableName, Map<String, AttributeValue> key) {
    Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>();
    expected.put(AttributeName.TXID.toString(), new ExpectedAttributeValue().withValue(new AttributeValue(txId)));
    expected.put(AttributeName.TRANSIENT.toString(), new ExpectedAttributeValue().withExists(false));
    expected.put(AttributeName.APPLIED.toString(), new ExpectedAttributeValue().withExists(false));
    
    try {
        Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>(1);
        updates.put(AttributeName.TXID.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
        updates.put(AttributeName.DATE.toString(), new AttributeValueUpdate().withAction(AttributeAction.DELETE));
        
        UpdateItemRequest update = new UpdateItemRequest()
            .withTableName(tableName)
            .withAttributeUpdates(updates)
            .withKey(key)
            .withExpected(expected);
        txManager.getClient().updateItem(update);
    } catch (ConditionalCheckFailedException e) {
        try {
            expected.put(AttributeName.TRANSIENT.toString(), new ExpectedAttributeValue().withValue(new AttributeValue().withS(BOOLEAN_TRUE_ATTR_VAL)));
            
            DeleteItemRequest delete = new DeleteItemRequest()
                .withTableName(tableName)
                .withKey(key)
                .withExpected(expected);
            txManager.getClient().deleteItem(delete);    
        } catch (ConditionalCheckFailedException e1) {
            // Ignore, means it was definitely rolled back
            // Re-read to ensure that it wasn't applied
            Map<String, AttributeValue> item = getItem(txManager, tableName, key);
            txAssert(! (item != null && txId.equals(getOwner(item)) && item.containsKey(AttributeName.APPLIED.toString())), 
                "Item should not have been applied.  Unable to release lock", "item", item);
        }
    }
}
 
源代码25 项目: dynamodb-transactions   文件: TransactionItem.java
/**
 * Saves the old copy of the item.  Does not mutate the item, unless an exception is thrown.
 * 
 * @param item
 * @param rid
 */
public void saveItemImage(Map<String, AttributeValue> item, int rid) {
    txAssert(! item.containsKey(AttributeName.APPLIED.toString()), txId, "The transaction has already applied this item image, it should not be saving over the item image with it");
    
    AttributeValue existingTxId = item.put(AttributeName.TXID.toString(), new AttributeValue(txId));
    if(existingTxId != null && ! txId.equals(existingTxId.getS())) {
        throw new TransactionException(txId, "Items in transactions may not contain the attribute named " + AttributeName.TXID.toString());
    }
    
    // Don't save over the already saved item.  Prevents us from saving the applied image instead of the previous image in the case
    // of a re-drive.
    // If we want to be extremely paranoid, we could expect every attribute to be set exactly already in a second write step, and assert
    Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>(1);
    expected.put(AttributeName.IMAGE_ID.toString(), new ExpectedAttributeValue().withExists(false));
    
    AttributeValue existingImageId = item.put(AttributeName.IMAGE_ID.toString(), new AttributeValue(txId + "#" + rid));
    if(existingImageId != null) {
        throw new TransactionException(txId, "Items in transactions may not contain the attribute named " + AttributeName.IMAGE_ID.toString() + ", value was already " + existingImageId); 
    }
    
    // TODO failures?  Size validation?
    try {
        txManager.getClient().putItem(new PutItemRequest()
            .withTableName(txManager.getItemImageTableName())
            .withExpected(expected)
            .withItem(item));
    } catch (ConditionalCheckFailedException e) {
        // Already was saved
    }
    
    // do not mutate the item for the customer unless if there aren't exceptions
    item.remove(AttributeName.IMAGE_ID.toString());
}
 
源代码26 项目: dynamodb-transactions   文件: TransactionItem.java
/**
 * Marks the transaction item as either COMMITTED or ROLLED_BACK, but only if it was in the PENDING state.
 * It will also condition on the expected version. 
 * 
 * @param targetState
 * @param expectedVersion 
 * @throws ConditionalCheckFailedException if the transaction doesn't exist, isn't PENDING, is finalized, 
 *         or the expected version doesn't match (if specified)  
 */
public void finish(final State targetState, final int expectedVersion) throws ConditionalCheckFailedException {
    txAssert(State.COMMITTED.equals(targetState) || State.ROLLED_BACK.equals(targetState),"Illegal state in finish(): " + targetState, "txItem", txItem);
    Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>(2);
    expected.put(AttributeName.STATE.toString(), new ExpectedAttributeValue().withValue(new AttributeValue().withS(STATE_PENDING)));
    expected.put(AttributeName.FINALIZED.toString(), new ExpectedAttributeValue().withExists(false));
    expected.put(AttributeName.VERSION.toString(), new ExpectedAttributeValue().withValue(new AttributeValue().withN(Integer.toString(expectedVersion))));
    
    Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
    updates.put(AttributeName.STATE.toString(), new AttributeValueUpdate()
        .withAction(AttributeAction.PUT)
        .withValue(new AttributeValue(stateToString(targetState))));
    updates.put(AttributeName.DATE.toString(), new AttributeValueUpdate()
        .withAction(AttributeAction.PUT)
        .withValue(txManager.getCurrentTimeAttribute()));
    
    UpdateItemRequest finishRequest = new UpdateItemRequest()
        .withTableName(txManager.getTransactionTableName())
        .withKey(txKey)
        .withAttributeUpdates(updates)
        .withReturnValues(ReturnValue.ALL_NEW)
        .withExpected(expected);
    
    UpdateItemResult finishResult = txManager.getClient().updateItem(finishRequest);
    txItem = finishResult.getAttributes();
    if(txItem == null) {
        throw new TransactionAssertionException(txId, "Unexpected null tx item after committing " + targetState);
    }
}
 
源代码27 项目: dynamodb-transactions   文件: TransactionItem.java
/**
 * Completes a transaction by marking its "Finalized" attribute.  This leaves the completed transaction item around
 * so that the party who created the transaction can see whether it was completed or rolled back.  They can then either 
 * delete the transaction record when they're done, or they can run a sweeper process to go and delete the completed transactions
 * later on. 
 * 
 * @param expectedCurrentState
 * @throws ConditionalCheckFailedException if the transaction is completed, doesn't exist anymore, or even if it isn't committed or rolled back  
 */
public void complete(final State expectedCurrentState) throws ConditionalCheckFailedException {
    Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>(2);
    
    if(State.COMMITTED.equals(expectedCurrentState)) {
        expected.put(AttributeName.STATE.toString(), new ExpectedAttributeValue(new AttributeValue(STATE_COMMITTED)));
    } else if(State.ROLLED_BACK.equals(expectedCurrentState)) {
        expected.put(AttributeName.STATE.toString(), new ExpectedAttributeValue(new AttributeValue(STATE_ROLLED_BACK)));
    } else {
        throw new TransactionAssertionException(txId, "Illegal state in finish(): " + expectedCurrentState + " txItem " + txItem);
    }
    
    Map<String, AttributeValueUpdate> updates = new HashMap<String, AttributeValueUpdate>();
    updates.put(AttributeName.FINALIZED.toString(), new AttributeValueUpdate()
        .withAction(AttributeAction.PUT)
        .withValue(new AttributeValue(Transaction.BOOLEAN_TRUE_ATTR_VAL)));
    updates.put(AttributeName.DATE.toString(), new AttributeValueUpdate()
        .withAction(AttributeAction.PUT)
        .withValue(txManager.getCurrentTimeAttribute()));
    
    UpdateItemRequest completeRequest = new UpdateItemRequest()
        .withTableName(txManager.getTransactionTableName())
        .withKey(txKey)
        .withAttributeUpdates(updates)
        .withReturnValues(ReturnValue.ALL_NEW)
        .withExpected(expected);
    
    txItem = txManager.getClient().updateItem(completeRequest).getAttributes();
}
 
源代码28 项目: dynamodb-transactions   文件: TransactionItem.java
/**
 * Deletes the tx item, only if it was in the "finalized" state.
 * 
 * @throws ConditionalCheckFailedException if the item does not exist or is not finalized
 */
public void delete() throws ConditionalCheckFailedException {
    Map<String, ExpectedAttributeValue> expected = new HashMap<String, ExpectedAttributeValue>(1);
    expected.put(AttributeName.FINALIZED.toString(), new ExpectedAttributeValue().withValue(new AttributeValue(Transaction.BOOLEAN_TRUE_ATTR_VAL)));
    
    DeleteItemRequest completeRequest = new DeleteItemRequest()
        .withTableName(txManager.getTransactionTableName())
        .withKey(txKey)
        .withExpected(expected);
    txManager.getClient().deleteItem(completeRequest);
}
 
private void checkExpectedValues(String tableName,
        Map<String, AttributeValue> itemKey,
        Map<String, ExpectedAttributeValue> expectedValues) {
    if (expectedValues != null && !expectedValues.isEmpty()) {
        for (Map.Entry<String, ExpectedAttributeValue> entry : expectedValues.entrySet()) {
            if ((entry.getValue().isExists() == null || entry.getValue().isExists() == true)
                    && entry.getValue().getValue() == null) {
                throw new IllegalArgumentException("An explicit value is required when Exists is null or true, "
                        + "but none was found in expected values for item with key " + itemKey +
                        ": " + expectedValues);
            }
        }

        // simulate by loading the item and checking the values;
        // this also has the effect of locking the item, which gives the
        // same behavior
        GetItemResult result = getItem(new GetItemRequest()
                .withAttributesToGet(expectedValues.keySet())
                .withKey(itemKey)
                .withTableName(tableName));
        Map<String, AttributeValue> item = result.getItem();
        try {
            checkExpectedValues(expectedValues, item);
        } catch (ConditionalCheckFailedException e) {
            throw new ConditionalCheckFailedException("Item " + itemKey + " had unexpected attributes: " + e.getMessage());
        }
    }
}
 
/**
 * This test ensures that optimistic locking can be successfully done through the {@link DynamoDBMapper} when
 * combined with the @{link AttributeEncryptor}. Specifically it checks that {@link SaveBehavior#PUT} properly
 * enforces versioning and will result in a {@link ConditionalCheckFailedException} when optimistic locking should
 * prevent a write. Finally, it checks that {@link SaveBehavior#CLOBBER} properly ignores optimistic locking and
 * overwrites the old value.
 */
@Test
public void optimisticLockingTest() {
    DynamoDBMapper mapper = new DynamoDBMapper(client,
            DynamoDBMapperConfig.builder()
                    .withSaveBehavior(SaveBehavior.PUT).build(),
            new AttributeEncryptor(symProv));
    DynamoDBMapper clobberMapper = new DynamoDBMapper(client, CLOBBER_CONFIG, new AttributeEncryptor(symProv));

    /*
     * Lineage of objects
     * expected -> v1 -> v2 -> v3
     *                |
     *                -> v2_2 -> clobbered
     * Splitting the lineage after v1 is what should
     * cause the ConditionalCheckFailedException.
     */
    final int hashKey = 0;
    final int rangeKey = 15;
    final Mixed expected = new Mixed();
    expected.setHashKey(hashKey);
    expected.setRangeKey(rangeKey);
    expected.setIntSet(new HashSet<Integer>());
    expected.getIntSet().add(3);
    expected.getIntSet().add(5);
    expected.getIntSet().add(7);
    expected.setDoubleValue(15);
    expected.setStringValue("Blargh!");
    expected.setDoubleSet(
            new HashSet<Double>(Arrays.asList(15.0D, 7.6D, -3D, -34.2D, 0.0D)));

    mapper.save(expected);
    Mixed v1 = mapper.load(Mixed.class, hashKey, rangeKey);
    assertEquals(expected, v1);
    v1.setStringValue("New value");
    mapper.save(v1);
    Mixed v2 = mapper.load(Mixed.class, hashKey, rangeKey);
    assertEquals(v1, v2);
    Mixed v2_2 = mapper.load(Mixed.class, hashKey, rangeKey);

    v2.getIntSet().add(-37);
    mapper.save(v2);
    Mixed v3 = mapper.load(Mixed.class, hashKey, rangeKey);
    assertEquals(v2, v3);
    assertTrue(v3.getIntSet().contains(-37));

    // This should fail due to optimistic locking
    v2_2.getIntSet().add(38);
    try {
        mapper.save(v2_2);
        fail("Expected ConditionalCheckFailedException");
    } catch (ConditionalCheckFailedException ex) {
        // Expected exception
    }

    // Force the update with clobber
    clobberMapper.save(v2_2);
    Mixed clobbered = mapper.load(Mixed.class, hashKey, rangeKey);
    assertEquals(v2_2, clobbered);
    assertTrue(clobbered.getIntSet().contains(38));
    assertFalse(clobbered.getIntSet().contains(-37));
}
 
 类方法
 同包方法