DEV Community

Cover image for How to configure host name resolution to use a universal host name resolver in Java
JJBRT
JJBRT

Posted on • Edited on

2

How to configure host name resolution to use a universal host name resolver in Java

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:

<dependency>
    <groupId>org.burningwave</groupId>
    <artifactId>tools</artifactId>
    <version>0.26.2</version>
</dependency>

HitCount

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
view raw config.yml hosted with ❤ by GitHub

From here you can download/clone the tutorial shared on GitHub.

Speedy emails, satisfied customers

Postmark Image

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more