Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
08dcd48
Improving logging by solving it centrally
AndreasIgel Mar 7, 2026
0cfebbf
Adding expectation of resulting logging and getting a state of very s…
AndreasIgel Mar 7, 2026
c0ac5d5
Improving logging on constructor fields
AndreasIgel Mar 7, 2026
56f3c08
Improving logger api
AndreasIgel Mar 7, 2026
63d8173
Changing tree spacing from 1 space to 2
AndreasIgel Mar 7, 2026
0a9145b
Having just a summarized info-message instead a message for each builder
AndreasIgel Mar 7, 2026
50a372b
Updating documentation
AndreasIgel Mar 7, 2026
b48cc4b
Improving code after reviewing change in pull-request
AndreasIgel Mar 7, 2026
b37dffb
Fixing test
AndreasIgel Mar 7, 2026
7371353
Disabled instable test: "shouldHandleOverloadedSettersForSameFieldWit…
AndreasIgel Mar 8, 2026
e959ce3
adding indention on logging of warnings and info messages when debug …
AndreasIgel Mar 8, 2026
5525c83
Adapting documentation
AndreasIgel Mar 10, 2026
f871b28
Adding example DTO with builder for conflict case
AndreasIgel Mar 10, 2026
5d8f448
Fixing wrong documentation content on logging
AndreasIgel Mar 10, 2026
956e58b
customGeneratorExample: Changing version of compiler plugin to match …
AndreasIgel Mar 11, 2026
c240699
Adding example projects to dependabot
AndreasIgel Mar 11, 2026
0777ab0
Reactivation of instabile test
AndreasIgel Mar 11, 2026
8218ee7
Code-Cleanup: Removing unused parameter
AndreasIgel Mar 11, 2026
d4873db
Fixing generated file (should be the correct one in code)
AndreasIgel Mar 11, 2026
6a48835
Cleaning up indentionLevel after usage
AndreasIgel Mar 11, 2026
fbde2b9
Disabled test, because the ordering is still not stabile
AndreasIgel Mar 11, 2026
42ee1e1
Fixing test stability by putting ordering on correct place
AndreasIgel Mar 11, 2026
e928700
Replacing string-concatenation with parameters in loggings
AndreasIgel Mar 11, 2026
c5a87e1
Removing System.out.println on tests
AndreasIgel Mar 11, 2026
76b8427
Debug-Logging should only show up on debug-level activated
AndreasIgel Mar 11, 2026
0b524ca
Switching back generated Builder to nameOptional (after having sortin…
AndreasIgel Mar 11, 2026
468c007
Adding missing license headers
AndreasIgel Mar 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ updates:
directories:
- "/core"
- "/processor"
- "/example-custom-generator"
- "/example"
schedule:
interval: "weekly"
labels:
Expand Down
18 changes: 13 additions & 5 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,19 @@ For complete documentation, see [DEBUG_LOGGING.md](DEBUG_LOGGING.md).
```
========== Compilation Diagnostics ==========
--- NOTES ---
[DEBUG] simple-builders: Processing element: Project
[DEBUG] Extracting builder definition from: test.Project
[DEBUG] Analyzing method: setName with 1 parameter(s)
[DEBUG] -> Adding field: name (type: java.lang.String)
[DEBUG] Generated 4 methods for field: name
[DEBUG] simple-builders: Processing round started. Found 1 annotated elements.
[DEBUG] Processing element: Project
[DEBUG] ├─ Extracting builder definition from: test.Project
[DEBUG] │ ├─ Builder will be generated as: test.ProjectBuilder
[DEBUG] │ ├─ Analysing setters for finding fields
[DEBUG] │ │ ├─ Analyzing method: setName with 1 parameter(s)
[DEBUG] │ │ │ └─ Adding field: name (type: java.lang.String)
[DEBUG] │ └─ Processed 1 possible setters: added 1 fields, skipped 0
[DEBUG] ├─ Code generation for builder: ProjectBuilder
[DEBUG] │ ├─ Adding Methods for 4 candidates
[DEBUG] │ │ └─ 4 Methods added
[DEBUG] │ └─ Successfully generated builder: ProjectBuilder
simple-builders: Successfully generated 1 builder(s) in this processing round
=============================================

========== Generated Source Files ==========
Expand Down
80 changes: 55 additions & 25 deletions docs/DEBUG_LOGGING.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ The Simple Builders annotation processor supports conditional debug logging that

## Logging Levels

- **INFO**: Always visible - Shows success messages for each builder generated
- **WARNING**: Always visible - Shows when a builder cannot be generated (e.g., wrong annotation target, generation errors). Other builders will continue to be generated.
- **INFO**: Always visible - Shows success messages for each builder generated. When debug mode is enabled, INFO messages use hierarchical indentation.
- **WARNING**: Always visible - Shows when a builder cannot be generated (e.g., wrong annotation target, generation errors). When debug mode is enabled, WARNING messages use hierarchical indentation.
- **ERROR**: Always visible - Shows fatal configuration errors (e.g., unsupported JDK version). Stops compilation completely.
- **DEBUG**: Conditional - Shows detailed tracing of field discovery, method analysis, and code generation steps
- **DEBUG**: Conditional - Shows detailed tracing of field discovery, method analysis, and code generation steps with hierarchical indentation

## Enabling Debug Logging

Expand Down Expand Up @@ -64,32 +64,63 @@ Set it permanently in your `pom.xml`:
</build>
```

## Conditional Hierarchical Logging

The Simple Builders processor provides **conditional hierarchical logging** to balance readability in production with detailed debugging when needed:

### **When Debug Mode is DISABLED (Default):**
- INFO and WARNING messages appear flat without indentation
- Suitable for production systems where log noise should be minimized
- Example: `simple-builders: Successfully generated 3 builder(s) in this processing round`

### **When Debug Mode is ENABLED (-Averbose=true):**
- INFO and WARNING messages have no extra prefix, DEBUG messages are posted on `[INFO]` chanel so they have the prefix `[INFO] [DEBUG]`
- Provides full visibility into the processing hierarchy
- Example: `[INFO] │ └─ simple-builders: Successfully generated 3 builder(s) in this processing round`
- Example: `[WARNING] │ │ ├─ Builder field conflict: field 'name'...`
- Example: `[INFO] [DEBUG] │ │ │ └─ Processing method: setName`
- All message types align vertically despite different prefix lengths

This approach ensures clean production logs while maintaining full debugging capabilities when needed.

## Example Debug Output

When debug logging is enabled, you'll see detailed output with visual separators:

```
[INFO] [DEBUG] ===============================
[INFO] simple-builders: PROCESSING ROUND START
[INFO] [DEBUG] ===============================
[INFO] [DEBUG] simple-builders: Processing round started. Found 3 annotated elements.
[INFO] [DEBUG] ------------------------------------
[INFO] [DEBUG] simple-builders: Processing element: PersonDto
[INFO] [DEBUG] ------------------------------------
[INFO] [DEBUG] Extracting builder definition from: org.example.PersonDto
[INFO] [DEBUG] Builder will be generated as: org.example.PersonDtoBuilder
[INFO] [DEBUG] Analyzing method: setName with 1 parameter(s)
[INFO] [DEBUG] -> Adding field: name (type: java.lang.String)
[INFO] [DEBUG] Analyzing method: setAge with 1 parameter(s)
[INFO] [DEBUG] -> Adding field: age (type: int)
[INFO] [DEBUG] Processed 2 possible setters: added 2 fields, skipped 0
[INFO] [DEBUG] Starting code generation for builder: PersonDtoBuilder
[INFO] [DEBUG] Generating 0 constructor fields and 2 setter fields
[INFO] [DEBUG] Generated 2 methods for field: name
[INFO] [DEBUG] Generated 2 methods for field: age
[INFO] [DEBUG] Writing builder class to file: org.example.PersonDtoBuilder
[INFO] [DEBUG] Successfully generated builder: PersonDtoBuilder
[INFO] simple-builders: Successfully generated builder for: PersonDto
[INFO] [DEBUG] Processing element: PersonDto
[INFO] [DEBUG] ├─ Extracting builder definition from: org.example.PersonDto
[INFO] [DEBUG] │ ├─ Builder will be generated as: org.example.PersonDtoBuilder
[INFO] [DEBUG] │ ├─ Analysing setters for finding fields
[INFO] [DEBUG] │ │ ├─ Analyzing method: setName with 1 parameter(s)
[INFO] [DEBUG] │ │ │ └─ Adding field: name (type: java.lang.String)
[INFO] [DEBUG] │ │ ├─ Analyzing method: setAge with 1 parameter(s)
[INFO] [DEBUG] │ │ │ └─ Adding field: age (type: int)
[INFO] [DEBUG] │ └─ Processed 2 possible setters: added 2 fields, skipped 0
[INFO] [DEBUG] ├─ Code generation for builder: PersonDtoBuilder
[INFO] [DEBUG] │ ├─ Class builder created
[INFO] [DEBUG] │ ├─ Generating 0 constructor fields and 2 setter fields
[INFO] [DEBUG] │ │ └─ Fields added: 2 fields
[INFO] [DEBUG] │ ├─ Adding Methods for 4 candidates
[INFO] [DEBUG] │ │ └─ 4 Methods added
[INFO] [DEBUG] │ ├─ Writing builder class to file: org.example.PersonDtoBuilder
[INFO] [DEBUG] │ └─ Successfully generated builder: PersonDtoBuilder
[INFO] [DEBUG] Processing element: OrderDto
[INFO] [DEBUG] ├─ Extracting builder definition from: org.example.OrderDto
[INFO] [DEBUG] │ └─ Builder will be generated as: org.example.OrderDtoBuilder
[INFO] [DEBUG] │ └─ Processed 1 possible setters: added 1 fields, skipped 0
[INFO] [DEBUG] ├─ Code generation for builder: OrderDtoBuilder
[INFO] [DEBUG] │ └─ Successfully generated builder: OrderDtoBuilder
[INFO] [DEBUG] Processing element: CustomerDto (with conflicts)
[INFO] [DEBUG] ├─ Extracting builder definition from: org.example.CustomerDto
[INFO] [DEBUG] │ └─ Builder will be generated as: org.example.CustomerDtoBuilder
[INFO] [DEBUG] │ └─ Processed 2 possible setters: added 2 fields, skipped 0
[WARNING] │ │ └─ Builder field conflict: field 'name' (type Optional) renamed to 'nameOptional' to avoid conflict
[INFO] [DEBUG] ├─ Code generation for builder: CustomerDtoBuilder
[INFO] [DEBUG] │ └─ Successfully generated builder: CustomerDtoBuilder
[INFO] simple-builders: Successfully generated 3 builder(s) in this processing round
```

**Note**: Debug messages are prefixed with `[DEBUG]` and use `Diagnostic.Kind.OTHER` which appears as `[INFO]` in Maven output.
Expand All @@ -99,9 +130,8 @@ When debug logging is enabled, you'll see detailed output with visual separators
Without debug logging enabled, you only see the INFO-level messages:

```
[INFO] simple-builders: Successfully generated builder for: PersonDto
[INFO] simple-builders: Successfully generated builder for: OrderDto
[INFO] simple-builders: Successfully generated builder for: CustomerDto
[INFO] simple-builders: PROCESSING ROUND START
[INFO] simple-builders: Successfully generated 3 builder(s) in this processing round
```

## Troubleshooting
Expand Down
3 changes: 2 additions & 1 deletion example-custom-generator/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<code-format.version>2.25</code-format.version>
<commons-lang.version>3.18.0</commons-lang.version>

<plugin.maven.compiler.version>3.13.0</plugin.maven.compiler.version>
<plugin.maven.compiler.version>3.15.0</plugin.maven.compiler.version>
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<maven.compiler.release>${java.version}</maven.compiler.release>
Expand Down Expand Up @@ -48,6 +48,7 @@
<source>${java.version}</source>
<target>${java.version}</target>
<release>${java.version}</release>
<proc>none</proc>
</configuration>
</plugin>
</plugins>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package org.javahelpers.simple.builders.example;

import org.javahelpers.simple.builders.core.annotations.SimpleBuilder;

/**
* Example DTO demonstrating field conflict resolution in Simple Builders.
*
* <p>This class intentionally creates a field conflict scenario by having two setters
* with the same name but different parameter types. This is a common user error that
* Simple Builders handles gracefully by renaming conflicting fields in the generated
* builder.</p>
*
* <h2>Conflict Scenario</h2>
* <ul>
* <li>Both setters are named {@code setName} but accept different types</li>
* <li>One accepts {@code String} for the {@code firstName} field</li>
* <li>One accepts {@code Optional<String>} for the {@code lastName} field</li>
* </ul>
*
* <h2>Expected Behavior</h2>
* <p>When debug logging is enabled ({@code -Dsimplebuilder.verbose=true}), you will see
* warning messages showing how Simple Builders resolves this conflict:</p>
* <ul>
* <li>The second field gets renamed from {@code name} to {@code nameOptional}</li>
* <li>Method conflicts are resolved by priority</li>
* <li>Compilation succeeds with warnings instead of errors</li>
* </ul>
*
* <h2>How to Fix the Conflict</h2>
* <p>The proper solution is to give the setters different names:</p>
* <pre>{@code
* public void setFirstName(String name) {
* this.firstName = name;
* }
*
* public void setLastName(Optional<String> name) {
* this.lastName = name;
* }
* }</pre>
*
* <p>Alternatively, use {@code @IgnoreInBuilder} on one of the setters if the conflict
* is intentional.</p>
*
* @see org.javahelpers.simple.builders.core.annotations.IgnoreInBuilder
*/
@SimpleBuilder
public class FieldConflictExample {
private String firstName;
private java.util.Optional<String> lastName;

public void setName(String name) {
this.firstName = name;
}

public void setName(java.util.Optional<String> name) {
this.lastName = name;
}

public String getFirstName() {
return firstName;
}

public String getLastName() {
return lastName.orElse(null);
}
}
Loading
Loading