Skip to content

Conversation

@oschwald
Copy link
Member

@oschwald oschwald commented Dec 6, 2025

  • Fix enum pointer decoding with @MaxMindDbCreator
  • Update maxmind-db test data submodule
  • Improve error messages for constructor argument mismatches

oschwald and others added 3 commits December 6, 2025 09:11
When an enum with @MaxMindDbCreator was accessed via a pointer in the
database, decoding failed with ConstructorNotFoundException. This
affected enums like ConnectionType in GeoIP2 when data was deduplicated
via pointers.

The bug was in requiresLookupContext() which called
loadConstructorMetadata() before checking for creator methods. Enums
don't have usable public constructors, causing the exception.

Fix:
- Add cls.isEnum() to early-return checks (zero overhead for enums)
- Add @MaxMindDbCreator check for non-enum classes with creators
- Add negative caching to getCachedCreator() to avoid repeated method
  scanning for classes without creators

Fixes: maxmind/GeoIP2-java#644

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
When constructor invocation fails with IllegalArgumentException, the
error diagnostic now:

1. Reports null-to-primitive issues: "null value for primitive double
   parameter 'ip_risk'" - this identifies the actual root cause when a
   database field is missing and the model uses a primitive type.

2. Uses proper type compatibility checks for boxed/primitive pairs.
   Previously, Boolean/boolean pairs were incorrectly reported as type
   mismatches even though auto-unboxing handles them correctly.

This makes debugging much easier by pointing to the actual problem
instead of reporting misleading type mismatches.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@oschwald oschwald requested a review from Copilot December 6, 2025 17:21
Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a bug where enums with @MaxMindDbCreator would throw exceptions when data was stored via pointers in the database, and improves error messages for constructor argument mismatches.

Key Changes:

  • Fixed enum decoding by checking for creator methods before loading constructor metadata in requiresLookupContext()
  • Enhanced error messages to distinguish between null-to-primitive issues and type mismatches
  • Added comprehensive test coverage for enum pointer decoding and error message improvements

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/test/resources/maxmind-db Updated test data submodule to include new test cases
src/test/java/com/maxmind/db/ReaderTest.java Added tests for enum creator with pointer data and null-to-primitive error messages; corrected expected IPv6 address format
src/main/java/com/maxmind/db/Decoder.java Fixed enum pointer decoding logic, improved error messages, and added primitive/boxed type checking
CHANGELOG.md Documented bug fix and error message improvements

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +744 to +768
if (primitive == boolean.class) {
return Boolean.class;
}
if (primitive == byte.class) {
return Byte.class;
}
if (primitive == short.class) {
return Short.class;
}
if (primitive == int.class) {
return Integer.class;
}
if (primitive == long.class) {
return Long.class;
}
if (primitive == float.class) {
return Float.class;
}
if (primitive == double.class) {
return Double.class;
}
if (primitive == char.class) {
return Character.class;
}
return primitive;
Copy link

Copilot AI Dec 6, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The boxedType method uses a chain of if statements to map primitive types to their boxed equivalents. Consider using a switch expression for better readability and maintainability, similar to the pattern used in ConnectionTypeEnum.fromString().

Suggested change
if (primitive == boolean.class) {
return Boolean.class;
}
if (primitive == byte.class) {
return Byte.class;
}
if (primitive == short.class) {
return Short.class;
}
if (primitive == int.class) {
return Integer.class;
}
if (primitive == long.class) {
return Long.class;
}
if (primitive == float.class) {
return Float.class;
}
if (primitive == double.class) {
return Double.class;
}
if (primitive == char.class) {
return Character.class;
}
return primitive;
return switch (primitive.getName()) {
case "boolean" -> Boolean.class;
case "byte" -> Byte.class;
case "short" -> Short.class;
case "int" -> Integer.class;
case "long" -> Long.class;
case "float" -> Float.class;
case "double" -> Double.class;
case "char" -> Character.class;
default -> primitive;
};

Copilot uses AI. Check for mistakes.
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love hardcoding the string values like this. I am going to reject this approach. Another option would be a static map, but the original seems fine, if a bit verbose.

@horgh horgh merged commit 82ddc5b into main Dec 7, 2025
29 of 30 checks passed
@horgh horgh deleted the greg/eng-3610 branch December 7, 2025 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants