Skip to content

Commit 076553e

Browse files
committed
Add DynamoDB Toolkit Java library and update gitignore
- Add Maven project configuration (pom.xml) with Java 25 and updated groupId - Add complete library source code copied from tourino project - Add comprehensive .gitignore for Java/macOS projects - Add basic README for the open source project - Library uses annotation processing for compile-time DynamoDB mapping code generation
1 parent 11490cd commit 076553e

23 files changed

+2638
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Claude Code
22
.claude/
3+
CLAUDE.md
34

45
# Compiled class file
56
*.class

README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# DynamoDB Mapping Library
2+
3+
Annotation-driven DynamoDB mapping library with automatic dependency resolution and compile-time code generation for type-safe bidirectional conversion between domain objects and DynamoDB AttributeValue format.
4+
5+
## Features
6+
7+
- **Single annotation approach**: Only `@DynamoMappable` needed to mark types
8+
- **Automatic dependency resolution**: Analyzes object relationships and generates proper CDI injection
9+
- **Compile-time code generation**: No runtime reflection, full Quarkus/GraalVM compatibility
10+
- **Type-safe mapping**: Compile-time validation and generation
11+
- **CDI integration**: Generated mappers are `@ApplicationScoped` beans with dependency injection
12+
13+
## Usage
14+
15+
### 1. Mark your domain classes with `@DynamoMappable`
16+
17+
```java
18+
@DynamoMappable
19+
@Table(name = "routes")
20+
public class Route {
21+
private String userId;
22+
private String routeId;
23+
private String name;
24+
private List<Waypoint> waypoints; // Waypoint must also be @DynamoMappable
25+
private RouteGeometry geometry; // RouteGeometry must also be @DynamoMappable
26+
private Instant createdAt;
27+
}
28+
29+
@DynamoMappable
30+
public class Waypoint {
31+
private double lat;
32+
private double lng;
33+
private String name;
34+
}
35+
36+
@DynamoMappable
37+
public class RouteGeometry {
38+
private GeometryType type;
39+
private List<List<Double>> coordinates;
40+
}
41+
```
42+
43+
### 2. Generated mappers are automatically injected
44+
45+
The annotation processor generates mapper classes with proper CDI dependency injection:
46+
47+
```java
48+
@ApplicationScoped
49+
public class RouteMapper {
50+
private final WaypointMapper waypointMapper;
51+
private final RouteGeometryMapper routeGeometryMapper;
52+
53+
public RouteMapper(WaypointMapper waypointMapper, RouteGeometryMapper routeGeometryMapper) {
54+
this.waypointMapper = waypointMapper;
55+
this.routeGeometryMapper = routeGeometryMapper;
56+
}
57+
58+
public AttributeValue toDynamoDbAttributeValue(Route route) { /* generated */ }
59+
public Route fromDynamoDbAttributeValue(AttributeValue attributeValue) { /* generated */ }
60+
}
61+
```
62+
63+
### 3. Use in your repository classes
64+
65+
```java
66+
@ApplicationScoped
67+
public class DynamoDbRoutesRepository implements RoutesRepository {
68+
69+
private final DynamoDbClient dynamoDb;
70+
private final RouteMapper routeMapper; // Automatically injected
71+
72+
public Route save(Route route) {
73+
Map<String, AttributeValue> item = routeMapper.toDynamoDbAttributeValue(route).m();
74+
// ... save to DynamoDB
75+
}
76+
77+
public Route findById(String id) {
78+
// ... get from DynamoDB
79+
return routeMapper.fromDynamoDbAttributeValue(AttributeValue.builder().m(item).build());
80+
}
81+
}
82+
```
83+
84+
## Supported Field Types
85+
86+
| Type | Strategy | Description |
87+
|------|----------|-------------|
88+
| `String` | STRING | Direct string mapping |
89+
| `Double`, `Integer`, etc. | NUMBER | Number mapping with type conversion |
90+
| `Boolean` | BOOLEAN | Boolean mapping |
91+
| `Instant` | INSTANT | ISO-8601 string representation |
92+
| `Enum` | ENUM | Enum name mapping |
93+
| `List<String>` | STRING_LIST | Native DynamoDB string set |
94+
| `List<@DynamoMappable>` | COMPLEX_LIST | List of mapped complex objects |
95+
| `@DynamoMappable` objects | COMPLEX_OBJECT | Nested object mapping via dependency injection |
96+
97+
## Build Integration
98+
99+
Add the annotation processor to your Maven build:
100+
101+
```xml
102+
<dependency>
103+
<groupId>com.tourino</groupId>
104+
<artifactId>dynamodb-mapping-lib</artifactId>
105+
<version>1.0.0-SNAPSHOT</version>
106+
</dependency>
107+
```
108+
109+
The annotation processor runs automatically during compilation and generates mapper classes in the same package as your domain classes.
110+
111+
## Benefits over Manual Mapping
112+
113+
- **Reduced Code**: 256 lines of manual mapping → ~10 lines of annotations
114+
- **Type Safety**: Compile-time validation vs runtime parsing errors
115+
- **Maintainability**: New entities require only `@DynamoMappable` annotation
116+
- **Consistency**: Generated code follows same patterns
117+
- **Performance**: No reflection at runtime, optimal native compilation
118+
- **Dependency Management**: Automatic resolution of mapper dependencies
119+
120+
## Generated Code Structure
121+
122+
For each `@DynamoMappable` class, the processor generates:
123+
124+
- **Mapper class**: `{ClassName}Mapper` with CDI annotations
125+
- **Bidirectional methods**: `toDynamoDbAttributeValue()` and `fromDynamoDbAttributeValue()`
126+
- **Dependency injection**: Constructor injection for required mappers
127+
- **Null safety**: Proper null handling throughout mapping logic
128+
- **Error handling**: Safe parsing with fallback to null values

