Serialio

The difference between SerialPort and javax.comm.SerialPort

People frequently ask if SerialPort provides support for javax.comm.SerialPort. Yes, absolutely. This information will help you determine if you wish to use the superior SerialPort API directly, or the javax.comm.SerialPort API. SerialPort provides maximum flexibility (evident by the fact that javax.comm.SerialPort is implemented entirely using SerialPort). The SerialPort API was shipping commercially for about 18 months before Sun introduced javax.comm.SerialPort. As diagrammed below, the Serialio.com implementation of javax.comm.SerialPort was built completely using the SerialPort API and is based on the Comm API 2.0 (the first release in spite of the version number).

Benefits Unique to SerialPort

SerialPort provides a very flexible solution, and provides a consistent API across all devices.

Did you know you may have to code your solution twice? If you use javax.comm.SerialPort you may have to recode your solution if you want to run it on MIDP. If you use CommConnection, you may have to recode your solution to run on a non-MIDP environment. If you code your solution with the SerialPort API, use the same code on both MIDP and non-MIDP environments.

The original SerialPort design was robust enough to port to J2ME MIDP on WME. Developers using the SerialPort API can use the same powerful API for all their target devices, from Super Computer class to MIDP class devices. The javax.comm API design is insufficient for such flexibility; therefore the CommConnection interface was developed to replace javax.comm on MIDP. The CommConnection API is even more restrictive than the javax.comm.SerialPort API, and requires the developer to learn another API only to be limited by its design.

API FeatureSerialPortjavax.comm.SerialPort
Source code availableYesNo
Precise control of event loopYesNo
Allows pollingYesNo
Supports platform dependent featuresYesNo
Advanced Power Management (APM)*YesNo
APM Battery life statusYesNo
APM CF slot status (detect CF serial port)YesNo
APM Wakeup detectionYesNo
Flexible ‘isSupported’ cross-platform feature implementationYesNo
Selectable blocking at Java or Native levelYesNo
Supports transmit timeouts**YesNo
Works on MIDPYesNo
ExtendableYesNo
Continued enhancement since inceptionYesNo
*Provided on several platformsYesNone

**javax.comm.CommPort provides the method enableReceiveTimeout, however, does NOT provide the parity method enableTransmitTimeout. This means that threads that transmit data using javax.comm.SerialPort, can potentially lockup. This can occur for example, when hardware flow control is selected, but no hardware is present, or the client has flow control disabled indefinitely.

JavaPOS Support

The Serialio.com implementation of javax.comm.SerialPort supports JavaPOS.

Limitations of the Comm API 2.0 Design

When Sun released the first early version of the Comm API Solutions Consulting implemented that API using SerialPort and reported these design problems with the API. Many of the issues reported were apparently ignored by Sun, as those issues still remain with the Comm API in the initial release (long after the issues were reported).

There should be some way to determine if some set/is???, and notifyOn??? API methods are supported. The SerialPort product does this with the ‘isSupported’ methods. Since the Comm API does not provide this feature, it should at least define some of the methods to throw unsupportedCommOperationException. For example, Macintosh hardware does not have DSR or RTS hardware so isDSR and setRTS make absolutely no sense on the Mac. Likewise, notifyOnCD, and notifyOnRingIndicator make no sense on the Mac. When using our javax.comm.SerialPort implementation on a platform that does not support one of these features (e.g. setDTR on UnixWareIA32) a message similar to the one shown below will appear on the console:

The correct thing to do is to throw an UnsupportedCommOperationException; however, Sun’s API does not define this. For source code compatibility with Sun’s API, we can not do it the correct way. You should contact Sun and encourage them to fix their API. (We suggested they do this in early 1998). It also seems odd that methods like setDTR, setRTS, and sendBreak are not declared to throw an IOExcepion.

Note that the Comm API defines isDTR and isRTS methods. From the serial hardware level, these signals are write-only, so these methods can be misleading. Additionally,  these methods make no sense on some platforms.

The Comm API provides no method for polling (or to disable event generation). For many applications this is not a problem, however, for some high-performance applications, the overhead of event creation/propagation can be limiting. Note also that some platforms may not provide a mechanism to generate interrupts for all of the events defined in the Comm API. This means that a thread must be dedicated to polling at the Java level to generate the required events.

Dynamic port configuration is a questionable cross-platform strategy. In the Comm API when the methods setSerialPortParams and setFlowControlMode are called, the driver must reconfigure an open port. Performing port configuration changes without resetting the port can be risky since some OS’s do not support the concept, or can have subtle bugs associated with it. (This is one of the reasons the Solutions Consulting SerialPort API uses the SerialConfig object)

