You are brilliant, We are Hiring. Find out more...
Palantir Tech Blog

Archive for the ‘tips and tricks’ Category

Printing to Plotters in Java

Monday, August 11th, 2008

One of the things our customers love to do is print our beautiful object graphsландшафт and tape them to the wall for discussion. What they hate to do is print 30 pages, line them up, and tape them to a poster one at a time. So we bought a plotter, and I started plotting.

I needed to print directly to a Java Graphics object. Unfortunately, the available information on large output printing from Java is thin at best. While there are lots of ways to successfully place ink on paper, I was only able to find one that reliably lets the application pick odd paper sizes that plotters use, like 24×19.7 inches. (The term “plotter” used to mean something with pens for printing blueprints and such. Now it just means a large format printer, commonly printers that can use roll paper as a source.)

One of the first things you’ll learn when you start working with printing in Java is that a language intended to be all things to all people (i.e., cross-platform) is utterly lousy at tasks highly specific to a given environment, such as printing. It will not surprise you to hear that native print services on Windows are pretty different from those available on a Mac, which themselves are pretty different from the CUPS system common to Unix systems.

So, by and large, you are reduced to the least common denominator of printing. Part and parcel of this least common denominator is agreeing on what constitutes a piece of paper and sticking to it. This is fine for people thinking, “My paper is 8.5 inches wide by 11 inches tall.” It poses a bit of a problem for people with plotters who are thinking, “My paper is 24 inches wide by as many damned inches tall as I need.” Even relatively powerful programs like PhotoShop or GIMP don’t seem to support plotters well. I believe Photoshop works by specifying the exact paper size you want to use, but any technique in which the easiest solution for the user is to pull out a calculator does not meet with my approval.
(more…)

SSL HOWTO: using openssl to get keys into PKCS#12 format.

Monday, June 23rd, 2008

Some of our customers are pretty serious about data security. To that end, our products need to support and integrate with SSL for both data security and authentication. SSL is very neat technology, but there is a dizzying maze of standards to navigate to figure how to get it all to work.

It turns out that in this age of Google, the fastest way to figure out how to do something is often to Google for key terms and hope that someone has put the relevant details in a blog post somewhere. In trying to figure out how to set up keys on a SunOne Directory Server for testing our LDAP integration, I needed to figure out how to get keys into PKCS#12 format after generating them with OpenSSL.

I’ll spare you the gory details of what it took to figure out how to do this; suffice to say there was some trial and error mixed with a bunch of RTFM. After the jump, the full howto.
(more…)

SwingUtilities.invokeAndWait… doesn’t.

Thursday, February 21st, 2008

One of the most misunderstood aspects of multithreaded Swing applications is care and feeding of SwingUtilities.invokeAndWait. Hans Muller and Kathy Walrath authored a nice article that includes an overview of when to use invokeLater or its slightly more risky sibling, invokeAndWait.

We often use worker threads to do some long-running process, so often run into two issues using SwingUtilities invokeLater/invokeAndWait, and have developed wrapper code to deal with it. One issue is executing code from both worker threads and the Event Dispatch Thread (EDT). invokeLater and invokeAndWait both throw exceptions if executed on EDT. Second, invokeAndWait isn’t guaranteed — interruption on the calling thread will resume execution before the job is finished. The remainder of this post shows the code we used to solve these issues.

(more…)

Writing JUnit tests for memory leaks

Tuesday, November 6th, 2007

LeakMemory leaks are no fun — to find them, you usually have to do a work flow while using a profiler like YourKit, force garbage collection, capture a memory snapshot, and then manually go through the snapshot looking for objects that you expected to be gone but are still there.Even after you’ve finally fixed the memory leak, how can you make sure that the issue doesn’t resurface later? Every good developer knows that, if you fix a bug, you should probably also have a JUnit test for that bug so that it doesn’t happen again. But how can you test for memory leaks programmatically?Find out after the jump… (more…)

Getting equals() and hashCode() right

Wednesday, September 5th, 2007

Whenever you override the equals() and hashCode() functions of a class, it is very important that you do so correctly. Bugs in these functions are often quite insidious, because they will not fail catastrophically. Your application will compile and probably do something reasonable, passing any smoke test you throw at it. However, the output will be subtly incorrect. Moreover, by the time you realize that some has gone wrong, there is little information about what caused the error. This is because the error occurred 10 steps ago, nested five levels deep, when a member of a HashSet went MIA. While a NullPointerException is normally trivial to diagnose and fix, you can easily lose several hours tracking down an equals()/hashCode() bug.

There are many excellent tutorials out there on equals() and hashCode(). The best source is probably Items 7 and 8 of Effective Java by Josh Bloch, and we have a couple copies of this book floating around the office. A good online tutorial is Java theory and practice: Hashing it out, by another Java guru, Brian Goetz.

