diff --git a/CHANGELOG.md b/CHANGELOG.md index c1e24aea..7ddc15ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,9 +1,12 @@ CHANGELOG ========= -4.0.0 +4.0.0 (2025-11-10) ------------------ +**This is a major release with several breaking changes. Please see +[UPGRADING.md](UPGRADING.md) for detailed migration instructions.** + * Java 17 or greater is now required. * Added support for MaxMind DB files larger than 2GB. The library now uses an internal Buffer abstraction that can handle databases exceeding the diff --git a/README.md b/README.md index 6367d115..7197ef5c 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ To do this, add the dependency to your pom.xml: com.maxmind.db maxmind-db - 3.2.0 + 4.0.0 ``` @@ -29,7 +29,7 @@ repositories { mavenCentral() } dependencies { - compile 'com.maxmind.db:maxmind-db:3.2.0' + compile 'com.maxmind.db:maxmind-db:4.0.0' } ``` @@ -83,8 +83,8 @@ public class Lookup { DatabaseRecord record = reader.getRecord(address, LookupResult.class); - System.out.println(record.getData().getCountry().getIsoCode()); - System.out.println(record.getNetwork()); + System.out.println(record.data().getCountry().getIsoCode()); + System.out.println(record.network()); } } @@ -214,7 +214,7 @@ while(networks.hasNext()) { DatabaseRecord> iteration = networks.next(); // Get the data. - Map data = iteration.getData(); + Map data = iteration.data(); // The IP Address InetAddress ipAddress = InetAddress.getByName(data.get("ip")); diff --git a/UPGRADING.md b/UPGRADING.md new file mode 100644 index 00000000..090205b1 --- /dev/null +++ b/UPGRADING.md @@ -0,0 +1,255 @@ +# Upgrading to 4.0.0 + +This guide covers the breaking changes introduced in version 4.0.0 and how to +update your code. + +## Java Version Requirement + +**Java 17 or greater is now required.** If you are using Java 11, you must +upgrade to Java 17 or later before upgrading to 4.0.0. + +## Record Conversion and Method Changes + +The `DatabaseRecord`, `Metadata`, and `Network` classes have been converted to +Java records. This means getter methods have been replaced with record accessor +methods. + +### DatabaseRecord Changes + +**Before (3.x):** + +```java +DatabaseRecord record = reader.getRecord(address, MyData.class); +MyData data = record.getData(); +Network network = record.getNetwork(); +``` + +**After (4.0.0):** + +```java +DatabaseRecord record = reader.getRecord(address, MyData.class); +MyData data = record.data(); +Network network = record.network(); +``` + +**Find and replace:** + +- `record.getData()` → `record.data()` +- `record.getNetwork()` → `record.network()` + +### Network Changes + +**Before (3.x):** + +```java +InetAddress address = network.getNetworkAddress(); +int prefixLength = network.getPrefixLength(); +``` + +**After (4.0.0):** + +```java +InetAddress address = network.networkAddress(); +int prefixLength = network.prefixLength(); +``` + +**Find and replace:** + +- `network.getNetworkAddress()` → `network.networkAddress()` +- `network.getPrefixLength()` → `network.prefixLength()` + +### Metadata Changes + +All getter methods on `Metadata` have been replaced with record accessor +methods. Remove the `get` prefix and use camelCase instead. + +**Before (3.x):** + +```java +Metadata metadata = reader.getMetadata(); +int majorVersion = metadata.getBinaryFormatMajorVersion(); +String dbType = metadata.getDatabaseType(); +List languages = metadata.getLanguages(); +``` + +**After (4.0.0):** + +```java +Metadata metadata = reader.getMetadata(); +int majorVersion = metadata.binaryFormatMajorVersion(); +String dbType = metadata.databaseType(); +List languages = metadata.languages(); +``` + +**Common replacements:** + +- `getBinaryFormatMajorVersion()` → `binaryFormatMajorVersion()` +- `getBinaryFormatMinorVersion()` → `binaryFormatMinorVersion()` +- `getDatabaseType()` → `databaseType()` +- `getLanguages()` → `languages()` +- `getDescription()` → `description()` +- `getIpVersion()` → `ipVersion()` +- `getNodeCount()` → `nodeCount()` +- `getRecordSize()` → `recordSize()` + +### Build Time Change (Date → Instant) + +The `getBuildDate()` method has been replaced with `buildTime()`, which returns +`java.time.Instant` instead of `java.util.Date`. + +**Before (3.x):** + +```java +import java.util.Date; + +Metadata metadata = reader.getMetadata(); +Date buildDate = metadata.getBuildDate(); +``` + +**After (4.0.0):** + +```java +import java.time.Instant; + +Metadata metadata = reader.getMetadata(); +Instant buildTime = metadata.buildTime(); +``` + +If you need a `Date` object, you can convert: + +```java +Date buildDate = Date.from(metadata.buildTime()); +``` + +## DatabaseRecord Constructor Change + +If you are manually constructing `DatabaseRecord` instances, the legacy +constructor has been removed. + +**Before (3.x):** + +```java +DatabaseRecord record = new DatabaseRecord<>(data, ipAddress, prefixLength); +``` + +**After (4.0.0):** + +```java +Network network = new Network(ipAddress, prefixLength); +DatabaseRecord record = new DatabaseRecord<>(data, network); +``` + +## Deserialization Improvements + +### Automatic Constructor Selection + +If your classes use records or have a single public constructor, you may no +longer need to annotate them with `@MaxMindDbConstructor`. + +**Before (3.x) - Required annotations:** + +```java +public record Location( + @MaxMindDbParameter(name = "latitude") Double latitude, + @MaxMindDbParameter(name = "longitude") Double longitude +) {} +``` + +**After (4.0.0) - Annotations optional when names match:** + +```java +public record Location( + Double latitude, + Double longitude +) {} +``` + +The canonical record constructor is used automatically, and component names +match the database field names. + +### Parameter Name Support + +For non-record classes, if you compile with the `-parameters` flag, parameter +names can be used instead of requiring `@MaxMindDbParameter` annotations. + +**Before (3.x):** + +```java +@MaxMindDbConstructor +public Location( + @MaxMindDbParameter(name = "latitude") Double latitude, + @MaxMindDbParameter(name = "longitude") Double longitude +) { + this.latitude = latitude; + this.longitude = longitude; +} +``` + +**After (4.0.0) - With `-parameters` flag:** + +```java +@MaxMindDbConstructor +public Location(Double latitude, Double longitude) { + this.latitude = latitude; + this.longitude = longitude; +} +``` + +### New Injection Annotations + +4.0.0 introduces `@MaxMindDbIpAddress` and `@MaxMindDbNetwork` annotations for +injecting lookup context into your constructors. + +**Example:** + +```java +public record EnrichedData( + String city, + @MaxMindDbIpAddress InetAddress lookupIp, + @MaxMindDbNetwork Network network +) {} +``` + +## Large Database Support (>2GB) + +Version 4.0.0 adds support for MaxMind DB files larger than 2GB. This change is +transparent to most users: + +- Files under 2GB continue to use a single `ByteBuffer` for optimal performance +- Files 2GB and larger automatically use a multi-buffer implementation +- No code changes required in your application + +## Migration Checklist + +1. ✅ Upgrade to Java 17 or later +2. ✅ Update Maven/Gradle dependency to 4.0.0 +3. ✅ Replace `record.getData()` with `record.data()` +4. ✅ Replace `record.getNetwork()` with `record.network()` +5. ✅ Replace `network.getNetworkAddress()` with `network.networkAddress()` +6. ✅ Replace `network.getPrefixLength()` with `network.prefixLength()` +7. ✅ Update all `Metadata` getter methods (remove `get` prefix, use camelCase) +8. ✅ Replace `metadata.getBuildDate()` with `metadata.buildTime()` and change + type from `Date` to `Instant` +9. ✅ Update any manual `DatabaseRecord` constructions to use `Network` + parameter +10. ✅ (Optional) Remove unnecessary `@MaxMindDbParameter` annotations if using + records or `-parameters` flag + +## Finding Issues + +To help identify code that needs updating, you can search your codebase for: + +- `.getData()` +- `.getNetwork()` +- `.getNetworkAddress()` +- `.getPrefixLength()` +- `.getBuildDate()` +- `.getBinaryFormatMajorVersion()` (and similar Metadata getters) +- `new DatabaseRecord<>` (check for three-parameter constructor) + +## Support + +If you encounter issues during the upgrade, please check: + +- [GitHub Issues](https://github.com/maxmind/MaxMind-DB-Reader-java/issues) +- [MaxMind Support](https://www.maxmind.com/en/support) diff --git a/pom.xml b/pom.xml index cab3d1a8..652f4f3d 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.maxmind.db maxmind-db - 4.0.0-SNAPSHOT + 4.0.0 jar MaxMind DB Reader Reader for MaxMind DB diff --git a/src/test/java/com/maxmind/db/ReaderTest.java b/src/test/java/com/maxmind/db/ReaderTest.java index 20479831..890a95ac 100644 --- a/src/test/java/com/maxmind/db/ReaderTest.java +++ b/src/test/java/com/maxmind/db/ReaderTest.java @@ -2001,7 +2001,6 @@ private void testIpV4(Reader reader, File file) throws IOException { } } - // XXX - logic could be combined with above private void testIpV6(Reader reader, File file) throws IOException { var subnets = new String[] {"::1:ffff:ffff", "::2:0:0", "::2:0:40", "::2:0:50", "::2:0:58"};