The file name UnsupportedCommOperationException.java is too long for the Mac file system.

The Solutions Consulting SerialPort product has none of these limitations. In fact, our implementation of the Comm API is done with SerialPort reflecting SerialPort’s robust design. By using SerialPort the developer is provided with maximum flexibility since the Comm API or the SerialPort API can be used.

Installation

Install SerialPort per instructions. SerialPort must be installed for the Comm API to function.

Update any Serialio files included with the Comm API package (e.g., SerialPortLocal.java, SerInputStream.java) and rebuild the Serialio class file(s).

Here are two common ways to install the Comm API classes

You can use the JAR file as follows:

1) Add the jspComm.jar file to the CLASSPATH. For example on Windows if you have jspComm.jar in c:\jsp then CLASSPATH=…;c:\jsp\jspComm.jar;…

Or do it this way if you have the separate classes:

1) Create a directory named javax.comm (case sensitive) that is a subdirectory of where the main Java Comm API classes will exist e.g. on Windows create the directory C:\jsp\javax\comm

2) Copy the Comm API class files into the directory created in 1).

3) Add the parent directory of the javax.comm directory to the CLASSPATH. For this example on Windows CLASSPATH=…;c:\jsp;…

Port Enumeration

Note enumeration requires that the OS provide some type of ‘registry’ functionality, this is not provided on all platforms. The Solutions Consulting implementation is very flexible in that it provides the developer the direct ability to add ports in case the developer does not wish to rely on enumeration. This is done as follows:

CommPortIdentifier.addPortName(devName, CommPortIdentifier.PORT_SERIAL, null);

Where devName is the device name (e.g. “COM2”, “/dev/tty1”, “Modem Port”). Note that the Driver parameter is set to null. This indicates you simply want to add a name to the list and use the default (Solutions Consulting) driver.

You can see an example of this in the Comm API version of TermTest.java.

You can also hard code device names into the list by modifying JSPDriver.java.

Events

The term event is misleading in this context. Those who have worked with serial ports at the UART level might immediately think that this means these would be hardware interrupt driven. This certainly makes sense, if the platform serial port drivers supported such an interface; unfortunately, many do not. Even for those platforms that do provide some event type of event interface, there is no guarantee that the driver itself is not polling the hardware.

Although we have no access to Sun’s implementation of javax.comm, it is our belief that this implementation is similar to ours in that it has a thread that does the polling and delivery of events. If you dump out Sun’s comm.jar (jar -tvf comm.jar) you will see this class:

com/sun/comm/NotificationThread.class

If you dump out jspComm.jar in SerialPort you will see this class:

javax/comm/SerialPortEventTask.class

We believe that these are functionally equivalent. As for performance, our last test showed the implementation provided with SerialPort was about 2% faster than Sun’s on WinNT. Considering the implementation we provide, sits on top of the SerialPort API, this is quite good. So even if we are wrong, and Sun has gone to great links to use ‘events’ in Win32 (i.e., Overlapped IO) then our polling strategy is still faster. As for polling directly with the SerialPort API (i.e., doing essentially what javax.comm.SeralPort does, but directly in the application), SerialPort will happily run 96 port (or more) on a single machine.

Polling

The fact is polling can be more efficient than the event model provided by the javax.comm especially for fast-changing events. Consider that each time an event is produced, a JNI interface call, a JVM system call, memory allocation (which may create additional overhead by creating more work for the garbage collector), then the event must be posted (in javax.comm, this is a method call to the listener). In the polling scenario, there is only a method call from the JVM to the native driver.

Example Code

All the serial port example code that ships with the 2.0 release of the Comm API. Has been tested with the Solutions Consulting implementation. Depending on your VM, when you run the SimpleWrite.java example you may need to use CTL-C to stop the program. You can avoid this by adding the following one line of code to SimpleWrite.java where the code exits.

System.exit(1); //proper exit

Sun’s SerialDemo example: Note when using this example program it may appear that it will not work when trying to communicate with a modem. This is NOT a problem with Solutions Consulting javax.comm.SerialPort implementation. There are two issues here. First, some modems (and other devices) will not respond unless the DTR is set, since SerialDemo does not provide a hook to set DTR your modem will not send a reply. Secondly, if you note that SerialDemo works with your modem on JDK 1.1.x, but not JDK 1.2.x, then this is an issue of a change that Sun made to the way the Enter key event is handled. In JDK 1.2.x the Enter key does not send the CR, and the modem will not respond until it sees a CR. You should use JavaTerm, not SerialDemo, as JavaTerm provides smart and flexible CR control as well as the ability to set DTR.