Saturday, February 20, 2010

CopyTo...Pastebin (and others) Plug-In for Eclipse

The situation

Do you hang out in IRC channels often? And do you use pastebin.com or other services to show the users snippets of your source code that illustrates a problem you have? Then you no longer need to switch between your Eclipse IDE, a webbrowser and the IRC chat window.

A small solution that can save time

I have finished today the first alpha version of a small Eclipse Plugin that adds a new menu and toolbar button to the Eclipse Workbench.

In its basic version it allows you to click any resource in the Package/Project Explorer and copies the content of the resource to the pastebin service of your choice. I have created some default configurations for the most used ones. The one working most stable is "pastebin.com". "Codepad.org" is experimental and "pastebin.ca" returns invalid URLs in its JSON response. I have contacted the author of the service already. They merely serve as samples and I am sure most users will just use "pastebin.com". And if you choose to only install one "Target", like "pastebin.com" then there will be no submenu but you can directly select "Copy to pastebin.com" as shown below:

The targets are configurable in the preferences and are persisted in your Eclipse configuration location. That means you do not have to re-configure the targets for each workspace (a feature I would wish for a lot of Eclipse options to be the default).

You can also install the "CopyTo JDT" feature which allows you to copy Java methods or classes from the Outline view, the source editor or the Package Explorer. For "pastebin.com" this will also enable Java syntax highlighting. Since the whole plugin code is available at github others could contribute specialized modules for Ruby, PHP, etc.

After the selected content was sent to the target and the target returned a valid redirection URL (or JSON response, that contains a URL) there are several actions possible. The default action is the "Copy to clipboard" action which is supplied by default.

You can install additional "PasteTo" actions like for direct pasting into your favorite IRC client.
I have implemented support for Eclipse ECF (IRC) Chats (newest ECF 3.2 required) and some experimental for my favorite IRC client that comes with Miranda-IM for Windows. You can see that in action in the video below:

Of course having many actions will slow down your workflow so there will be a mechanism to select a default action and display the dialog only if you hold down the "CTRL" key. If there is only one action available, then no dialog will be displayed. And for the "Copy to clipboard" action you can disable the initial warning it gives you when the clipboard contains (probably) valuable data.

Unfortunately there is no way to get the "CopyTo" menu at a consistent place in popups and main menu. That's because some popup menus do not provide anchors or group-markers. And sometimes the group marker is below the seperator (Text editor popup). If anyone has an idea how to solve that placement problem he can say or change the source :)

Test it out

I am already using the plugin in my daily Eclipse life and if you want to give it a test run you can add the Update URL http://pke.github.com/CopyTo/update/ to your Eclipse Installation. Don't forget to select at least the main feature and the "pastebin.com target". The update manager will warn you that the features are not signed but you can safely ignore the message (if you trust my code :) You need to restart the workbench to get the pastebin.com configuration visible to "CopyTo". That's currently an known issue.

I would like to hear from you, especially if you have suggestions for the workflow.

Saturday, February 13, 2010

ServiceRunnable - Easier use of OSGi service trackers

The situation

