Wednesday, February 09, 2011

I won!

To my utter surprise, I won a Google notebook. Perhaps it is my wife who won. :-)

Thank you, Google!

Friday, January 14, 2011

Teach Spring to use per-listener JMS destination queue names, not hard-coded ones

This took some experimenting.

My problem: I am using Spring Framework 3.0 JMS support to wire up a JMS listener container to listener beans. The XML syntax looks like:

<jms:listener-container>
    <jms:listener
            destination="hard-coded-queue-name"
            ref="listener"/>
</jms:listener-container>

This XML is distributed with each program instance. Not a single single server or client instance but a server cluster or client farm: each one of these needs a unique destination so JMS routes correctly.

My first try fixed the uniqueness problem but was less than fully usable:

<jms:listener-container>
    <jms:listener
            destination="#{T(java.util.UUID).randomUUID().toString()}"
            ref="listener"/>
</jms:listener-container>

This suffers excess cleverness. Each listener gets a random UUID for its destination. But, how does the listener refer to this queue name when filling in a JMS reply-to field, or logging or other purposes?

The real answer is to ask the listener for a destination, no produce one externally:

<jms:listener-container>
    <jms:listener
            destination="#{listener.inbox}"
            ref="listener"/>
</jms:listener-container>

And in the listener:

private final String inbox = UUID.randomUUID().toString();

public String getInbox() {
    return inbox;
}

Wednesday, January 12, 2011

JacORB in Jetty

There is a nasty JVM bug with class verification when you use JacORB in a webapp in Jetty. The issue only occurs when you use a custom classloader (as Jetty does) and load the CORBA in JacORB which replace the default implementation in the JDK. The characteristic message is:

java.lang.VerifyError: (class: org/jacorb/orb/Delegate, method: getReference signature: (Lorg/jacorb/poa/POA;)Lorg/omg/CORBA/portable/ObjectImpl;) Incompatible object argument for function call

The problem has been ongoing since at least 2004 that I can tell from googling without much progress. It happens to other containers than Jetty.

The solution is to ensure the JacORB classes are loaded with the system classloader, not the custom classloader in the webapp container. The only way this can happen is

  1. The jacorb jar and its dependencies are not in WEB-INF/lib so Jetty cannot find them there with its classloader, forcing delegation to the system classloader.
  2. The system classloader has the jacorb jar and its dependencies prepended to the boot classpath so they can take precedence over the default CORBA implementation in the JDK.

As I use maven, this means my POM for building the war includes:

<dependency>
    <groupId>jacorb</groupId>
    <artifactId>jacorb</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-core</artifactId>
    <version>${ch.qos.logback.version}</version>
    <optional>true</optional>
    <scope>provided</scope>
</dependency>

(I am relying on a parent pom to define versions for these)

And my command line to run Jetty from maven with the excellent jetty-maven-plugin (I am on Windows for this project):

$ MAVEN_OPTS='-Xbootclasspath/p:jacorb-2.3.1jboss.patch01-brew.jar\;slf4j-api-1.6.1.jar\;logback-classic-0.9.26.jar\;logback-core-0.9.26.jar -Dorg.omg.CORBA.ORBClass=org.jacorb.orb.ORB -Dorg.omg.CORBA.ORBSingletonClass=org.jacorb.orb.ORBSingleton' mvn jetty:run-war

I am glad this is finally behind me; a day and a half I could have better spent playing elsewhere.

Monday, December 13, 2010

Correct SLF4J logger wrapping

The problem

As much as the idea pains me, I find it necessary to wrap the well-known logger wrapping framework SLF4J. Why?

The framework author goes to lengths to support JDK1.4 in the API, a reasonable goal for a broadly used API. The result is signatures such as this:

public interface Logger {
    /* ... */

    void info(String msg);

    void info(String format, Object arg);

    void info(String format, Object arg1, Object arg2);

    void info(String format, Object[] args);

    void info(String format, Throwable t);

    /* ... */
}

That's it. You get 0-2 parameters to put into your formatted mesage. If you have more than two parameters you are out of luck. An no mixing exceptions with formatted messages. However, were SLF4J coded against JDK5 the API might become:

public interface Logger {
    /* ... */

    void info(String msg, Object... args);

    /* NB - ellipsis parameter must be last. */
    void info(Throwable t, String msg, Object... args);

    /* ... */
}

Yes, both simpler and more functional. But not a an option without maintaining two versions of the code base or losing backwards compatibility.

A solution

In the past I worked around this with some pretty wild solutions, but today I ran across Wrapping the slf4j API, posted in August.

I can fix SLF4J for JDK5 myself:

public class LoggerBase {
    private static final String FQCN = LoggerBase.class.getName();

