In the JDK 8 the java.net.InetAddress resolves host names using the local machine's default host name resolver by default:
Host name-to-IP address resolution is accomplished through the use of a combination of local machine configuration information and network naming services such as the Domain Name System (DNS) and Network Information Service(NIS). The particular naming services(s) being used is by default the local machine configured one. For any host name, its corresponding IP address is returned. [source]
In the JDK 19 the java.net.InetAddress works the same way but there is also the option to use a custom configuration:
The built-in InetAddress resolver implementation does host name-to-IP address resolution and vice versa through the use of a combination of local machine configuration information and network naming services such as the Domain Name System (DNS) and the Lightweight Directory Access Protocol (LDAP). The particular naming services that the built-in resolver uses by default depends on the configuration of the local machine. InetAddress has a service provider mechanism for InetAddress resolvers that allows a custom InetAddress resolver to be used instead of the built-in implementation. [source]
So how can we configure this behavior without modifying the local machine's default host name resolver in a universal way that works for Java 8 and later?
In this situation Burningwave Tools comes to our aid by providing us with the HostResolutionRequestInterceptor
that allows us:
- to use a custom resolver instead the default one
- to prepend a custom resolver to the default one
- to postpone a custom resolver to the default one
To include Burningwave Tools in our project we need to add the following dependency to our pom.xml:
And to install the HostResolutionRequestInterceptor component we must proceed as follows:
Map<String, String> hostAliases = new LinkedHashMap<>(); | |
hostAliases.put("my.hostname.one", "123.123.123.123"); | |
//Installing the host resolvers | |
HostResolutionRequestInterceptor.INSTANCE.install( | |
new MappedHostResolver(hostAliases), | |
//This is the system default resolving wrapper | |
DefaultHostResolver.INSTANCE | |
); | |
InetAddress inetAddress = InetAddress.getByName("my.hostname.one"); |
Burningwave Tools provides also a DNS server connection based host resolver:
HostResolutionRequestInterceptor.INSTANCE.install( | |
new DNSClientHostResolver("208.67.222.222"), //Open DNS server | |
new DNSClientHostResolver("208.67.222.220"), //Open DNS server | |
new DNSClientHostResolver("8.8.8.8"), //Google DNS server | |
new DNSClientHostResolver("8.8.4.4"), //Google DNS server | |
DefaultHostResolver.INSTANCE | |
); | |
InetAddress inetAddress = InetAddress.getByName("github.com"); |
But you can also define a new custom resolver by implementing the HostResolver interface that create DNS packet requests, send them to the servers through the java.net.DatagramSocket and parse the responses:
HostResolutionRequestInterceptor.INSTANCE.install( | |
new HostResolver() { | |
@Override | |
public Collection<InetAddress> getAllAddressesForHostName(Map<String, Object> argumentMap) { | |
String hostName = (String)super.getMethodArguments(argumentMap)[0] | |
//Do the stuff... | |
} | |
@Override | |
public Collection<String> getAllHostNamesForHostAddress(Map<String, Object> argumentMap) { | |
byte[] iPAddressAsByteArray = (byte[])super.getMethodArguments(argumentMap)[0]; | |
String iPAddress = IPAddressUtil.INSTANCE.numericToTextFormat(iPAddressAsByteArray); | |
//Do the stuff... | |
} | |
}, | |
DefaultHostResolver.INSTANCE | |
); |
If we add the Jackson framework to our project we can add the configuration via yaml file support with a few lines of code by using the PathHelper
component:
public static void installHostResolutionRequestInterceptor() throws UnknownHostException { | |
Map<String, Object> configuration = loadConfiguration("config.yml"); | |
List<HostResolver> resolvers = new ArrayList<>(); | |
resolvers.add( | |
new MappedHostResolver(() -> (List<Map<String, Object>>)configuration.get("hostAliases")) | |
); | |
resolvers.addAll( | |
DNSClientHostResolver.newInstances(() -> | |
(List<Map<String, Object>>)((Map<String, Object>)configuration.get("dns")).get("servers") | |
) | |
); | |
resolvers.add(DefaultHostResolver.INSTANCE); | |
HostResolutionRequestInterceptor.INSTANCE.install( | |
resolvers.toArray(new HostResolver[resolvers.size()]) | |
); | |
InetAddress.getByName("google.com"); | |
} | |
public static Map<String, Object> loadConfiguration(String fileNameRelativePathFromClasspath) { | |
ObjectMapper mapper = new ObjectMapper(new YAMLFactory()); | |
try (InputStream inputStream = ComponentContainer.getInstance().getPathHelper().getResourceAsStream(fileRelativePathFromClasspath)) { | |
return mapper.readValue(inputStream, Map.class); | |
} catch (IOException exc) { | |
return Driver.throwException(exc); | |
} | |
} |
hostAliases: | |
- ip: 123.123.123.123 | |
hostnames: | |
- my.hostname.one | |
- my.hostname.two | |
- ip: 12.21.34.43 | |
hostnames: | |
- my.hostname.three | |
- my.hostname.four | |
dns: | |
servers: | |
- ip: 208.67.222.222 | |
port: 53 | |
ipTypeToSearchFor: | |
- IPV4 | |
- IPV6 | |
- ip: 208.67.222.220 | |
port: 53 | |
ipTypeToSearchFor: | |
- IPV4 | |
- IPV6 |
From here you can download/clone the tutorial shared on GitHub.
Top comments (0)