Sometimes you cannot use the beauty of DS (ie. in Eclipse Workbench classes, that are instantiated by the Workbench) and have to revert back to the next best thing in the OSGi world when working with services. The ServiceTracker. If you want to use a certain service in your command handlers execute method you would have to create a service tracker, query it for the service, and call the services method like this:
// Somewhere in your code
private static final ServiceTracker tracker = new ServiceTracker(
  FramworkUtil.getBundle(MyClass.class,
  EventAdmin.class.getName(),
  null) {
    { open(); }
  };

Object execute(ExecutionEvent event) {
  EventAdmin eventAdmin = (EventAdmin)tracker.getService();
  if (eventAdmin != null) {
    eventAdmin.postEvent(new Event("EVENT/TOPIC", (Map)null));
  }
  return null;
}
Or lets say you have a service that returns a collection of items:
Collection listAllCars() {
  CarService carService = (CarService)carServiceTracker.getService();
  if (carService != null) {
    return carService.findAll();
  }
  return Collections.emptyList();
}
As you can see, there is always boyer-plate code involved (and I am already using a shortcut to open the tracker) including null checking and we have not even looked on fall-back code, that should be executed if the service is not available. Let's say we want to log something with the OSGi LogService but if its not available we will just print to the standard output stream.
public static void log(int level, Throwable t, String message, Object... args) {
  final String text = String.format(message, args);
  LogService logService = (LogService)tracker.getService();
  if (logService != null) {
    logService.log(level, text, t);
  } else {
    System.out.println(text);
  } 
}
Again we would have to create the the service tracker and check if the service is available. What, if we could do that all in one call?

Introducing Trackers

We could have a small helper class "Trackers" that creates service trackers for use automatically and executes a piece of code depending on the availability of the requested service. From the JDK we all know the Runnable interface. We will just take the idea a step further and give its run method a parameter, much like Eclipse's ParameterizedRunnable. But instead of doing it the Java 1.4 way we use generics like this:
public interface ServiceRunnable<T> {
  void run(T service);
}
The code in the run() method is only executed if there is a Service that publishes itself with the type "T". Our helpers class static method would look like this:
public final class Trackers {
 public static <T> void run(Class<T> serviceClass, ServiceRunnable<T> runnable) {
   T service = getService(serviceClass);
   if (service != null) {
     runnable.run(service);
   }
 }
}
And we would call it like this:
Trackers.run(EventAdmin.class, new ServiceRunnable<EventAdmin>() {
  void run(EventAdmin service) {
    service.postEvent(new Event("EVENT/TOPIC", (Map)null));
  }
});

Who tracks the services?

Above you saw the not further explained call to "getService(serviceClass)". That's where Trackers fetches the service. And in case there is no tracker for it yet, it will create one for this service. It keeps a map of ServiceTracker, on for each service class you request.
private static <T> T getService(final Class<T> serviceClass) {
  ServiceTracker tracker = trackers.get(serviceClass);
  if (null == tracker) {
    tracker = createTracker(serviceClass);
    trackers.put(serviceClass, tracker);
  }
  // Safe to cast here, since OSGi already checks the returned service.
  return (T)tracker.getService();
}
Creating the tracker is pretty standard:
private static <T> ServiceTracker createTracker(final Class<T> serviceClass) {
  ServiceTracker tracker = new ServiceTracker(
    FrameworkUtil.getBundle(Trackers.class).getBundleContext(),
    serviceClass.getName(),
    null);
  tracker.open();
  return tracker;
}

Some Sugar

Remember our sample about the car listings? Rewriting it using the new Trackers class it would like this:
Collection<Car> listAllCars() {
 Collection<Car> cars = Collections.emptyList();
 Trackers.run(CarService.class, new ServiceRunnable<CarService> {
   void run(CarService service) {
     cars = service.findAll();
   }
 });
 return cars;
}
Looks ok, but can be improved. It would be nice if we could return a value from Trackers.run() so that our code would look like this:
Collection<car> listAllCars() {
 return Trackers.run(CarService.class, new ServiceRunnable<CarService, Collection<Car>> {
   Collection<Car> run(CarService service) {
     return service.findAll();
   }
 });
}
This can be done by changing the run method as follows:
public static <T, R> R run(Class<T> serviceClass, ServiceRunnable<T, R> runnable) {
  final T service = getService(serviceClass);
  if (service != null) {
    return runnable.run(service);
  }
  return null;
}
It would take into account a user specified return value. If no service was found the run method would now return null. So to fulfill our API contract of before (returning an empty list and not null) the final method would be:
Collection<Car> listAllCars() {
  Collection<Car> cars = Trackers.run(CarService.class, new ServiceRunnable<CarService, Collection<Car>> {
    Collection<Car> run(CarService service) {
      return service.findAll();
    }
  });
  return cars != null ? cars : Collections.emptyList();
}
This could further be improved if we would have a fall-back facility.
public interface ServiceRunnableFallback<T, R> extends ServiceRunnable<T, R> {
  R run();
}
This simply introduces a new method that has no parameter but the same return value as the base interface. The Trackers class will use this interface if the service is not available:
if (service != null) {
  return runnable.run(service);
} else if (runnable instanceof ServiceRunnableFallback<?,?>) {
  return ((ServiceRunnableFallback<T, R>) runnable).run();
}
The car listing sample would then change to:
Collection<car> listAllCars() {
  return Trackers.run(CarService.class, new ServiceRunnableFallback<CarService, Collection<Car> > {

     Collection<Car> run(CarService service) {
       return service.findAll();
     }

     Collection<Car> run() {
       return Collections.emptyList();
     }
   }); 
}
Of course this is such a common use case, that we can create an abstract class for that, that will take the default return value in case the service is not available as a constructor argument:
public abstract class DefaultServiceRunnable<T, R> implements ServiceRunnableFallback<T, R> {

  private final R defaultReturn;

  public DefaultServiceRunnable(final R defaultReturn) {
    this.defaultReturn = defaultReturn;
  }

  public final R run() {
    return defaultReturn;
  }
}
And voilá, the final car listing example:
Collection<Car> listAllCars() {
  return Trackers.run(CarService.class, new DefaultServiceRunnable<CarService, Collection<Car>>(Collections.EMPTY_LIST) {
    Collection<Car> run(CarService service) {
      return service.findAll();
    }
  }); 
}
Now, the logging example from above does not return anything, so it would be nice if the code could be further simplified. We create another abstract class that will implement the ServiceRunnableFallback methods for us and just return null:
public abstract class SimpleServiceRunnable<T> implements ServiceRunnableFallback<T, Object> {

  public final Object run(final T service) {
    doRun(service);
    return null;
  }

  public final Object run() {
    doRun();
    return null;
  }

  protected void doRun() {
  }

  protected abstract void doRun(T service);
}
Note that this class marks the run(T) and run() as final so no subclass can override them but must doRun(T) instead. The abstract class has an empty body for doRun() in the case that the service is not available. With that in place the logging example could be re-written like this:
public static void log(int level, Throwable t, String message, Object... args) {
 final String text = String.format(message, args);
 Trackers.run(LogService.class, new SimpleServiceRunnable<LogService>() {
    protected void doRun(final LogService service) {
      service.log(level, text, t);
    }
   
    protected void doRun() {
      System.out.println(text);
    }
  });
}
I will upload the full source code to github soon, but to get you started here is full code of the Trackers class:
public final class Trackers {

  private static final Map<Class<?>, ServiceTracker> trackers = new HashMap<Class<?>, ServiceTracker>();

  public static <T, R> R run(Class<T> serviceClass, ServiceRunnable<T, R> runnable) {
    final T service = getService(serviceClass);
    if (service != null) {
      return runnable.run(service);
    } else if (runnable instanceof ServiceRunnableFallback<T, R>) {
      return ((ServiceRunnableFallback<T, R>) runnable).run();
    }
    return null;
  }

  private static <T> T getService(Class<T> serviceClass) {
    ServiceTracker tracker = trackers.get(serviceClass);
    if (null == tracker) {
      tracker = createTracker(serviceClass);
      trackers.put(serviceClass, tracker);
    }
    return serviceClass.cast(tracker.getService());
  }

  private static <T> ServiceTracker createTracker(Class<T> serviceClass) {
    return new ServiceTracker(FrameworkUtil.getBundle(Trackers.class)
        .getBundleContext(), serviceClass.getName(), null) {
      {
        open();
      }
    };
  }

  private Trackers() {
  }
}
The interfaces are all fully mentioned here, it'ss just a matter of copy&paste until everything is up on github. As always the code mentioned on this blog is licensed under EPL 1.0, so feel free to use and enhance it.

Tuesday, February 9, 2010

OSGi Clipboard Monitor for Java (on Windows using JNA)

Before you read on you should be familiar with JNA and OSGi as I will make heavy use of it in this posting.

Preface

For my CopyTo Eclipse plugin's preference page I wanted to enable the "Paste" button for label/URL combinations only if there is some text in the clipboard (and that text can be converted to a "CopyTo" target). So I would need to monitor the content of the systems clipboard.

SWT to the rescue! ... not!

So I checked if SWT can already help me here. There should be a Clipboard.addListener method that would allow me to register a listener with the clipboard and let SWT notify me about changed clipboard content. Unfortunately there is no such functionality in SWT. And I would soon know why that is ;)

