Skip to main content

Posts

Showing posts from February, 2013

Advanced ListenableFuture capabilities

Last time we familiarized ourselves with ListenableFuture. I promised to introduced more advanced techniques, namely transformations and chaining. Let's start from something straightforward. Say we have our ListenableFuture<String> which we got from some asynchronous service. We also have a simple method:

Document parse(String xml) {//... We don't need String, we need Document. One way would be to simply resolve Future (wait for it) and do the processing on String. But much more elegant solution is to apply transformation once the results are available and treat our method as if was always returning ListenableFuture<Document>. This is pretty straightforward:

final ListenableFuture<String> future = //... final ListenableFuture<Document> documentFuture = Futures.transform(future, new Function<String, Document>() { @Override public Document apply(String contents) { return parse(contents); } }); or more readable:

final Function<…

ListenableFuture in Guava

ListenableFuture in Guava is an attempt to define consistent API for Future objects to register completion callbacks. With the ability to add callback when Future completes, we can asynchronously and effectively respond to incoming events. If your application is highly concurrent with lots of future objects, I strongly recommend using ListenableFuture whenever you can.

Technically ListenableFuture extends Future interface by adding simple

void addListener(Runnable listener, Executor executor) method. That's it. If you get a hold of ListenableFuture you can register Runnable to be executed immediately when future in question completes. You must also supply Executor (ExecutorService extends it) that will be used to execute your listener - so that long-running listeners do not occupy your worker threads.

Let's put that into action. We will start by refactoring our first example of web crawler to use ListenableFuture. Fortunately in case of thread pools it's just a matter of …

ExecutorCompletionService in practice

Everyone is talking about the future of Java, we continue our journey explaining Future<T> interface in Java. ExecutorCompletionService wrapper class tries to address one of the biggest deficiencies of Future<T> type - no support for callbacks or any event-driven behaviour whatsoever. Let's go back for a moment to our sample asynchronous task downloading contents of a given URL:

final ExecutorService pool = Executors.newFixedThreadPool(10); pool.submit(new Callable<String>() { @Override public String call() throws Exception { try (InputStream input = url.openStream()) { return IOUtils.toString(input, StandardCharsets.UTF_8); } } }); Having such code we can easily write a simple web search engine/crawler, examining several URLs concurrently:

final List<String> topSites = Arrays.asList( "www.google.com", "www.youtube.com", "www.yahoo.com", "www.msn.com", "www.…

Implementing custom Future

Last time we learned the principles behind java.util.concurrent.Future<T>. We also discovered that Future<T> is typically returned by libraries or frameworks. But there is nothing stopping us from implementing it all by ourselves when it makes sense. It is not particularly complex and may significantly improve your design. I did my best to pick interesting use case for our example.

JMS (Java Message Service) is a standard Java API for sending asynchronous messages. When we think about JMS, we immediately see a client sending a message to a server (broker) in a fire and forget manner. But it is equally common to implement request-reply messaging pattern on top of JMS. The implementation is fairly simple: you send a request message (of course asynchronously) to an MDB on the other side. MDB processes the request and sends a reply back either to hardcoded reply queue or to an arbitrary queue chosen by the client and sent along with the message in JMSReplyTo property. The seco…

java.util.concurrent.Future basics

Hereby I am starting a series of articles about future concept in programming languages (also known as promises or delays) with a working title: Back to the Future. Futures are very important abstraction, even more these day than ever due to growing demand for asynchronous, event-driven, parallel and scalable systems. In the first article we'll discover most basic java.util.concurrent.Future<T> interface. Later on we will jump into other frameworks, libraries or even languages. Future<T> is pretty limited, but essential to understand, ekhm, future parts.

In a single-threaded application when you call a method it returns only when the computations are done (IOUtils.toString() comes from Apache Commons IO):

public String downloadContents(URL url) throws IOException { try(InputStream input = url.openStream()) { return IOUtils.toString(input, StandardCharsets.UTF_8); } } //... final String contents = downloadContents(new URL("http://www.example.com&q…

Don't rely on unit tests alone

When you are building a complex system, barely testing components in isolation is not enough. It's crucial, but not enough. Imagine a car factory that manufactures and imports highest quality parts, but after assembling the vehicle never starts the engine. If your test case suite consists barely of unit tests, you can never be sure that the system as a whole works. Let's give a contrived example:

public class UserDao { public List<User> findRecentUsers() { try { return //run some query } catch(EmptyResultDataAccessException ignored) { return null; } } //... } I hope you already spotted an anti-pattern in the catch block (and I don't mean ignoring the exception, it seems to be expected). Being a good citizen we decide to fix the implementation by returning an empty collection instead of null:

Breaking build is not a crime

For years I've been taught that breaking continuous integration build is something that should be avoided under all circumstances. Let me first quote few classics. Uncle Bob in The Clean Coder says:

The team must simply keep the build working at all times. If the build fails, it should be a “stop the presses” event and the team should meet to quickly resolve the issue. and later in that section:

I have every developer run the continuous-build script before they commit. Final quote:

They (CI tests) should never fail. If they fail, then the whole team should stop what they are doing and focus on getting the broken tests to pass again. A broken build [...] should be viewed as an emergency[...] In another wonderful book Continuous Delivery by Jez Humble and David Farley the authors go way further. They present 7-point plan that we should follow on every commit (!):

3. Run the build script and tests on your development machine to make sure that everything still works correctly on your …