pom.xml

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
<?xml version="1.0"?>
2+
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
3+
xmlns="http://maven.apache.org/POM/4.0.0"
4+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
5+
<modelVersion>4.0.0</modelVersion>
6+
7+
<groupId>io.github.wassertim</groupId>
8+
<artifactId>dynamodb-toolkit</artifactId>
9+
<version>1.0.0-SNAPSHOT</version>
10+
11+
<name>DynamoDB Toolkit</name>
12+
<description>Comprehensive DynamoDB toolkit with annotation-driven mapping, automatic dependency resolution, and utilities</description>
13+
14+
<properties>
15+
<maven.compiler.source>21</maven.compiler.source>
16+
<maven.compiler.target>21</maven.compiler.target>
17+
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
18+
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
19+
20+
<!-- Dependency versions -->
21+
<aws.sdk.version>2.29.39</aws.sdk.version>
22+
<jakarta.enterprise.version>4.1.0</jakarta.enterprise.version>
23+
<junit.version>5.11.4</junit.version>
24+
<assertj.version>3.26.3</assertj.version>
25+
</properties>
26+
27+
<dependencies>
28+
<!-- Core dependencies -->
29+
<dependency>
30+
<groupId>software.amazon.awssdk</groupId>
31+
<artifactId>dynamodb</artifactId>
32+
<version>${aws.sdk.version}</version>
33+
</dependency>
34+
35+
<!-- CDI for dependency injection -->
36+
<dependency>
37+
<groupId>jakarta.enterprise</groupId>
38+
<artifactId>jakarta.enterprise.cdi-api</artifactId>
39+
<version>${jakarta.enterprise.version}</version>
40+
</dependency>
41+
42+
<!-- Annotation processing -->
43+
<dependency>
44+
<groupId>com.google.auto.service</groupId>
45+
<artifactId>auto-service</artifactId>
46+
<version>1.1.1</version>
47+
<optional>true</optional>
48+
</dependency>
49+
50+
<!-- Test dependencies -->
51+
<dependency>
52+
<groupId>org.junit.jupiter</groupId>
53+
<artifactId>junit-jupiter</artifactId>
54+
<version>${junit.version}</version>
55+
<scope>test</scope>
56+
</dependency>
57+
58+
<dependency>
59+
<groupId>org.assertj</groupId>
60+
<artifactId>assertj-core</artifactId>
61+
<version>${assertj.version}</version>
62+
<scope>test</scope>
63+
</dependency>
64+
</dependencies>
65+
66+
<build>
67+
<plugins>
68+
<plugin>
69+
<groupId>org.apache.maven.plugins</groupId>
70+
<artifactId>maven-compiler-plugin</artifactId>
71+
<version>3.14.0</version>
72+
<configuration>
73+
<source>${maven.compiler.source}</source>
74+
<target>${maven.compiler.target}</target>
75+
<encoding>${project.build.sourceEncoding}</encoding>
76+
<annotationProcessorPaths>
77+
<path>
78+
<groupId>com.google.auto.service</groupId>
79+
<artifactId>auto-service</artifactId>
80+
<version>1.1.1</version>
81+
</path>
82+
</annotationProcessorPaths>
83+
</configuration>
84+
</plugin>
85+
86+
<plugin>
87+
<groupId>org.apache.maven.plugins</groupId>
88+
<artifactId>maven-surefire-plugin</artifactId>
89+
<version>3.5.3</version>
90+
</plugin>
91+
</plugins>
92+
</build>
93+
</project>

0 commit comments

Comments
 (0)