The long way... using a Windows Clipboard "Viewer"

Since I am developing on a Windows machine, I fired up the Windows SDK help to see what it offers in regard to the clipboard. There is a SetClipboardViewer function that in a somewhat awkward way let your window become part of the clipboard viewer chain. Windows will then send 2 specific messages to this windows message proc to inform it about clipboard changes (WM_DRAWCLIPBOARD) or changes in the clipboard viewer chain (WM_CHANGECBCHAIN , if someone else calls SetClipboardViewer).

The first thing that bugged me was, that I do not have a window that I could give to the function and that could receive messages from Windows. Then, I remembered my old Win32 coding days in C++ and that one can create a hidden window just for messages. Instead of creating my own window class for that I decided to use an existing one. The "STATIC" window class does not need a lot of resources and does not receive a lot of messages so its the perfect candidate. We will just create an invisible instance of such window using JNA:

viewer = User32.INSTANCE.CreateWindowEx(0, "STATIC", "", 0, 0, 0, 0, 0, null, 0, 0, null);

Then we register the window with the clipboard viewer chain according to the API specs:

nextViewer = User32.INSTANCE.SetClipboardViewer(viewer);

The next thing to do is to redirect all messages to a custom window proc instead of the default one of the "STATIC" window class. This is called "subclassing" in Windows and in a sense is something like class subclassing in the Java world. Only on a "message only" basis.