    private final Logger logger;

    public LoggerBase(Class thisClass) {
        this.logger = getLogger(thisClass);
    }

    public LoggerBase(String loggerName) {
        this.logger = getLogger(loggerName);
    }

    /* ... */

    public void info(String format, Object... args) {
        info(null, format, args);
    }

    public void info(Throwable thrown, String format, Object... args) {
        if (!logger.isInfoEnabled())
            return;

        if (logger instanceof LocationAwareLogger)
            ((LocationAwareLogger) logger)
                    .log(null, FQCN, INFO_INT, format, args, thrown);
        else
            logger.info(arrayFormat(format, args).getMessage(), thrown);
    }

    /* ... */
}

Hopefully SLF4J presents a solution for this (perhaps a separate JDK5 jar) so I can drop my warped logger wrapper wrapping class.

Scala for the Java programmer

Dave Copeland wrote a wonderful wiki, Another Tour of Scala, around the official A Tour of Scala. In Dave's version he presents Scala topics from the perspective of the Java programmer, explaining how Scala features looks coded in Java and commenting on usefulness and scrutability.

This is the best bootstrap into Scala resource for Java programmers (like me) I have seen. Thanks, Dave.

Tuesday, December 07, 2010

Jumping off into Spring with Maven

I keep wasting time rediscovering the right Maven dependencies for Spring Framework. I could have just read Keith Donald's blog post.

Wednesday, December 01, 2010

A new leaf

Today was my last day at JPMorgan Investment Bank where I worked with a great group of people in equities trading. I will miss them.

In a week or two I start my first day at Macquarie Group here in Houston at the energy/gas trading desks and turn over a new leaf. Leaf here means a page of a book. So I am beginning a new part in the diary of my life, a book I hope never closes.

Tuesday, November 30, 2010

Programming when speed counts

A clever fellow at my work posted a link to Numbers everyone should know. When speed matters, you need to know what is cheap and what is dear.

Dear Oscar Wilde said "What is a cynic? A man who knows the price of everything and the value of nothing." But Alan Perlis countered, "LISP programmers know the value of everything and the cost of nothing."

Learn your costs, the value you get for them, and the price you pay.

Saturday, November 27, 2010

Getting started with Ruby on Windows from Felix Raab

Felix Raab posts Ruby Development on Windows, a practical getting started guide. I've seen similar instructions elsewhere. This one is a little different in that he walks you through setting up Microsoft ConsolePowerShell instead of Cygwin. I want to give this a try.

Take that, Mike

This post is gentle ribbing at the best developer I work with at JPMorgan: Mike Doberenz. He is a big Eclipse fan, I am an IntelliJ fan. It's a little like the Emacs-v-vi flame war except that there is an actual argument in favor of Eclipse.

Martin Mikkelborg writes a helpful post on preferring IntelliJ to Eclipse for Android development.

As Mike and I often observe, folks like me feel IntelliJ is better than Eclipse. But I also believe the development model of Eclipse is likely to win out in the long run (units arbitrary):

However, JetBrains has done brilliant work lately in bringing out a free, community edition and keeping their API accessible to plugin authors. It will be interesting to watch the contest of editors over the next few years.

Here is JetBrains explaining how they succeed in an interview with Michael Hunger.

Saturday, November 20, 2010

Looking forward to IntelliJ IDEA X

I'm looking forward to IntelliJ IDEA X (10), due real soon now. Typical of the incremental improvements every release has is How to Run a Single Inspection in IDEA X?.

I've been running the preview releases for a while now, and have noticed to my delight that version X is generally faster and lighter-weight than 9 or 8. Faster, better — what's not to like?

Find broken symlinks

Helpful sysadmin tip from Jason White (jasonjgw), philosopher cum Linux expert, on finding broken symlinks.

Thursday, November 18, 2010

Great agile advice from Improving Enterprises

Devlin Liles of Improving Enterprises writes of his type at Tyson: Lessons Learned: A Developer Retrospective. My favorite piece of advice is the first one: Always Say Yes:

If the user wants you to write a program that will send unmanned spaceships to hundreds of planets and safely get them back. Say yes. The time, money, effort, and return on investment should be the determining factors for a request, not the developers opinion.

I'd love to build that project.

Thursday, November 11, 2010

Monday, November 08, 2010

Great management example: origins of Java

I found a real gem in this e-mail exchange featuring Patrick Naughton. This part jumped out at me (written by Sean Luke):

As I remember my Java history Patrick Naughton the gentleman who got the ball rolling was about to quit Sun and join up with NeXT. He happened to be on the same intermural hockey team as Scott McNealy. Scott told him to hold off, write what he thought was wrong with Sun before he left. Patrick didn't leave and was one of the original Oak people.

