If this is for a single app (i.e. a main and couple of threads), JMS is overkill.
The basics of this is a simple queue (of which Java has several good ones, BlockingQueue waving its hand in the back over there).
The serial port reads its data, formats a some relevant message object, and dumps it on a central Message Queue. This can be as simple as a BlockingQueue singleton.
Next, you'll need a queue listener/dispatcher.
This is a separate thread that sits on the queue, waiting for messages.
When it gets a message it then dispatches it to the waiting "widgets".
How it "knows" what widgets get what is up to you.
It can be a simple registration scheme:
String messageType = "XYZ";
MyMessageListener listener = new MyMessageListener();
EventQueueFactory.registerListener(messageType, listener);
Then you can do something like:
public void registerListener(String type, MessageListener listener) {
List<MessageListener> listeners = registrationMap.get(type);
if (listeners == null) {
listeneres = new ArrayList<MessageListener>();
registrationMap.put(type, listeners);
}
listeners.add(listener);
}
public void dispatchMessage(Message msg) {
List<MessageListener> listeners = registrationMap.get(type);
if (listeners != null) {
for(MessageListener listener : listeners) {
listener.send(msg);
}
}
}
Also, if you're using Swing, it has a whole suite of Java Bean property listeners and what not that you could leverage as well.
That's the heart of it. That should give you enough rope to keep you in trouble.