Our new window proc will handle the two clipboard related messages and redirect the other messages to the original window proc of the "STATIC" window class.

User32.INSTANCE.SetWindowLong(viewer, User32.GWL_WNDPROC, this.ourProc);

Please note that ourProc is a member field, so that the Java GC will not remove its reference and JNA would no longer be able to send messages to our callback!

Thats how the callback looks like:

class OurProc implements WNDPROC {
public int callback(HWND hWnd, int uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case User32.WM_CHANGECBCHAIN:
  // If the next window is closing, repair the chain.
  if (nextViewer.toNative().equals(wParam.toNative())) {
    nextViewer = new HWND(Pointer.createConstant(lParam.longValue()));
  } // Otherwise, pass the message to the next link.
  else if (nextViewer != null) {
    User32.INSTANCE.SendMessage(nextViewer, uMsg, wParam, lParam);
  }
  return 0;
case User32.WM_DRAWCLIPBOARD:
  try {
    onChange(new ClipboardEvent(this));
  } finally {
    User32.INSTANCE.SendMessage(nextViewer, uMsg, wParam, lParam);
  }
  return 0;
case User32.WM_DESTROY:
  User32.INSTANCE.ChangeClipboardChain(viewer, nextViewer);
  break;
}
return User32.INSTANCE.DefWindowProc(hWnd, uMsg, wParam, lParam);
}

That's pretty much the code from the Windows SDK help for programming a Clipboard Viewer. There is some strange chain repairing code included. Speaking of bad API design. How easily could that break, if one programmer gets it wrong?

Polling the message queue without wasting CPU cycles

Now, for the sub-classed static window to receive any messages we need to poll the message queue. In Windows you can only poll your own threads message queue. And, important to know, Windows only creates a message queue if a thread creates a window or calls one of the message queue related functions like GetMessage or PeekMessage. So a simple message poller in our threads run() method would look like this:

while (User32.INSTANCE.GetMessage(msg, null, 0, 0)>0) {
  User32.INSTANCE.TranslateMessage(msg);
  User32.INSTANCE.DispatchMessage(msg);
}

However, GetMessage is a blocking call and so our Thread would consume all the available CPU cycles it could get until a new message arrives in the queue. That's certainly not what we want. Instead we have to create more sophisticated message queue polling logic. We also want to be able to end our clipboard monitor at any given time. We do that by signaling a special Win32 kernel event object. The MsgWaitForMultipleObjects allows us to wait for message to arrive in the queue as well as events that get signaled. So our new message polling loop that cost (almost) no CPU cycles looks like this:

final HANDLE handles[] = { event };
while (true) {
  int result = User32.INSTANCE.MsgWaitForMultipleObjects(handles.length, handles, false, Kernel32.INFINITE, User32.QS_ALLINPUT);

  if (result == Kernel32.WAIT_OBJECT_0) {
    User32.INSTANCE.DestroyWindow(viewer);
    return;
  }
  if (result != Kernel32.WAIT_OBJECT_0 + handles.length) {
    // Serious problem, end the thread's run() method!
    break;
  }

  while (User32.INSTANCE.PeekMessage(msg, null, 0, 0, User32.PM_REMOVE)) {
    User32.INSTANCE.TranslateMessage(msg);
    User32.INSTANCE.DispatchMessage(msg);
  }
}

