Write Once, Communicate… Nowhere?
Back in August I made the off-hand comment "thank goodness for RXTX" when talking about communicating with serial ports using Java. I've been meaning to revisit that topic in a bit more detail, and now is as good a time as any.
- Forrester Study: The Total Economic Impact of VMware View
- Operational Insight for Running IT at the Speed of Business
I can't decide if I love Java or hate it. I've written books on Java, produced a special DDJ issue on Java, and was a Java columnist for one of our sister magazines, back when we had those. I even edited the Dobb's Java newsletter for a while. There must be something I like. However, I always find I like it more in the server and network environment. For user interfaces, I tend towards Qt these days. For embedded systems, I haven't warmed to Java, even though there are a few options out there, some of which I will talk about sometime later this year.
The lines, however, are blurring between all the different kinds of systems. You almost can't avoid Java somewhere. The Arduino uses Java internally. So does Eclipse. Many data acquisition systems need to connect over a network and Java works well for that, either on the device or running on a host PC (or even a Raspberry Pi).
Another love-hate relationship I have is with the serial port. My first real job was with a company that made RS-232 devices, so like many people I have a long history with serial communications. We keep hearing that the office is going paperless and serial ports are dead. Neither of those seems to have much chance of being true anytime soon. Even a lot of USB devices still look like serial ports, so it is pretty hard to completely give up on the old standard, at least for now.
It isn't that Java doesn't support the serial port. Sun released the Java Communications API in 1997 and Oracle still nominally supports it. It covers using serial ports and parallel ports (which are mostly, but not completely, dead). The problem has always been in the implementation.
When reading the official Oracle page, I noticed that there are reference implementations for Solaris (both SPARC and x86) and Linux x86. I guess they quit trying to support Windows, which is probably a good thing. The last time I tried to use the Windows port, it suffered from many strange errors. For example, if the library wasn't on the same drive as the Java byte code, you couldn't enumerate ports. Things like that.
Pretty much everyone I know has switched to using an open project's implementation, RXTX. The Arduino, for example, uses this set of libraries to talk to the serial port (even if the serial port is really a USB port). The project implements the "official" API and requires a native library, but works on most flavors of Windows, Linux, Solaris, and MacOS. The project is pretty much a drop-in replacement unless you use the latest version.
The 2.1 series of versions still implement the standard API (more or less), but they change the namespace to gnu.io.*. If you use the older 2.0 series, you don't have to even change the namespace from the official examples.
Speaking of examples, instead of rewriting code here, I'll simply point you to the RXTX examples if you want to experiment.
One thing I did find interesting, however, is that RXTX uses JNI to interface with the native library (which, of course, varies by platform). I have always found JNI to be a pain to use (although, you don't use JNI yourself if you are just using RXTX in your program). I much prefer JNA. JNA is another way to call native code in Java programs, and it is much easier to manage. Granted, you can get slightly better performance in some cases using JNI, but in general, modern versions of JNA perform well and typically slash development costs.
I did a quick search to see if there was something equivalent to RXTX but using JNA. There is PureJavaComm. Even if you don't want to switch off RXTX, the analysis of the design of PureJavaComm at that link is interesting reading. Using JNA, the library directly calls operating system calls and avoids having a platform-specific shared library, which is a good thing for many reasons.
Have you managed to dump all your serial ports? Leave a comment and share your experiences.