To test your understanding, make sure that you can answer the following questions. I often ask variants of the first two during interviews. The third comes from an error we’ve seen more than once in our code base.

  1. Suppose we have a Media class, composed of title and contents fields. What can go wrong if equals() is based on both fields, while hashCode() is based solely on title?
  2. Conversely, what can go wrong if hashCode() is based on both fields, but equals() is based solely on title?
  3. Consider a class A which overrides equals() and hashCode(). If you create a class B which extends class A, and use Eclipse to generate your equals() and hashCode() functions for class B, then the output of class B’s hashCode() function will depend on the value of super.hashCode(). What happens if you refactor class B so that it no longer extends class A?

Best Practices: compareTo consistent with equals

Sunday, September 2nd, 2007

What is wrong with this class and why? I’ll tell you beforehand there are two things I am looking for and they are both in the compareTo function. Yes, this came from the Palantir code base and caused me some issues. It has been modified slightly for illustrative purposes.

(more…)

SimpleDateFormat is not thread-safe

Wednesday, July 11th, 2007

It seems like a relatively common mistake is to assume that the java.text.SimpleDateFormat class is thread-safe (at least for methods such as format(), which you might not expect to mutate state!). This is not true; SimpleDateFormat is not thread-safe, and format() does mutate state. From the javadoc:

Date formats are not synchronized. It is recommended to create separate format instances for each thread. If multiple threads access a format concurrently, it must be synchronized externally.

Suggestions on handling synchronization:

N.B. In general, you should be very careful when using ThreadLocal storage, especially when using thread pools (your data won’t be automatically garbage collected and may be visible to other Threads—a security risk) or when storing references to Thread objects in ThreadLocal storage (which might confuse the GC). However, in this case, we should be okay.

Fully Interactive JTables (aka Mouseover Editing)

Thursday, May 17th, 2007

What sucks about JTables? Everything, of course—but that’s a developer’s perspective. To the user, cell editing is rough around the edges: when and where to click, and how many times—it’s never perfectly clear. Cells in a table just don’t provide the mouseover feedback that regular components do. If only a JTable behaved like a bunch of components thrown into a giant GridBag or TableLayout

mouseover-screenshot.png

Mouseover Editing simulates just that. The idea is to attach a MouseListener to the JTable and call editCellAt(row, col) whenever the cursor moves over a new cell. In other words, even though only one cell in a table can be fully interactive (the editing cell) at any given time, as long as we keep moving that cell to stay underneath the user’s cursor, the whole table will appear to be fully interactive. If done correctly, this will appear to the user as though he’s interacting with a bunch of real components (rather than rendered stamps) inside a giant Grid/GridBag/TableLayout.

Most importantly, the user will get mouseover feedback about which cells are editable, and how to edit them. Checkboxes, buttons, and comboboxes (if the L&F supports it) will highlight to indicate press-ability and the cursor will turn to a text caret when hovering over cells that contain textfields. When done correctly, the effect is nearly seamless and very satisfying.

Here’s a webstart demo. Read on for the solution in code.

(more…)

Unicode and happy user experiences

Tuesday, March 6th, 2007

Everyone agrees that it’s crucial to do validation on user input so that, among other things, your application never tries to write a value that’s too long into a database field with a specific limit. Users of your application shouldn’t, however, be left guessing whether the megabyte they pasted (and you know they will) into the eensy-teensy text field really got saved to the database or not. So you should limit the text field itself so they get immediate feedback, rather than via some Johnnie-come-lately error message, or worse, a bunch of text gets dropped in the bit bucket.

One fairly well established technique is to write a DocumentFilter, and when insertString() or replace() is called, validate the added text and truncate as necessary to ensure the database field length is not exceeded.

Now the fun part. What happens when you try to store your comments on N’Ko, Mongolian, Bopomofo (phonetic markers, now commonly used as an input character set for Mandarin), or even ancient Viking runes? You get two choices, store as ASCII or ISO-8859-1 (aka Latin-1), or whatever, and you lose data. Oops. Or convert to UTF-16 or UTF-8. Hm. Wait a minute, now the value (in bytes) is somewhere between 1-3 times as many bytes as the original String length. So, how do you limit the text field to the number of bytes the database will permit? If you picked UTF-16, it’s pretty simple, divide the database limit by two. But it’s pretty wasteful of space, usually. On the other hand, you can’t predict exactly how many bytes the UTF-8 representation needs until you try it out.

The following algorithm will produce a String which, if converted to supplied Charset, will be no more than maxBytes in length. It could be less, depending on the charset chosen and the text being trimmed. This happens because it removes whole characters at once, which may trim several bytes, jumping you from 1 byte over the limit to two under.


As a final note (thanks to the comments by one of our faithful and numerous readers), we would like to acknowledge that we have indeed ignored the existence of the supplementary planes of Unicode mappings, sticking to the Basic Multilingual Plane in this example. This avoids the even more intricate hassle of dealing with surrogate pairs. If one of these rather obscure character encodings (Byzantine Music Symbols, Phoenician, or my personal favorite, Deseret [editors note: yeah, I didn't know what it was either. Wikipedia to the rescue], for example) should appear, it’s possible that they might be truncated mid-character. According to the Unicode standard, this is an error, but also a very unlikely situation to encounter. Free Palantir t-shirt to the first person who posts a working example that properly deals with surrogates.