diff --git a/src/main/java/com/github/wassertim/dynamodb/toolkit/generation/MapperGenerator.java b/src/main/java/com/github/wassertim/dynamodb/toolkit/generation/MapperGenerator.java index 4346c2f..2625d7e 100644 --- a/src/main/java/com/github/wassertim/dynamodb/toolkit/generation/MapperGenerator.java +++ b/src/main/java/com/github/wassertim/dynamodb/toolkit/generation/MapperGenerator.java @@ -55,7 +55,8 @@ private TypeSpec buildMapperClass(TypeInfo typeInfo) { .addAnnotation(ApplicationScoped.class) .addJavadoc(createGeneratedJavadoc( "Generated DynamoDB mapper for " + className + ".\n" + - "Provides bidirectional conversion between " + className + " and DynamoDB AttributeValue." + "Provides bidirectional conversion between " + className + " and DynamoDB AttributeValue.\n" + + "DEBUG_MARKER: Local build verification - " + System.currentTimeMillis() )); // Add dependency injection (fields and constructor) diff --git a/src/main/java/com/github/wassertim/dynamodb/toolkit/processor/AnnotationProcessor.java b/src/main/java/com/github/wassertim/dynamodb/toolkit/processor/AnnotationProcessor.java index fd804f7..a6c5833 100644 --- a/src/main/java/com/github/wassertim/dynamodb/toolkit/processor/AnnotationProcessor.java +++ b/src/main/java/com/github/wassertim/dynamodb/toolkit/processor/AnnotationProcessor.java @@ -61,6 +61,9 @@ public class AnnotationProcessor extends AbstractProcessor { private FieldConstantsGenerator fieldConstantsGenerator; private TableNameResolverGenerator tableNameResolverGenerator; + // Track processed types to avoid reprocessing in subsequent rounds + private final Set processedTypes = new java.util.HashSet<>(); + @Override public synchronized void init(ProcessingEnvironment processingEnv) { super.init(processingEnv); @@ -79,10 +82,28 @@ public synchronized void init(ProcessingEnvironment processingEnv) { @Override public boolean process(Set annotations, RoundEnvironment roundEnv) { + // Skip processing if annotations are empty if (annotations.isEmpty()) { return false; } + // CRITICAL FIX: Only process in the first round, skip all subsequent rounds + // This prevents multi-round processing bugs where type information changes between rounds + if (!roundEnv.processingOver() && roundEnv.getRootElements().isEmpty()) { + // This is a subsequent round with no new source files - skip it + return false; + } + + // Skip the final processing-over round + if (roundEnv.processingOver()) { + return false; + } + + // Only process if we haven't processed anything yet (first round only) + if (!processedTypes.isEmpty()) { + return false; + } + try { // Collect all @DynamoMappable annotated elements Set annotatedElements = roundEnv.getElementsAnnotatedWith(DynamoMappable.class); @@ -90,6 +111,11 @@ public boolean process(Set annotations, RoundEnvironment // Collect all @Table annotated elements Set tableElements = roundEnv.getElementsAnnotatedWith(Table.class); + // Mark all types as processed + for (Element element : annotatedElements) { + processedTypes.add(((TypeElement) element).getQualifiedName().toString()); + } + // If no annotations to process, return false if (annotatedElements.isEmpty() && tableElements.isEmpty()) { return false;