What’s Wrong With Java: Angst APIs

3. February, 2009

If you’ve been using Java for a while, you will have encountered the need to start an external process. So you use Runtime.getRuntime().exec(...) … and you’re stuck. You can’t set the current directory for the new process, change the environment, etc. And you’ll also have to handle deadlocks.

Bad Java. Down. So Martin Buchholz came up with ProcessBuilder. I’ll use this API to explain my concept of “Angst API”. An Angst API is an API which keeps you afraid. You use it and there is the constant feeling that something might break. The default case (which should work out of the box) is in fact the most hard to make work right.

If you know a bit about processes, you know how easy it is to get a deadlock when one is reading from the other: Process 1 is trying to write some more data to process 2 which is waiting for process 1 to read the data is has sent back a few moments ago. Deadlock.

To avoid this, you need to wrap the output streams (from which your process is reading) in a thread. This is the default case. In the special case, when you know that the processes won’t exchange any data, you don’t need this but in the common case, you do. This is what is broken with the ProcessBuilder API: It makes the special case (no data exchange) simple and the common case hard. It even tries its best to make a fix hard: All classes involved are final, private, the “no trespassing” style.

Which is the other side of the Angst API: We don’t want to bloat the Java runtime, we are afraid that some user might reuse our code, we are afraid that the performance could suffer, we are afraid that error handling is more complex if we start a background thread (one thread would be enough to process the outputs of all external processes).

When you design an API, don’t be afraid. Make it a nice API, one which you love to write, which users love to use and which welcomes them with open arms. No one likes the scary neighbor who waits for trespassers with a gun in his arms.

Stop Auto-Scrolling in SWT When The User Grabs The Scrollbar

3. February, 2009

Imagine you have a console widget in an SWT app. The app is doing some background work and dumps lots of text in the console. Something catches the eye of the user and she desperately tries to keep it in view while the console jumps to the bottom all of the time. Here is a simple solution how to notice that the user has grabbed the scrollbar.

    private AtomicBoolean userHoldsScrollbar
                = new AtomicBoolean ();

        control.getVerticalBar ().addSelectionListener (new SelectionListener () {
            public void widgetDefaultSelected (SelectionEvent e)
                // NOP

            public void widgetSelected (SelectionEvent e)
                if (e.detail == SWT.DRAG)
                    userHoldsScrollbar.set (true);
                else if (e.detail == SWT.NONE)
                    userHoldsScrollbar.set (false);

In your auto-scroll code, check whether userHoldsScrollbar.get() is true.

Improving Performance of The Data Layer

3. February, 2009

Anyone here who is working on an application which doesn’t need to persist its model in a database? You can tune out here.

The rest of you knows the problem: You have a change in your model, you need to persist it. The problem: The persistence layer is synchronous. Your application “hangs” until the change is written to the database and the database has confirmed the commit. The reason for this design is error handling: We are afraid of what might happen if there is an error in a commit for a transaction which we sent to the persistence layer five minutes ago. What’s the user supposed to do? How can the storage thread decide what to do with the following commits? Throw them away? Suppress them until the problem has been fixed five days later? Write them to a file? To name but a few.

If  there is no error, this is not an issue and this works astonishingly good. I implemented such a scheme with roughly 50 lines in my program upcscan. For Java with it’s unhealthy type system, that would be a bit more code, a whole lot harder to get right. Fortunately, the guys at Terracotta offer a support module for that.

Read more in this article: Asynchronous Write Behinds and the Repository Pattern