Please note that we poll all messages out of the queue until there are no more left and only then return to another round of MsgWaitForMultipleObjects until our halt event is signaled.

That's it about the gory details of implementing such a "viewer" in Windows (without displaying anything). The hard thing to figure out was, that all user level related calls had to be made from the thread that will read out the message queue.

Why Microsoft decided to put the responsibility of a chain into the hands of the programmer is beyond me. Clearly bad API design.

Adding some spin - OSGi services

Of course when programming in Java I will always use OSGi whenever possible. The Clipboard Monitor is no exception. Granted, the whole code can be used without OSGi too. But then you would have to implement a kind of listener management yourself. That's up to the reader of this entry and I welcome everyone to contribute a plain old Java implementation of AbstractWindowsClipboardMonitor that integrates hand crafted listener management instead of using the OSGi service registry.

So there is a monitor component that will consume ClipboardListener services registered in the system and inform them about changes in the clipboard.

Listener that publishes an event using the EventAdmin

Now we can have a fairly simple listener that publishes an event on every clipboard change:

public class EventAdminClipboardListener implements ClipboardListener {
  private static final String TOPIC = "clipboard/monitor/event"; //$NON-NLS-1$

  private final AtomicReference ref = new AtomicReference();

  protected void bind(EventAdmin eventAdmin) {
    ref.set(eventAdmin);
  }

  protected void unbind(EventAdmin eventAdmin) {
    ref.compareAndSet(eventAdmin, null);
  }

  public void onEvent(ClipboardEvent event) {
    EventAdmin eventAdmin = ref.get();
    if (eventAdmin != null) {
      eventAdmin.postEvent(new Event(TOPIC, (Map) null));
    }
  }
}

Pretty simple.

The SWT Clipboard Listener service

Then we have this listener service that will examine the content of the clipboard and use the OSGi EventAdmin to publish specialized events with topics describing the content of the clipboard. EventHandler services can so easily react on specific changes in the clipboard. The following event topics are currently implemented:

  • clipboard/monitor/swt/TEXT
  • clipboard/monitor/swt/URL
  • clipboard/monitor/swt/IMAGE
  • clipboard/monitor/swt/RTF
  • clipboard/monitor/swt/HTML
  • clipboard/monitor/swt/FILE

So you could register an EventHandler that reacts on changes in the clipboard, and only if the new clipboard content contains (also) text. Your EventHandler service would register with the topic set to "clipboard/monitor/swt/TEXT". The beauty of this componentized approach is that you do not even have to know that there is a clipboard monitor installed and running in the system. You have no dependencies on it. You simply register for events of a specific topic and get informed about changes. You can then use SWT to read out the clipboard.

Conclusion

I hope this rather lengthy posting gave you another clue what can be done using clean OSGi component design. And maybe some of you can even put the components to some use in your own projects. It's all licensed under EPL 1.0 so feel free to use the code.

Here you can watch a little video demonstration (if you cannot see the video below).

Code at GitHub

You are invited to check out the full source code over at GitHub and you are invited to fork/clone and contribute, if you want. Maybe someone can add a GTK/Linux clipboard viewer?

Friday, February 5, 2010

P2 error messages are useless - for users and for me as a programmer

I handed out the update site URL of my "copyto" Plug-in to a friend and when he wanted to install it, p2 threw this message at him:
Cannot complete the install because one or more required items could not be found. Software being installed: codepad.org support 0.1.0.201002050243 (eclipseutils.ui.copyto.codepad.feature.feature.group 0.1.0.201002050243) Missing requirement: eclipseutils.ui.copyto 0.1.0.201002050243 requires 'package org.eclipse.core.runtime.preferences 3.3.0' but it could not be found Cannot satisfy dependency: From: codepad.org support 0.1.0.201002050243 (eclipseutils.ui.copyto.codepad.feature.feature.group 0.1.0.201002050243) To: eclipseutils.ui.copyto 0.0.0
I would guess that there is at least one package with the name "org.eclipse.core.runtime.preferences" installed and it would be very helpful if p2 prints out the available versions of that package. That would have made it easier for me to recognize, that 3.3.0 is obviously an Eclipse 3.6 package (I am using the I-Build as my target). Beside that, this error message displayed to a non-programmer is equally useless. It's filled with cryptic numbers and too much information the average user cannot understand. Heck, I do not even understand it and then it's also missing crucial information for me as a programmer. I filed a bug to get at least the required information into the error message.

