To my utter surprise, I won a Google notebook. Perhaps it is my wife who won. :-)
Thank you, Google!
To my utter surprise, I won a Google notebook. Perhaps it is my wife who won. :-)
Thank you, Google!
At Agile Advice a clear example that agile teams are self-organizing: The BIG Difference Between Agile Teams and Project Teamd.
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;
}
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
WEB-INF/lib so Jetty cannot find them there with its classloader, forcing delegation to the system classloader.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.
While setting up a new Cygwin installation I ran cron-config and found this nugget: Switching the user context without password, Method 1: Create a token from scratch, Switching the user context without password, Method 2: LSA authentication package, and Switching the user context without password, Method 3: With password. Does Windows really need to be this hard?
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.
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.
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.
I keep wasting time rediscovering the right Maven dependencies for Spring Framework. I could have just read Keith Donald's blog post.
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.
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.
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.
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.
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?
Helpful sysadmin tip from Jason White (jasonjgw), philosopher cum Linux expert, on finding broken symlinks.
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.
Like a programming René Magritte, Robert Smith tells us that LISP does not have lists and it does not have parentheses. To be fair, he is right.
Sri Lankan Hiranya Jayathilaka posts on Java 6 GC algorithms and tuning. This goes in my bookmarks.
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.
A great post from Jonathan Rasmusson (author of The Agile Samurai) on successful project inception. I wish I had his slide deck.
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.
Danilo Campos shows by examples how to tempt good programmers to work for you.
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:
System.currentTimeMillis() and average over long numbers of runs; many problems here.System.nanoTime() and time individual events. Great, but the Javadoc is very scary for multi-threaded code.sun.misc.Perf.highResCounter() (many non-official references for this.)gettimeofday().After months of hitting my head I wised up and looked into the JDK6 C++ source code. Surprise!
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.)
Just use System.nanoTime() and stop worrying so much. It is fine for microsecond timing—even across threads—just RTFM and ignore javadoc.
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.