Class IP2LocationService
- All Implemented Interfaces:
AutoCloseable
This service provides a complete solution for IP geolocation including:
- Automatic monthly database downloads from IP2Location
- Support for both IPv4 and IPv6 lookups
- Thread-safe concurrent lookups
- Hot-reload of databases without service restart
- Configurable memory-mapped file support
- Proxy support via system
ProxySelector - Asynchronous initialization with callbacks
- Custom thread factory for virtual thread support (Java 21+)
- Parallel download of IPv4 and IPv6 databases
- Recovery mode for corrupted state or databases
- Disabled mode for dev/test environments or feature flags
- Human-readable status descriptions for UI display
Quick Start (Blocking)
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.includeIPv6(true)
.directory(Paths.get("/var/lib/ip2location"))
.build(); // Blocks until databases are loaded
GeoLocation loc = service.lookup("8.8.8.8");
if (loc.isOk()) {
System.out.println("Country: " + loc.getCountryCode());
System.out.println("Location: " + loc.getLocationDescription());
}
// Display service status in UI
statusLabel.setText(service.getStatusDescription());
// "IPv4+IPv6, IPv4 ready, IPv6 ready"
service.dispose();
Async Initialization
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.buildAsync((svc, success, error) -> {
if (success) {
System.out.println("Service ready!");
} else {
System.err.println("Init failed: " + error);
}
});
// Service returned immediately, initialization runs in background
// Wait for initialization if needed:
boolean ready = service.awaitReady(30, TimeUnit.SECONDS);
Recovery Mode
If the database or state files become corrupted, use recovery mode to clear everything and start fresh:
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.database(Database.DB11)
.directory(Paths.get("/var/lib/ip2location"))
.attemptRecovery() // Clears directory before initialization
.build();
For manual recovery without creating a new service:
// Clear directory manually (service must be disposed first!)
Path dir = Paths.get("/var/lib/ip2location");
int deleted = IP2LocationService.clearDirectory(dir, IEventLogger.nullLogger());
System.out.println("Deleted " + deleted + " files");
Disabled Mode
The service can be started disabled for environments where geolocation is not needed:
boolean useGeoLocation = Boolean.parseBoolean(
System.getProperty("app.geolocation.enabled", "true"));
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.enabled(useGeoLocation) // Disable via configuration
.build();
if (service.isEnabled()) {
GeoLocation loc = service.lookup("8.8.8.8");
}
Threads
Background work (initialization, downloads, the update scheduler) runs on virtual threads by default (IThreadFactory.virtualFactory()); a host that manages its own threads sets another factory:
IP2LocationService service = new IP2LocationService.Builder()
.downloadToken("YOUR_TOKEN")
.threadFactory(IThreadFactory.defaultFactory())
.buildAsync();
Database Update Schedule
IP2Location LITE databases are updated on the 1st of each calendar month. This service follows IP2Location's recommendation to download during days 1-7 of each month. The service also forces a download on startup if the existing database is from a previous month.
IPv6 Support
When IP2LocationService.Builder.includeIPv6(boolean) is set to true:
- Both IPv4 and IPv6 databases are downloaded (in parallel for speed)
- IPv4 lookups use the smaller IPv4-only database for efficiency
- IPv6 lookups use the IPv6 database (which also contains IPv4 ranges)
Memory-Mapped Files
The service supports two database access modes:
- Memory-mapped (
useMemoryMappedFile=true): Uses less heap memory, OS manages page caching. Best for production servers with adequate RAM. - Standard (
useMemoryMappedFile=false, default): More predictable memory behavior. Better for containers or memory-constrained environments.
Reconfiguration
This service is immutable after construction. To change configuration:
- Call
dispose()on the existing instance - Create a new instance with
IP2LocationService.Builder
For seamless reconfiguration without downtime, use IP2LocationManager.
Thread Safety
This class is thread-safe. Multiple threads can safely call lookup(String) concurrently. Database reloads are performed atomically using read-write locks.
The builder defaults to virtual threads for all background work.
- Author:
- Christopher Mindus
- See Also:
Nested Class Summary
Nested ClassesMethod Summary
Modifier and TypeMethodDescriptionbooleanawaitReady(long timeout, TimeUnit unit) Waits for the service to become ready.static intclearDirectory(Path directory, IEventLogger logger) Clears an IP2Location directory, removing all database and state files.voidclose()Alias fordispose()to support try-with-resources.voiddispose()Disposes of the service, releasing all resources.voidForces an immediate database update check and download.Returns the configured database type.Returns the configured storage directory.Returns the error that occurred during initialization.Returns the date of the currently loaded IPv4 database.Returns the date of the currently loaded IPv6 database.Returns the month of the last successful database update.Returns the instant when the next scheduled update check will occur.Returns the current status as a human-readable string for UI display.static booleanhasValidDatabases(Path directory, boolean requireIPv6) Checks if an IP2Location directory contains valid database files.booleanReturns whether the service is enabled.booleanReturns whether an IPv4 database is loaded and ready.booleanReturns whether IPv6 support is enabled.booleanReturns whether an IPv6 database is loaded and ready.booleanisReady()Returns whether the service is ready to handle lookups.booleanReturns whether the service is currently running.booleanReturns whether memory-mapped file mode is enabled.Looks up geolocation information for an IP address.voidsetDatabaseLoadCallback(BiConsumer<LocalDate, Boolean> callback) Sets a callback invoked when a database file is loaded into memory.voidsetDownloadCallback(IInitializationCallback callback) Sets a callback invoked after each download attempt (forced or scheduled).
Method Details
clearDirectory
Clears an IP2Location directory, removing all database and state files.This is a recovery utility that can be used when the database or state files become corrupted. It deletes:
- All
*.BINand*.bindatabase files - The state file (
.ip2location-state.properties) - All
*.tmptemporary files - All
*.zipdownload files
Important: All IP2LocationService instances using this directory must be disposed before calling this method. Otherwise, the service may hold file locks that prevent deletion, or may become unstable.
Usage Example
// First, dispose the service service.dispose(); // Clear the directory Path dir = Paths.get("/var/lib/ip2location"); int deleted = IP2LocationService.clearDirectory(dir, IEventLogger.nullLogger()); System.out.println("Deleted " + deleted + " files"); // Create a new service (will download fresh databases) service = new IP2LocationService.Builder() .downloadToken("YOUR_TOKEN") .directory(dir) .build();- Parameters:
directory- The directory to clearlogger- Logger for reporting progress (may benullfor silent operation)- Returns:
- The number of files deleted
- Throws:
IOException- if the directory cannot be accessed or files cannot be deleted
- All
hasValidDatabases
Checks if an IP2Location directory contains valid database files.This method can be used to determine if recovery might be needed before creating a service instance.
- Parameters:
directory- The directory to checkrequireIPv6- Whether to require both IPv4 and IPv6 databases- Returns:
trueif the directory contains the required database files
dispose
public void dispose()Disposes of the service, releasing all resources.This method:
- Cancels all scheduled update tasks
- Closes all loaded database readers
- Releases any memory-mapped file mappings
After calling this method, the service cannot be restarted. This method is idempotent.
close
public void close()Alias fordispose()to support try-with-resources.- Specified by:
closein interfaceAutoCloseable
isReady
public boolean isReady()Returns whether the service is ready to handle lookups.A service is ready when at least one database has been loaded. This method returns immediately without blocking.
- Returns:
trueif at least one database is loaded
awaitReady
Waits for the service to become ready.Blocks until initialization completes or the timeout expires.
- Parameters:
timeout- The maximum time to waitunit- The time unit- Returns:
trueif the service is ready,falseif timeout expired- Throws:
InterruptedException- if the current thread was interrupted
getInitializationError
Returns the error that occurred during initialization.- Returns:
- The initialization error, or
nullif successful
lookup
Looks up geolocation information for an IP address.This method automatically detects whether the IP is IPv4 or IPv6 and routes to the appropriate database.
- Parameters:
ip- The IP address to look up (e.g., "8.8.8.8" or "2001:4860:4860::8888")- Returns:
- A
GeoLocationcontaining the result (checkGeoLocation.isOk())
isEnabled
public boolean isEnabled()Returns whether the service is enabled.When disabled, the service does not download or load databases, does not start the update scheduler, and lookups return
STATUS_SERVICE_DISABLED.A disabled service consumes minimal resources and can be used as a placeholder when geolocation is not needed in certain environments (e.g., development, testing).
- Returns:
trueif the service is enabled,falseif disabled- See Also:
isRunning
public boolean isRunning()Returns whether the service is currently running.- Returns:
trueif started and not disposed
isIPv4Ready
public boolean isIPv4Ready()Returns whether an IPv4 database is loaded and ready.- Returns:
trueif IPv4 lookups are available
isIPv6Ready
public boolean isIPv6Ready()Returns whether an IPv6 database is loaded and ready.- Returns:
trueif IPv6 lookups are available
getLastUpdateMonth
Returns the month of the last successful database update.- Returns:
- The year-month of last update, or
nullif never updated
isUsingMemoryMappedFile
public boolean isUsingMemoryMappedFile()Returns whether memory-mapped file mode is enabled.- Returns:
trueif using memory-mapped files
getDirectory
Returns the configured storage directory.- Returns:
- Path to the database storage directory
getDatabase
Returns the configured database type.- Returns:
- The database type being used
isIPv6Enabled
public boolean isIPv6Enabled()Returns whether IPv6 support is enabled.- Returns:
trueif IPv6 lookups are enabled
getIPv4DatabaseDate
Returns the date of the currently loaded IPv4 database.The date reflects when the database was published by IP2Location, typically the 1st of the month.
- Returns:
- The database date, or
nullif no IPv4 database is loaded
getIPv6DatabaseDate
Returns the date of the currently loaded IPv6 database.The date reflects when the database was published by IP2Location, typically the 1st of the month.
- Returns:
- The database date, or
nullif no IPv6 database is loaded or IPv6 support is not enabled
getNextScheduledUpdate
Returns the instant when the next scheduled update check will occur.This reflects the scheduler's next planned execution, not necessarily when a download will occur (which depends on the current month and whether an update is needed).
- Returns:
- The instant of the next scheduled check, or
nullif the scheduler is not running (service disabled, not started, or disposed)
getStatusDescription
Returns the current status as a human-readable string for UI display.The status components are concatenated in order of importance, separated by ", " (comma and space). Possible components include:
- Disposed - Service has been disposed
- Disabled - Service is disabled
- Initializing - Service is starting up
- IPv4 only - Only IPv4 lookups enabled
- IPv4+IPv6 - Both IPv4 and IPv6 lookups enabled
- Downloading IPv4 - IPv4 database download in progress
- Downloading IPv6 - IPv6 database download in progress
- IPv4 ready - IPv4 database loaded
- IPv6 ready - IPv6 database loaded
- IPv4 not loaded - IPv4 database not available
- IPv6 not loaded - IPv6 database not available
Example outputs:
- "Disabled"
- "IPv4 only, IPv4 ready"
- "IPv4+IPv6, Downloading IPv4, Downloading IPv6"
- "IPv4+IPv6, IPv4 ready, IPv6 ready"
- "Disposed"
- Returns:
- A comma-separated status string, never
null
setDownloadCallback
Sets a callback invoked after each download attempt (forced or scheduled).- Parameters:
callback- The callback, ornullto remove
setDatabaseLoadCallback
Sets a callback invoked when a database file is loaded into memory.- Parameters:
callback- The callback receiving (date, isIPv6), ornullto remove
forceUpdate
public void forceUpdate()Forces an immediate database update check and download.This bypasses the normal scheduling logic and attempts to download the latest database immediately. The operation runs asynchronously.
- Throws:
IllegalStateException- if the service is not running