CopyTo...Pastebin (and others) Plug-In for Eclipse

I am currently working on a small Plug-In that some of you might find useful (especially if you are hanging out in IRC a lot). The plugin allows you to select resources, classes or methods in Java projects and posts them to your favorite pastebin. After that it provides the URL of the pastebin entry in your clipboard so you can easily send it to others. This little video demonstrates this: Some pastebins allow the user to specify additional options when posting. This will be covered when the user helds down the "CTRL" while selecting the menu entry. A dialog is then display where the user can adjust such options. Likewise he could change the content type of the pasted text, if the automatic detection failed. The Plug-In will be released under EPL 1.0 and the source will be up at github. Now, if anyone of you have a nicer name for the Plug-In, I would like to replace the rather generic "CopyTo" (Pasty?). The Plug-In is very easily extensible with new pastebin providers. In fact all current providers are supplied via Fragement-Bundles that basically just add their menuContribution the the CopyTo menu. There is support for the usual redirect based pastebins, as well as ones that send back JSON. Additional response handlers can be easily plugged in (SOAP *yikes*) and additional JSON helpers, that extract the new location URL component from a JSON response are queried using the Eclipse IAdapterManager. Currently there is only support for copying JDT elements (Classes, Methods) but other sources of "Copyable" content can be also plugged in via Adapters. I also plan to provide a "History" view of pastes that allows you to copy the URL again into the clipboard at any time.

Thursday, February 4, 2010

Use ID on the extension element or as an attribute?

I wonder whats the best approach to give an extension a unique ID. There are two ways to do that:
  1. Use the ID already present on each extension element
  2. Create an "id" attribute in a child-element of the extension
I am currently working on a "CopyTo" extension for the Eclipse Workbench, that allows to quickly copy Java classes or method bodies to your favorite pastebin site and puts the URL of the created entry into the clipboard. For some pastebin providers there is post-processing needed that one should be able to plug-in via extensions. So I have the "eclipseutils.ui.copyto" Extension Point that should provide the following:
  1. Allow to specify a response handler
  2. Allow to describe parameter configurations, that the user can edit prior the request is sent
Should I have 2 EPs for that: "eclipseutils.ui.copyto.responseHandlers" and "eclipseutils.ui.copyto.paramInfos"? Or one "eclipseutils.ui.copyto.extensions" with sub-elements "responseHandlers" and "paramInfos"? Each "CopyTo" is contributed via menuContribution that uses the "eclipseutils.ui.copyto" command. One of the command parameters is "id" which is used to look up extensions provided for that menuContribution. I guess the quickest way to fetch an extension for a specific "id" is to ask the IExtensionRegistry for an IExtension with a specific ID. That would mean you have to set the ID on the extension itself. Otherwise I would have to query all IConfigurationElements and parse it for the "id" attribute. How you design your extensions also depends if others should be able to contribute to them later. The product splashscreen is a good example of late bindings. You describe the splashscreen somewhere and later reference it in a binding with a specific product. Any thoughts?

Enterprise OSGi does not make JPA more dynamic