This is amazing! McNealy was the right kind of manager. Naughton discussed his interests in leaving Sun with McNealy, McNealy asked for feedback and helped Naughton start a new project.

The Internet is filled with tales of the other kind of boss.

Also, I should join my boss' team.

Saturday, November 06, 2010

Project inception

A great post from Jonathan Rasmusson (author of The Agile Samurai) on successful project inception. I wish I had his slide deck.

Thursday, October 28, 2010

Sunday, October 17, 2010

More on more uses for Iterables

Rúnar Bjarnason writes Scalaz Tutorial: Enumeration-Based I/O with Iteratees, an all-singing, all-dancing approach to composable iterators for I/O in Scala. This is a much fuller treatment of I/O iterators than my post, More uses for Iterables.

Wednesday, October 13, 2010

Java ain't got no rhythm, but can it keep time?

I need sub-millisecond timing in Java; I want to measure events in the low microsecond range. What to do? My options seem to be:

  1. Use System.currentTimeMillis() and average over long numbers of runs; many problems here.
  2. Use System.nanoTime() and time individual events. Great, but the Javadoc is very scary for multi-threaded code.
  3. Try out sun.misc.Perf.highResCounter() (many non-official references for this.)
  4. Write our own JNI call for gettimeofday().

After months of hitting my head I wised up and looked into the JDK6 C++ source code. Surprise!

The C++ source

Drilling down points me to os::javaTimeNanos() (nanoTime), os::elapsed_counter() (highResCounter), and os::javaTimeMillis() (currentTimeMillis). On Linux these are:

System.currentTimeMillis()

jlong os::javaTimeMillis() {
  timeval time;
  int status = gettimeofday(&time, NULL);
  assert(status != -1, "linux error");
  return jlong(time.tv_sec) * 1000  +  jlong(time.tv_usec / 1000);
}

System.nanoTime()

jlong os::javaTimeNanos() {
  if (Linux::supports_monotonic_clock()) {
    struct timespec tp;
    int status = Linux::clock_gettime(CLOCK_MONOTONIC, &tp);
    assert(status == 0, "gettime error");
    jlong result = jlong(tp.tv_sec) * (1000 * 1000 * 1000) + jlong(tp.tv_nsec);
    return result;
  } else {
    timeval time;
    int status = gettimeofday(&time, NULL);
    assert(status != -1, "linux error");
    jlong usecs = jlong(time.tv_sec) * (1000 * 1000) + jlong(time.tv_usec);
    return 1000 * usecs;
  }
}

sun.misc.Perf.highResCounter()

jlong os::elapsed_counter() {
  timeval time;
  int status = gettimeofday(&time, NULL);
  return jlong(time.tv_sec) * 1000 * 1000 + jlong(time.tv_usec) - initial_time_count;
}

And:

void os::init(void) {
  char dummy;   /* used to get a guess on initial stack address */
//  first_hrtime = gethrtime();

  // With LinuxThreads the JavaMain thread pid (primordial thread)
  // is different than the pid of the java launcher thread.
  // So, on Linux, the launcher thread pid is passed to the VM
  // via the sun.java.launcher.pid property.
  // Use this property instead of getpid() if it was correctly passed.
  // See bug 6351349.
  pid_t java_launcher_pid = (pid_t) Arguments::sun_java_launcher_pid();

  _initial_pid = (java_launcher_pid > 0) ? java_launcher_pid : getpid();

  clock_tics_per_sec = sysconf(_SC_CLK_TCK);

  init_random(1234567);

  ThreadCritical::initialize();

  Linux::set_page_size(sysconf(_SC_PAGESIZE));
  if (Linux::page_size() == -1) {
    fatal1("os_linux.cpp: os::init: sysconf failed (%s)", strerror(errno));
  }
  init_page_sizes((size_t) Linux::page_size());

  Linux::initialize_system_info();

  // main_thread points to the aboriginal thread
  Linux::_main_thread = pthread_self();

  Linux::clock_init();
  initial_time_count = os::elapsed_counter();
  pthread_mutex_init(&dl_mutex, NULL);
}

(The net effect is to normalize to 0-time at JVM boot rather than the epoch.)

The solution

Just use System.nanoTime() and stop worrying so much. It is fine for microsecond timing—even across threads—just RTFM and ignore javadoc.

Sunday, October 10, 2010

Elena Yatzeck promotes the agile Army Leadership Field Manual

A positive, fascinating post from Elena Yatzeck on agile leadership as taught in the U.S. Army Leadership Field Manual. The only military members of teams immediate to me are presently serving overseas. Looks like I missed out.