Skip to content

Commit f4a194d

Browse files
committed
Add kiro steering docs
1 parent dd3571f commit f4a194d

File tree

5 files changed

+685
-0
lines changed

5 files changed

+685
-0
lines changed
Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
---
2+
title: Asynchronous Programming Guidelines for AWS SDK v2
3+
inclusion: fileMatch
4+
fileMatchPattern: "**/*.java"
5+
---
6+
7+
# Asynchronous Programming Guidelines for AWS SDK v2
8+
9+
## Use of CompletableFuture
10+
11+
### Best Practices for CompletableFuture
12+
13+
- **Read the documentation**: Always read the [CompletionStage Javadocs](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html) to understand the nuances of CompletableFuture
14+
- **Prefer Non-Blocking Methods for Getting Results**:
15+
16+
```java
17+
// Avoid when possible - blocks the current thread
18+
String result = future.get();
19+
20+
// Better - use callbacks
21+
future.thenAccept(result -> processResult(result));
22+
```
23+
- **Add stacktrace to exceptions**: When using `CompletableFuture#join`, use `CompletableFutureUtils#joinLikeSync` to preserve stacktraces
24+
- **Don't ignore results**: Never ignore the result of a new `CompletionStage` if the parent stage can fail (unless you're absolutely sure it's safe to)
25+
- **Don't make thread assumptions**: Never make assumptions about which thread completes the future
26+
- CompletableFuture callbacks may execute on:
27+
- The thread that completed the future
28+
- A thread from the common ForkJoinPool (for async methods without explicit executor)
29+
- A thread from a provided executor
30+
- Thread behavior can vary based on:
31+
- Whether the future is already completed when a callback is added
32+
- Whether an async or non-async method is used (e.g., `thenApply` vs `thenApplyAsync`)
33+
- The specific JVM implementation and platform
34+
- Always ensure thread safety when:
35+
- Accessing shared state in callbacks
36+
- Modifying UI components (use the appropriate UI thread)
37+
- Working with thread-affinity resources like ThreadLocals
38+
- Example of incorrect assumption:
39+
```java
40+
// INCORRECT: Assuming the callback runs on a specific thread
41+
ThreadLocal<Context> contextHolder = new ThreadLocal<>();
42+
43+
public void processAsync(CompletableFuture<Response> responseFuture) {
44+
Context context = new Context();
45+
contextHolder.set(context); // Set in current thread
46+
47+
responseFuture.thenApply(response -> {
48+
// WRONG: Assuming contextHolder still has the context
49+
Context ctx = contextHolder.get(); // May be null if running on different thread!
50+
return processWithContext(response, ctx);
51+
});
52+
}
53+
```
54+
- Correct approach:
55+
```java
56+
// CORRECT: Explicitly passing context to callback
57+
public void processAsync(CompletableFuture<Response> responseFuture) {
58+
Context context = new Context();
59+
60+
responseFuture.thenApply(response -> {
61+
// Explicitly use the context passed from the outer scope
62+
return processWithContext(response, context);
63+
});
64+
}
65+
```
66+
- **Always provide custom executors**: Don't use `CompletableFuture#xxAsync` methods (like `runAsync` or `thenComposeAsync`) without providing a custom executor, as the default `ForkJoinPool.commonPool()` behavior can vary by platform
67+
- **Handle cancellation properly**: CompletableFuture does not support automatic cancellation propagation, so use `CompletableFutureUtils#forwardExceptionTo` to manually propagate cancellation
68+
- **Avoid chaining multiple API calls**: This can lead to cancellation issues without proper handling
69+
- **Avoid blocking operations**: Never use `get()` or `join()` inside a CompletableFuture chain as it defeats the purpose of asynchronous execution
70+
- **Handle exceptions properly**: Always include exception handling with `exceptionally()` or `handle()` methods
71+
```java
72+
CompletableFuture.supplyAsync(() -> fetchData())
73+
.exceptionally(ex -> {
74+
logger.error("Error processing data", ex);
75+
return fallbackData();
76+
}, executor);
77+
```
78+
- **Use appropriate completion methods**:
79+
- thenApply() - when transforming a result
80+
- thenAccept() - when consuming a result without returning anything
81+
- thenRun() - when executing code regardless of the result
82+
- thenCompose() - when the next step returns a CompletableFuture
83+
- **Test asynchronous code properly**:
84+
- Use `CompletableFuture.join()` in tests to wait for completion
85+
- Set appropriate timeouts for tests
86+
87+
## Reactive Streams Implementation
88+
89+
The AWS SDK for Java v2 uses Reactive Streams for asynchronous, non-blocking data processing with backpressure support. All implementations must adhere to the following requirements:
90+
91+
### Compliance Requirements
92+
93+
- All implementations **MUST** fully comply with the [Reactive Streams Specification](https://github.com/reactive-streams/reactive-streams-jvm)
94+
- All implementations **MUST** pass the [Reactive Streams Technology Compatibility Kit (TCK)](https://github.com/reactive-streams/reactive-streams-jvm/tree/master/tck) tests
95+
- Any code changes to Reactive Streams implementations **MUST** include TCK verification tests
96+
97+
### Implementation Guidelines
98+
99+
- Publishers **MUST** respect backpressure signals from subscribers
100+
- Publishers **MUST** properly propagate cancellation signals
101+
- Publishers **MUST** properly handle and propagate errors
102+
- Subscribers **MUST** handle onNext, onError, and onComplete signals appropriately
103+
- Subscribers **MUST** send appropriate request(n) signals to maintain backpressure
104+
- Processors **MUST** maintain all Publisher and Subscriber contracts
105+
- Developers **SHOULD NOT** implement new Publisher or Subscriber interfaces from scratch
106+
- Developers **SHOULD** utilize existing utility classes such as:
107+
- `SimplePublisher` - A simple implementation of the Publisher interface
108+
- `ByteBufferStoringSubscriber` - A subscriber that stores received ByteBuffers
109+
- Methods in `SdkPublisher` - Utility methods for common Publisher operations
110+
111+
### Common Patterns
112+
113+
- Use `SdkPublisher` for SDK-specific publisher implementations
114+
- Implement proper resource cleanup in both success and failure scenarios
115+
- Handle cancellation gracefully, including cleanup of any allocated resources
116+
- Ensure thread safety in all implementations
117+
- Document thread safety characteristics and any assumptions about execution context
118+
119+
### Testing Requirements
120+
121+
- All Reactive Streams implementations **MUST** include TCK verification tests
122+
- Tests **SHOULD** cover both normal operation and edge cases:
123+
- Cancellation during active streaming
124+
- Error propagation
125+
- Backpressure handling under various request scenarios
126+
- Resource cleanup in all termination scenarios
127+
128+
## References
129+
130+
- [CompletableFuture JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletableFuture.html)
131+
- [CompletionStage JavaDoc](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/CompletionStage.html)
132+
- [Reactive Streams Specification](https://github.com/reactive-streams/reactive-streams-jvm)
133+
- [AWS SDK for Java Developer Guide - Async Programming](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/asynchronous.html)
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
---
2+
title: AWS SDK for Java v2 General Guidelines
3+
inclusion: always
4+
---
5+
6+
# AWS SDK for Java v2 General Guidelines
7+
8+
## General Principles
9+
10+
- Write clean, readable, and maintainable code
11+
- Follow the SOLID principles of object-oriented design
12+
- Favor composition over inheritance
13+
- Program to interfaces, not implementations
14+
- Fail fast - detect and report errors as soon as possible
15+
- Maintain backward compatibility when modifying existing APIs
16+
17+
## Code Style Standards
18+
19+
- Follow Java coding conventions and the existing style in the codebase
20+
- Use meaningful variable, method, and class names that clearly indicate purpose
21+
- Include comprehensive Javadoc for public APIs
22+
- Keep methods short and focused on a single responsibility
23+
- Limit the number of method parameters (ideally 3 or fewer)
24+
- Use appropriate access modifiers (private, protected, public)
25+
- Follow consistent indentation and formatting
26+
27+
## Common Design Patterns
28+
29+
- Use builder pattern for object creation
30+
- Follow reactive programming principles for async operations
31+
- Use SdkException hierarchy for error handling
32+
- Prefer immutable objects where appropriate
33+
34+
## Naming Conventions
35+
36+
### Class Naming
37+
38+
#### General Rules
39+
- Prefer singular class names: `SdkSystemSetting`, not `SdkSystemSettings`
40+
- Treat acronyms as a single word: `DynamoDbClient`, not `DynamoDBClient`
41+
42+
#### Classes that instantiate other classes
43+
44+
- If the class's primary purpose is to return instances of another class:
45+
- If the "get" method has no parameters:
46+
- If the class implements `Supplier`: `{Noun}Supplier` (e.g. `CachedSupplier`)
47+
- If the class does not implement `Supplier`: `{Noun}Provider` (e.g. `AwsCredentialsProvider`)
48+
- If the "get" method has parameters: `{Noun}Factory` (e.g. `AwsJsonProtocolFactory`)
49+
50+
#### Service-specific classes
51+
52+
- If the class makes service calls:
53+
- If the class can be used to invoke *every* data-plane operation:
54+
- If the class is code generated:
55+
- If the class uses sync HTTP: `{ServiceName}Client` (e.g. `DynamoDbClient`)
56+
- If the class uses async HTTP: `{ServiceName}AsyncClient` (e.g. `DynamoDbAsyncClient`)
57+
- If the class is hand-written:
58+
- If the class uses sync HTTP: `{ServiceName}EnhancedClient` (e.g. `DynamoDbEnhancedClient`)
59+
- If the class uses async HTTP: `{ServiceName}EnhancedAsyncClient` (e.g. `DynamoDbEnhancedAsyncClient`)
60+
- If the class can be used to invoke only *some* data-plane operations:
61+
- If the class uses sync HTTP: `{ServiceName}{Noun}Manager` (e.g. `SqsBatchManager`)
62+
- If the class uses async HTTP: `{ServiceName}Async{Noun}Manager` (e.g. `SqsAsyncBatchManager`)
63+
- Note: If only one implementation exists and it uses async HTTP, `Async` may be excluded. (e.g. `S3TransferManager`)
64+
- If the class does not make service calls:
65+
- If the class creates presigned URLs: `{ServiceName}Presigner` (e.g. `S3Presigner`)
66+
- If the class is a collection of various unrelated "helper" methods: `{ServiceName}Utilities` (e.g. `S3Utilities`)
67+
68+
## Class Initialization
69+
70+
- Favor static factory methods over constructors:
71+
- Static factory methods provide meaningful names compared with constructors
72+
- They are useful when working with immutable classes as we can reuse the same object
73+
- Static factory methods can return any subtype of that class
74+
75+
### Naming Conventions for Static Factory Methods
76+
- `create()`, `create(params)` when creating a new instance (e.g., `DynamoDBClient.create()`)
77+
- `defaultXXX()` when returning an instance with default settings (e.g., `BackoffStrategy.defaultStrategy()`)
78+
79+
## Use of Optional
80+
81+
- `Optional` **MUST NOT** be used when the result will never be null
82+
- For return types:
83+
- `Optional` **SHOULD** be used when it is not obvious to a caller whether a result will be null
84+
- `Optional` **MUST NOT** be used for "getters" in generated service model classes
85+
- For member variables: `Optional` **SHOULD NOT** be used
86+
- For method parameters: `Optional` **MUST NOT** be used
87+
88+
## Object Methods (toString, equals, hashCode)
89+
90+
- All public POJO classes **MUST** implement `toString()`, `equals()`, and `hashCode()` methods
91+
- When adding new fields to existing POJO classes, these methods **MUST** be updated to include the new fields
92+
- Implementation guidelines:
93+
- `toString()`: Include class name and all fields with their values
94+
- **MUST** use the SDK's `ToString` utility class (`utils/src/main/java/software/amazon/awssdk/utils/ToString.java`) for consistent formatting:
95+
```java
96+
@Override
97+
public String toString() {
98+
return ToString.builder("YourClassName")
99+
.add("fieldName1", fieldValue1)
100+
.add("fieldName2", fieldValue2)
101+
.build();
102+
}
103+
```
104+
- `equals()`: Compare all fields for equality, including proper null handling
105+
- `hashCode()`: Include all fields in the hash code calculation
106+
- Consider using IDE-generated implementations
107+
- For immutable objects, consider caching the hash code value for better performance
108+
- Unit tests **MUST** be added using EqualsVerifier to ensure all fields are properly included in equals and hashCode implementations. Example:
109+
```java
110+
@Test
111+
public void equalsHashCodeTest() {
112+
EqualsVerifier.forClass(YourClass.class)
113+
.withNonnullFields("requiredFields")
114+
.verify();
115+
}
116+
```
117+
118+
## Exception Handling
119+
120+
- Avoid throwing checked exceptions in public APIs
121+
- Don't catch exceptions unless you can handle them properly
122+
- Always include meaningful error messages
123+
- Clean up resources in finally blocks or use try-with-resources
124+
- Don't use exceptions for flow control
125+
126+
## Use of Existing Utility Classes
127+
128+
- Developers **MUST** check for existing utility methods before implementing their own
129+
- Common utility classes are available in the `utils` module and **SHOULD** be used when applicable
130+
- Examples of available utility classes:
131+
- `Lazy` (`utils/src/main/java/software/amazon/awssdk/utils/Lazy.java`): For thread-safe lazy initialization of singleton objects
132+
- `ToString` (`utils/src/main/java/software/amazon/awssdk/utils/ToString.java`): For consistent toString() implementations
133+
- `IoUtils`: For safely closing resources and handling I/O operations
134+
- `StringUtils`: For common string operations
135+
- `CollectionUtils`: For common collection operations
136+
- `ValidationUtils`: For input validation
137+
- Using existing utilities ensures:
138+
- Consistent behavior across the codebase
139+
- Thread-safety where applicable
140+
- Proper handling of edge cases
141+
- Reduced code duplication
142+
- Example of using `Lazy` for thread-safe singleton initialization:
143+
```java
144+
private static final Lazy<ExpensiveObject> INSTANCE = new Lazy<>(() -> new ExpensiveObject());
145+
146+
public static ExpensiveObject getInstance() {
147+
return INSTANCE.getValue();
148+
}
149+
```
150+
151+
## Performance
152+
153+
- Avoid premature optimization
154+
- Use appropriate data structures for the task
155+
- Be mindful of memory usage, especially with large collections
156+
- Consider thread safety in concurrent applications
157+
- Use profiling tools to identify actual bottlenecks
158+
159+
## References
160+
161+
- [AWS SDK for Java Developer Guide](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html)
162+
- [Design Documentation](https://github.com/aws/aws-sdk-java-v2/tree/master/docs/design)
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
---
2+
title: AWS SDK for Java v2 Development Guidelines
3+
inclusion: always
4+
---
5+
6+
# AWS SDK for Java v2 Development Guidelines
7+
8+
This document serves as an index to the AWS SDK for Java v2 development guidelines. The guidelines have been organized into separate, focused documents to make them more manageable and easier to reference.
9+
10+
## Available Guidelines
11+
12+
### [General Guidelines](aws-sdk-java-v2-general.md)
13+
- General Principles
14+
- Code Style Standards
15+
- Common Design Patterns
16+
- Naming Conventions
17+
- Class Initialization
18+
- Use of Optional
19+
- Exception Handling
20+
- Performance
21+
- Documentation
22+
23+
### [Asynchronous Programming Guidelines](async-programming-guidelines.md)
24+
- Use of CompletableFuture
25+
- Reactive Streams Implementation
26+
27+
### [Testing Guidelines](testing-guidelines.md)
28+
- General Testing Principles
29+
- Test Naming Conventions
30+
- Unit Testing Best Practices
31+
- Testing Asynchronous Code
32+
33+
### [Javadoc Guidelines](javadoc-guidelines.md)
34+
- API Classification
35+
- Documentation Requirements
36+
- Style Guidelines
37+
- Code Snippets
38+
- Examples
39+
40+
## References
41+
42+
- [AWS SDK for Java Developer Guide](https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/home.html)
43+
- [Design Documentation](https://github.com/aws/aws-sdk-java-v2/tree/master/docs/design)
44+
- [Migration Guide](https://docs.aws.amazon.com/sdk-for-java/v2/migration-guide/what-is-java-migration.html)

0 commit comments

Comments
 (0)