I just browsed the draft version of the new OSGi specs for the enterprise. I was especially interested in how they want to address the JPA related problems. They have not chosen a fundamentally different path than I've been doing JPA development in OSGi for 2 years now. Difference is, they propose a new interface (PersistenceUnitProvider) to be registered for each persistence unit while I was just registering an EntiyManagerFactory with the "pu-name" service property. So every interested service could directly bind to a specific EntityManagerFactory and create its EntityManager from it. So far so good. I was surprised however, that the OSGi specs do not address the main issue with JPA. It's static. You can not add/remove entities dynamically. It was never designed that way and the OSGi enterprise will not solve that issue. You still have to specify all entities up front in the dreaded persistence.xml. Yet, the more OSGi way would be to skip that file altogether, have the name of the persistence unit name as service property (unit.name) of the PersistenceUnitProvider and let the PUP consume entity beans (exported as java.lang.Object services) with their "unit.name" specifying their target unit. The PersistenceUnitProvider would then have to parse the beans annotations and incorporate it into its EntityManagers. I am aware of the big problems that can bring with it. What if there are currently transactions running? Does removing an entity from the system also mean to clean up the database? The JPA implementation would have to rebuild its internal state and caches on entity changes. I had hopes the OSGi enterprise spec would address those issues of non-dynamically of current JPA implementations. So even with this new spec, not much is going to change how I program JPA. It will still not be possible to add new business logic to a running OSGi system without touching the persistence.xml.

Saturday, January 23, 2010

Adding actions to Eclipse console commands

This article assumes you know what Declarative Services (DS) are and have a basic understanding of OSGi.

Introduction

There is one big problem with the Eclipse console commands. You can have only one command with a specific name. That's of course the case in all consoles known to me. However in most consoles the commands express by their name what they actually do. Now in Eclipse we have good commands like "ss" for a quick overview of the currently known bundles in the system. Then there are the framework commands like "launch", "shutdown" and "exit" which fairly behave like you would expect them by their name. But do you know what the "list", "ls" or "enable", "en" commands do? Well, they come from the "Service Component Runtime" (SCR) bundle.
list/ls [-c] [bundle id] - Lists all components; add -c to display the complete info for each component;
enable/en  - Enables the specified component;
So when you load the SCR bundle the command "list" will be taken. And it will list components. A better name would have been "listcomponents". An even better approach would have been, if the Eclipse command framework was initially planned to have commands that can be extended by actions. Because then we would have a "list" command that could be extended by actions. We would have "list components", "list bundles" and "list services". There would be much less namespace clutter and a tighter set of commands. But since we cannot create a new "list" command, as SCR occupies it already, we have to go a slightly different way.

What are command actions?

Command actions are a way to group commands and redirect the concrete execution to an action. So for the SCR I would like to suggest the following command: component This command would have several actions: list,enable,disable,info and for the sake of completeness the short versions of the original SCR commands as actions: ls,en,dis,i A command action is an OSGi services, that can dynamically extend an existing command. Its service interface is really simple:
public interface CommandAction {
 void execute(CommandActionContext context) throws Exception;
}
The action gets in a context that allows it to query execution parameters that the user typed in the command line. It also allows the action to print text on the console.
public interface CommandActionContext {
 String getArgument(int index);

 boolean hasOption(String name);

 boolean isVerbose();

 void print(String text);

 void println(String text);
}
A sample action would look like this:
public class FileCopyAction implements CommandAction {
 void execute(CommandActionContext context) throws Exception {
   String from = context.getArgument(0);
   String to = context.getArgument(1);
   if (from == null || to == null) {
     throw new IllegalArgumentException("You must specify from and to arguments");
   }
   // Copy code here...
 }
}
Its OSGi DS definition would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.example.commands.file.CopyAction">
  <implementation class="org.example.commands.file.CopyAction"/>
  <service>
     <provide interface="org.eclipse.osgi.framework.console.action.CommandAction"/>
  </service>
  <property name="command" type="String" value="file"/>
  <property name="action" type="String" value="copy"/>
</scr:component>
Now we need a way to bring a command and its actions together. This is implemented in an abstract class that implements the standard Equinox CommandProvider. It also parses the command line and prints help. It takes the first argument from the command line and searches an action that matches the argument. It then calls the found actions execute method with the rest of the command line neatly seperated into arguments and options (that start with "-" or "--"). It also catches any exception that the action may throw during its execution. If the action throws an IllegalArgumentException, our command implementation will print help for the command. If we want to introduce a new command "file" all we have to do is to create a small subclass from the abstract base class "ActionCommand".
public class FileCommand extends ActionCommand {
 public void _file(CommandInterpreter ci) {
   execute("file", ci);
 }
}
Per definition, to create a command in Eclipse Equinox we have to have a public method beginning with an underscore. So there is a small duplication of names here, since our ActionCommand baseclass does not know the name of the method its called from, we have to hand it in as first parameter to the execute method. Somewhere we would also have to define the file command itself. Its published as a CommandProvider.
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="org.example.commands.file">
  <implementation class="org.example.commands.file.FileCommand"/>
  <service>
     <provide interface="org.eclipse.osgi.framework.console.CommandProvider"/>
  </service>
  <reference cardinality="1..n" interface="org.eclipse.osgi.framework.console.action.CommandAction" name="CommandAction" policy="static" target="(command=file)"/>
