Getting a usable, non-localhost IP address for a JVM

I recently had a task where I needed to inform a docker image of the host OS’ IP address. (The docker image needed to make an HTTP call to the host machine, for testing purposes.) However, it’s not trivial to find code to actually get a host machine’s IP address. Here’s some code in Kotlin (and in Java) to accomplish the task; I can’t say it’s perfect (and won’t) but it worked for me, and hopefully this can serve as a tentpole for perhaps better code.
There are two pieces of code here; both eliminate the 10.*.*.* network. If you don’t need that network to be eliminated, well, remove that line.

Kotlin

import java.net.NetworkInterface
fun getAddress(): String {
    return NetworkInterface.getNetworkInterfaces().toList().flatMap {
        it.inetAddresses.toList()
                .filter { it.address.size == 4 }
                .filter { !it.isLoopbackAddress }
                .filter { it.address[0] != 10.toByte() }
                .map { it.hostAddress }
    }.first()
}

Java

The Java code’s a lot more convoluted, and isn’t helped at all by the requirement for a means by which to convert an Enumeration to a Stream (copied shamelessly from “Iterate an Enumeration in Java 8“, by the way.) However, it’s functionally equivalent to the Kotlin code. If it can’t find a valid address or an internal exception is thrown, a RuntimeException is created and thrown.

private static  Stream enumerationAsStream(Enumeration e) {
    return StreamSupport.stream(
            Spliterators.spliteratorUnknownSize(
                    new Iterator() {
                        public T next() {
                            return e.nextElement();
                        }
                        public boolean hasNext() {
                            return e.hasMoreElements();
                        }
                    },
                    Spliterator.ORDERED), false);
}
public static String getAddress() {
    try {
        Optional address = enumerationAsStream(NetworkInterface.getNetworkInterfaces())
                .flatMap(networkInterface ->
                        networkInterface.getInterfaceAddresses().stream()
                )
                .filter(ia -> !ia.getAddress().isLoopbackAddress())
                .map(InterfaceAddress::getAddress)
                .filter(a -> a.getAddress().length == 4)
                .filter(a -> a.getAddress()[0] != 10)
                .findFirst();
        if (address.isPresent()) {
            return address.get().getHostAddress();
        } else {
            throw new RuntimeException("Address not accessible");
        }
    } catch (SocketException e) {
        throw new RuntimeException(e);
    }
}

Summary

This is not perfect code, I wouldn’t think. It was thrown together to fit a specific need, and ideally should have been easily located on StackOverflow or something like that.

Interesting Links – 24 Oct 2016

  • The Way of the Lambda – Elegant and Efficient discusses using Java 8’s removeIf to remove elements from collections, as opposed to removing them via an iterator, and shows graphs to show the improvement. One claim (via Reddit) was that it was O(1) but here the claim is a little more reasonable. Another thing from the post was that the author says that he’s “recently … spent a few years away from Java development,” something that a lot of people seem to be saying now. Not sure what’s making that happen – maybe Java 8 made Java cool again.
  • Speedment is another persistence engine for Java, focusing on streams.
  • Java Method Reference Evaluation discusses Java’s evaluation of method references, as done by the :: operator. From the author: “The immediate target evaluation of method references is likely undesirable in most cases where the target can be expected to change between invocations. Consider using method references only for static methods and constructors (X::new), or with instance references that are known to remain unchanged for all invocations. If there is any chance that the target reference might need dynamic re-evaluation you will have to use a lambda expression.”
  • Meet Franz is a centralized chat application. I haven’t tried it and can’t vouch for it (yet) but given that I have four chat applications open at minimum at all times… it might be something I have to try soon.
  • From /r/java: apparently GWT 2.8.0 has been released. The website looks really nice; I liked GWT in the day; who knew development was ongoing? (No release notes were apparent on the website, unfortunately, so I don’t know offhand what changed; I could dig it up, but maintaining interest is difficult.)

How to execute a group of tasks

Someone on the channel today asked about how to run a series of tasks, with a terminal condition of sorts. Basically, they wanted to run a number of tasks, and know when they were done.
The question was originally built around having a List of results (List<integer>, maybe?), counting the number of results until the number of results matched the number of tasks.
The channel suggested using an ExecutorService, particularly the shutdown() and awaitTermination() methods, with another suggestion being invokeAll() – which seemed particularly apt because the person asking didn’t want to have to build a new ExecutorService over and over again (which the shutdown() call would necessitate, although the cost of doing this shouldn’t be very high.)
Here’s an example with Java 8, of using the invokeAll() to execute a series of tasks; the task is made-up (it basically rolls three six-sided dice to determine a histogram of results, as a callback to Dungeons and Dragons). It has one dependency, on Apache’s commons-lang3.

package org.javachannel.examples.executors;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.LockSupport;
import java.util.stream.IntStream;
class Worker implements Callable {
    int roll() {
        LockSupport.parkNanos((long) (Math.random() * 10000000));
        return (int) (Math.random() * 6) + 1;
    }
    @Override
    public Integer call() throws Exception {
        return roll() + roll() + roll();
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        List workerList = new ArrayList<>();
        IntStream.range(0, 100000).forEach(i -> workerList.add(new Worker()));
        ExecutorService service = Executors.newCachedThreadPool();
        int[] count = new int[19];
        service.invokeAll(workerList).stream().map(f -> {
            try {
                return f.get();
            } catch (Throwable e) {
                return 0;
            }
        }).forEach(m -> count[m]++);
        IntStream.rangeClosed(3, 18).forEach(r -> {
            System.out.printf("%02d %s%n", r, StringUtils.repeat("*", count[r]/100));
        });
    }
}

This code creates a list of tasks, populates it, and then submits all of them in one call (service.invokeAll(workerList)), then uses the Stream API to populate the array of results. It looks a little more complicated than it should because of the lambda to pull the int out of the Future</integer><integer>, which is what return value for call() becomes when it’s submitted to the Executor.
It’s not a perfect example; surely others can come up with better examples. Feel free to submit them!