Install
$ agentstack add skill-giuseppe-trisciuoglio-developer-kit-aws-sdk-java-v2-dynamodb ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
AWS SDK for Java 2.x - Amazon DynamoDB
Overview
Provides DynamoDB patterns using AWS SDK for Java 2.x with Enhanced Client for type-safe CRUD, queries, batch operations, transactions, and Spring Boot integration.
When to Use
- CRUD operations on DynamoDB items
- Querying tables with sort keys or GSI
- Batch operations for multiple items
- Atomic transactions across tables
- Spring Boot integration with DynamoDB
Instructions
- Add AWS SDK DynamoDB dependencies to
pom.xml - Configure client setup (low-level or Enhanced Client)
- Define entity classes with
@DynamoDbBeanannotations - Perform operations using
DynamoDbTable(CRUD, query, scan, batch, transactions) - Handle partial failures with retry logic and exponential backoff
- Use repository pattern for Spring Boot integration
Dependencies
Add to pom.xml:
software.amazon.awssdk
dynamodb
software.amazon.awssdk
dynamodb-enhanced
Client Setup
Low-Level Client
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.dynamodb.DynamoDbClient;
DynamoDbClient dynamoDb = DynamoDbClient.builder()
.region(Region.US_EAST_1)
.build();
Enhanced Client (Recommended)
import software.amazon.awssdk.enhanced.dynamodb.DynamoDbEnhancedClient;
DynamoDbEnhancedClient enhancedClient = DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDb)
.build();
Entity Mapping
@DynamoDbBean
public class Customer {
@DynamoDbPartitionKey
private String customerId;
@DynamoDbAttribute("customer_name")
private String name;
private String email;
@DynamoDbSortKey
private String orderId;
// Getters and setters
}
For complex entity mapping with GSIs and custom converters, see [Entity Mapping Reference](references/entity-mapping.md).
CRUD Operations
Basic Operations
// Create or update item
DynamoDbTable table = enhancedClient.table("Customers", TableSchema.fromBean(Customer.class));
table.putItem(customer);
// Get item
Customer result = table.getItem(Key.builder().partitionValue(customerId).build());
// Update item
return table.updateItem(customer);
// Delete item
table.deleteItem(Key.builder().partitionValue(customerId).build());
Composite Key Operations
// Get item with composite key
Order order = table.getItem(Key.builder()
.partitionValue(customerId)
.sortValue(orderId)
.build());
Query Operations
Basic Query
import software.amazon.awssdk.enhanced.dynamodb.model.QueryConditional;
QueryConditional queryConditional = QueryConditional
.keyEqualTo(Key.builder()
.partitionValue(customerId)
.build());
List orders = table.query(queryConditional).items().stream()
.collect(Collectors.toList());
Advanced Query with Filters
import software.amazon.awssdk.enhanced.dynamodb.Expression;
Expression filter = Expression.builder()
.expression("status = :pending")
.putExpressionValue(":pending", AttributeValue.builder().s("PENDING").build())
.build();
List pendingOrders = table.query(r -> r
.queryConditional(queryConditional)
.filterExpression(filter))
.items().stream()
.collect(Collectors.toList());
For detailed query patterns, see [Advanced Operations Reference](references/advanced-operations.md).
Scan Operations
> Warning: Scan reads entire table and consumes read capacity for all items. Prefer Query operations with partition keys or GSIs whenever possible.
Validation before scan:
- Confirm query with partition key is not feasible for your access pattern
- Verify table has sufficient provisioned read capacity or use on-demand mode
- Consider using pagination with
limit()to control capacity consumption
// Scan all items
List allCustomers = table.scan().items().stream()
.collect(Collectors.toList());
// Scan with filter
Expression filter = Expression.builder()
.expression("points >= :minPoints")
.putExpressionValue(":minPoints", AttributeValue.builder().n("1000").build())
.build();
List vipCustomers = table.scan(r -> r.filterExpression(filter))
.items().stream()
.collect(Collectors.toList());
Batch Operations
Batch Get
import software.amazon.awssdk.enhanced.dynamodb.model.*;
List keys = customerIds.stream()
.map(id -> Key.builder().partitionValue(id).build())
.collect(Collectors.toList());
ReadBatch.Builder batchBuilder = ReadBatch.builder(Customer.class)
.mappedTableResource(table);
keys.forEach(batchBuilder::addGetItem);
BatchGetResultPageIterable result = enhancedClient.batchGetItem(r ->
r.addReadBatch(batchBuilder.build()));
List customers = result.resultsForTable(table).stream()
.collect(Collectors.toList());
Batch Write with Error Handling
WriteBatch.Builder batchBuilder = WriteBatch.builder(Customer.class)
.mappedTableResource(table);
customers.forEach(batchBuilder::addPutItem);
BatchWriteItemEnhancedRequest request = BatchWriteItemEnhancedRequest.builder()
.addWriteBatch(batchBuilder.build())
.build();
BatchWriteResult result = enhancedClient.batchWriteItem(request);
// Validate: check for unprocessed items
if (!result.writeResponsesForTable(table).isEmpty()) {
// Retry unprocessed items with exponential backoff
Map unprocessed = result.writeResponsesForTable(table).get(0)
.unprocessedAttributes();
if (unprocessed != null && !unprocessed.isEmpty()) {
enhancedClient.batchWriteItem(r -> r
.addWriteBatch(WriteBatch.builder(Customer.class)
.mappedTableResource(table)
.addPutItemFromItem(unprocessed)
.build()));
}
}
Transactions
Transactional Write with Retry
public void placeOrderWithRetry(Order order, Customer customer, int maxRetries) {
int attempt = 0;
while (attempt r
.addPutItem(customerTable, customer)
.addPutItem(orderTable, order));
return;
} catch (TransactionCanceledException e) {
if (e.cancellationReasons().stream()
.anyMatch(r -> r.code().equals("TransactionCanceledException")
&& r.message().contains("throughput"))) {
attempt++;
if (attempt results = enhancedClient.transactGetItems(request);
Spring Boot Integration
Configuration
@Configuration
public class DynamoDbConfiguration {
@Bean
public DynamoDbClient dynamoDbClient() {
return DynamoDbClient.builder()
.region(Region.US_EAST_1)
.build();
}
@Bean
public DynamoDbEnhancedClient dynamoDbEnhancedClient(DynamoDbClient dynamoDbClient) {
return DynamoDbEnhancedClient.builder()
.dynamoDbClient(dynamoDbClient)
.build();
}
}
Repository Pattern
@Repository
public class CustomerRepository {
private final DynamoDbTable customerTable;
public CustomerRepository(DynamoDbEnhancedClient enhancedClient) {
this.customerTable = enhancedClient.table("Customers", TableSchema.fromBean(Customer.class));
}
public void save(Customer customer) {
customerTable.putItem(customer);
}
public Optional findById(String customerId) {
Key key = Key.builder().partitionValue(customerId).build();
return Optional.ofNullable(customerTable.getItem(key));
}
}
For comprehensive Spring Boot integration patterns, see [Spring Boot Integration Reference](references/spring-boot-integration.md).
Testing
Unit Testing with Mocks
@ExtendWith(MockitoExtension.class)
class CustomerServiceTest {
@Mock
private DynamoDbClient dynamoDbClient;
@Mock
private DynamoDbEnhancedClient enhancedClient;
@Mock
private DynamoDbTable customerTable;
@InjectMocks
private CustomerService customerService;
@Test
void saveCustomer_ShouldReturnSavedCustomer() {
// Arrange
when(enhancedClient.table(anyString(), any(TableSchema.class)))
.thenReturn(customerTable);
Customer customer = new Customer("123", "John Doe", "john@example.com");
// Act
Customer result = customerService.saveCustomer(customer);
// Assert
assertNotNull(result);
verify(customerTable).putItem(customer);
}
}
Integration Testing with LocalStack
@Testcontainers
@SpringBootTest
class DynamoDbIntegrationTest {
@Container
static LocalStackContainer localstack = new LocalStackContainer(
DockerImageName.parse("localstack/localstack:3.0"))
.withServices(LocalStackContainer.Service.DYNAMODB);
@DynamicPropertySource
static void configureProperties(DynamicPropertyRegistry registry) {
registry.add("aws.endpoint",
() -> localstack.getEndpointOverride(LocalStackContainer.Service.DYNAMODB).toString());
}
@Autowired
private DynamoDbEnhancedClient enhancedClient;
@Test
void testCustomerCRUDOperations() {
// Test implementation
}
}
For detailed testing strategies, see [Testing Strategies](references/testing-strategies.md).
Best Practices
- Use Enhanced Client: Type-safe operations with less boilerplate
- Design partition keys for even distribution: Avoid hot partitions
- Prefer queries over scans: Use GSIs for access patterns
- Batch in chunks of 25/100: BatchGetItem limits to 100, BatchWriteItem to 25 per table
- Handle partial failures: Implement retry with exponential backoff for
ProvisionedThroughputExceeded - Use conditional writes: Prevent race conditions with
attribute_not_exists(pk)
Examples
Complete CRUD Repository
@Repository
public class UserRepository {
private final DynamoDbTable userTable;
public UserRepository(DynamoDbEnhancedClient enhancedClient) {
this.userTable = enhancedClient.table("Users", TableSchema.fromBean(User.class));
}
public User save(User user) {
userTable.putItem(user);
return user;
}
public Optional findById(String userId) {
Key key = Key.builder().partitionValue(userId).build();
return Optional.ofNullable(userTable.getItem(key));
}
public void deleteById(String userId) {
userTable.deleteItem(Key.builder().partitionValue(userId).build());
}
}
Conditional Write with Retry
public boolean createIfNotExists(User user) {
PutItemEnhancedRequest request = PutItemEnhancedRequest.builder(User.class)
.item(user)
.conditionExpression("attribute_not_exists(userId)")
.build();
try {
userTable.putItemWithRequest(request);
return true;
} catch (ConditionalCheckFailedException e) {
return false; // Item already exists
}
}
Constraints and Warnings
- Item Size Limit: DynamoDB items limited to 400KB
- Partition Key Design: Poor design causes hot partitions
- Batch Limits: BatchGetItem max 100, BatchWriteItem max 25 items per table
- Transaction Costs: Transactions cost 2x read/write capacity units
- Scan Operations: Scans consume large amounts of read capacity; use only when necessary
References
For detailed implementations, see the references folder:
- [Entity Mapping Reference](references/entity-mapping.md)
- [Advanced Operations Reference](references/advanced-operations.md)
- [Spring Boot Integration Reference](references/spring-boot-integration.md)
- [Testing Strategies](references/testing-strategies.md)
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: giuseppe-trisciuoglio
- Source: giuseppe-trisciuoglio/developer-kit
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.