</scr:component>
Please note, that this command component will only be instantiated if there is at least one CommandAction service registered that has its "command" property set to "file" and is therefor providing an action for our command. See the example file copy action in "action" (It does not really copy a file):
That's all. Happy extending your own commands. And maybe this will find its way back into the Equinox code and we can finally have one global "list" command with lots of actions.

The code is available at git.

Tuesday, January 12, 2010

Notification Listeners

To let other components in the system know about displayed notifications we use the White-Board-Pattern to consume listener services in our NotificationServiceImpl class. A listener for notifications has a very easy interface:
public interface NotificationListener extends EventListener {
  void onEvent(NotificationEvent event);
}
It extends the default Java (empty) EventListener base interface and contains a single method. This single method and its associated event object allows us to extend the kind of events we can publish without changing the interface for each new event like "Show" or "Hide". For now we will only publish "Show" events. But if in the future we decide to also notify listeners about the close/hide of a notification popup we would have to add another method to the interface "onHide" and breaking the API somehow. Using an event object we can put the type of the event inside the event object and the client would then have to decide what to do for each event type. It would still only implement a single method "onEvent" instead of having to implement a new method for each new event type such as "onShow" or "onHide". The event object itself looks like this:
public class NotificationEvent extends EventObject {
private static final long serialVersionUID = -8633958140848611658L;

private Notification notification;

private NotificationEventType type;

public NotificationEvent(NotificationService source, Notification notification, NotificationEventType type) {
  super(source);
  this.notification = notification;
  this.type = type;
}

public Notification getNotification() {
  return notification;
}

public NotificationEventType getType() {
  return type;
}
}
The event type is an enum:
public enum NotificationEventType {
Show
}
The NotificationServiceImpl is only slightly changed:
Object listeners[] = context.locateServices("NotificationListener"); //$NON-NLS-1$
if (listeners != null) {
 NotificationEvent event = new NotificationEvent(this, notification, NotificationEventType.Show);
 for (Object listener : listeners) {
   try {
     ((NotificationListener)listener).onEvent(event);
   } catch (Throwable e) {          
   }
 }
}
Right before we display the notification we get all the NotificationListener registered in the OSGi system and (safely) call their onEvent method. There are several ways to get the list of currently registered NotificationListener services. One way is to use the BundleContext.getServiceReferences(String, String) method. But this would involve getting the service object ourself and not forget to "unget" it also. Another way is to use a ServiceTracker. But since our implementation already is a Component with bindings we can just add a new binding to our service component definition XML:
<reference cardinality="0..n" interface="ui.notification.NotificationListener" name="NotificationListener" policy="dynamic"/>
We then use the ComponentContext object to get an array of services that could be bound to "NotificationListener" (as named in the component XML). This context we get from OSGi in a new protected method:
protected void activate(ComponentContext context) {
 this.context = context;
}
That's all for notifying listeners about notification display. We can now create a simple new bundle that will register a NotificationListener into the system and simply System.out.println the notifications data.
public class SysoutNotificationListener implements NotificationListener {

  public void onEvent(NotificationEvent event) {
    if (event.getType() == NotificationEventType.Show) {
      System.out.println(event.getNotification().getTitle() + ": " //$NON-NLS-1$
          + event.getNotification().getMessage());
    }
  }
}
Its component definition would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<scr:component xmlns:scr="http://www.osgi.org/xmlns/scr/v1.1.0" name="ui.notification.listener.sysout">
 <implementation class="ui.notification.listener.sysout.internal.SysoutNotificationListener"/>
 <service>
    <provide interface="ui.notification.NotificationListener"/>
 </service>
</scr:component>
Pretty simple. Here is what the result looks like: Listeners could also be used to log a history of notifications in various ways. In the next chapter of this series we will develop a View for Eclipse RCP apps that logs a history of notifications in a table.