diff --git a/CHANGELOG.md b/CHANGELOG.md index f068cedb..2353accc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ CHANGELOG ========= -5.0.2 (unreleased) +5.0.2 (2025-12-08) ------------------ * Fixed an issue where decoding `IpRiskResponse` from the IP Risk database would @@ -10,6 +10,11 @@ CHANGELOG that the risk score was not set in the database. In a future major release, this field may be changed to a nullable `Double` to better distinguish between "no data" and "zero risk". Reported by Fabrice Bacchella. GitHub #644. +* Updated `maxmind-db` dependency to 4.0.2. This fixes a bug where enums with + `@MaxMindDbCreator` would throw `ConstructorNotFoundException` when the data + was stored via a pointer in the database, commonly occurring with deduplicated + data in larger databases. It also improves error messages when constructor + invocation fails. Reported by Fabrice Bacchella. GitHub #644. 5.0.1 (2025-12-02) ------------------ diff --git a/README.md b/README.md index 51be05ac..2dd2ae45 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ To do this, add the dependency to your pom.xml: com.maxmind.geoip2 geoip2 - 5.0.1 + 5.0.2 ``` @@ -30,7 +30,7 @@ repositories { mavenCentral() } dependencies { - compile 'com.maxmind.geoip2:geoip2:5.0.1' + compile 'com.maxmind.geoip2:geoip2:5.0.2' } ``` diff --git a/pom.xml b/pom.xml index c0a8ba34..53720006 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ 4.0.0 com.maxmind.geoip2 geoip2 - 5.0.1 + 5.0.2 jar MaxMind GeoIP2 API GeoIP2 webservice client and database reader @@ -53,7 +53,7 @@ com.maxmind.db maxmind-db - 4.0.1 + 4.0.2 com.fasterxml.jackson.core diff --git a/src/test/java/com/maxmind/geoip2/DatabaseReaderTest.java b/src/test/java/com/maxmind/geoip2/DatabaseReaderTest.java index 21b1e6e6..746838a1 100644 --- a/src/test/java/com/maxmind/geoip2/DatabaseReaderTest.java +++ b/src/test/java/com/maxmind/geoip2/DatabaseReaderTest.java @@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import com.maxmind.db.Networks; import com.maxmind.db.Reader; import com.maxmind.geoip2.exception.AddressNotFoundException; import com.maxmind.geoip2.exception.GeoIp2Exception; @@ -27,6 +28,8 @@ import java.net.InetAddress; import java.net.URISyntaxException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.Paths; import java.util.Arrays; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -475,4 +478,78 @@ private File getFile(String filename) throws URISyntaxException { .getResource("/maxmind-db/test-data/" + filename); return new File(resource.toURI()); } + + /** + * Tests that all records in each test database can be deserialized. + * This test iterates over every network in the database and performs + * a lookup to ensure no deserialization errors occur. + * + *

Based on the reproduction test from GitHub issue #644. + * https://github.com/maxmind/GeoIP2-java/issues/644 + */ + @Test + public void testAllRecordsDeserialize() throws Exception { + var testDataDir = Paths.get( + getClass().getResource("/maxmind-db/test-data").toURI() + ); + + try (var stream = Files.newDirectoryStream(testDataDir, "*.mmdb")) { + for (var dbPath : stream) { + var filename = dbPath.getFileName().toString(); + + if (shouldSkipDatabase(filename)) { + continue; + } + + try (var reader = new Reader(dbPath.toFile()); + var dbReader = new DatabaseReader.Builder(dbPath.toFile()).build()) { + + var dbType = reader.getMetadata().databaseType(); + var networks = reader.networks(Object.class); + + while (networks.hasNext()) { + var ip = networks.next().network().networkAddress(); + lookupByDatabaseType(dbReader, dbType, ip); + } + } + } + } + } + + private boolean shouldSkipDatabase(String filename) { + // Skip internal test databases and those without model classes in GeoIP2-java + return filename.startsWith("MaxMind-DB-") + || filename.contains("Broken") + || filename.contains("Invalid") + || filename.contains("DensityIncome") + || filename.contains("User-Count") + || filename.contains("Static-IP-Score"); + } + + private void lookupByDatabaseType(DatabaseReader reader, String dbType, InetAddress ip) + throws IOException, GeoIp2Exception { + if (dbType.contains("City")) { + reader.city(ip); + } else if (dbType.contains("Country")) { + reader.country(ip); + } else if (dbType.contains("Enterprise")) { + reader.enterprise(ip); + } else if (dbType.equals("GeoIP-Anonymous-Plus")) { + reader.anonymousPlus(ip); + } else if (dbType.equals("GeoIP2-Anonymous-IP")) { + reader.anonymousIp(ip); + } else if (dbType.equals("GeoIP2-ISP")) { + reader.isp(ip); + } else if (dbType.equals("GeoIP2-IP-Risk")) { + reader.ipRisk(ip); + } else if (dbType.equals("GeoIP2-Domain")) { + reader.domain(ip); + } else if (dbType.equals("GeoLite2-ASN")) { + reader.asn(ip); + } else if (dbType.equals("GeoIP2-Connection-Type")) { + reader.connectionType(ip); + } else { + throw new IllegalArgumentException("Unknown database type: " + dbType); + } + } }