Both have a set of hashes (the old one only has one, which is itself), both can create a verification string from a set of features and identities and both can create a "capability hash node", each using their own algorithm.

The interface Hashed is implemented by the old Entity Caps and also by the XEP-0300 hash element. InfoNode is a disco#info query response (features, identities, extensions).

The class structure looks like this:

Processing Entity Capabilities

When processing a presence stanza or stream features with either or both old and new Entity Capabilities, the flow has become quite complex as you can see in the following flow chart. However, the good news is that it works with only the above interface. Take a look at how it's implemented right now:

Generating Entity Capabilities

The generating entity side is a bit easier:

I hope you liked this little presentation about how both XEP-0115 and XEP-0390 can be implemented behind the same interface.

Entity Capabilties 2.0 will of course be available in the next release.

The method getLastActivity() sends out the IQ request and then waited (blocked) a few milliseconds or even seconds for the response or until a timeout happened.

Having blocking operations is of course resource consuming because you have to dedicate a thread for it, which however is blocking most of the time while waiting on the operation to finish. It's the same issue as with blocking IO and the reason why NIO exists.

Doing multiple blocking IQ queries in parallel means, you have to create a thread for each query.

If you want to do such an IQ query from a JavaFX application you also had to write a lot of boilerplate code like this:

You don't want to block the UI thread and therefore need to run blocking operations in a background task.

Furthermore the blocking API in Babbler was not interruptible because it didn't throw InterruptedException.
Of course we could have solved the interruptible issue easily, but you still would have the drawbacks of a blocking API.

Futures to the Rescue

Instead of waiting for the response and then returning the result, all IQ-based APIs now return a java.util.concurrent.Future:

You might ask, what we've gained now, because the get() method is blocking again and usually you need the IQ result anyway.

Well, that's true. One part of the answer is that we gain interruptibility and the other part is that the returned result is not only a Future, but also a java.util.concurrent.CompletionStage (Java 8's new toy).

It basically allows you to react asynchronously when the result is present, i.e. when the Future is done.
Some frameworks like Guava already have such a concept of a "Listenable Future", now it's part of the JDK.

Taking our JavaFX example from above, updating the UI with the result as in the above example can now become a simple one-liner: