Jacob can register Java classes for MS application events or callbacks.  The normal flow for this is:

 

1)        Application thread creates an instance of the event handler and registers it with Jacob

2)        The application continues on doing other work.

3)        Some time later, the MS application takes some action and initiates the event callback.

4)        The Java VM receives the event and spins up a new thread to handle it.

5)        The Jacob EventProxy in the dll is called by the VM.

6)        The Jacob EventProxy creates Variant objects to handle the parameters of the passed in event.

7)        The Jacob EventProxy uses reflection to map the event name to a method name with the exact same name.

8)        The Jacob EventProxy sends the message to the registered event handler.

 

Swing developers should note that this message comes in on a thread other than the event thread.  All objects receiving events that require user intervention or drawing in the UI should use invokeLater() to post requests for actions onto the event queue.  Failure to do so will insure random failures in the GUI.

 

Java Web Start (JWS) and other launchers can have additional issues related to the class loader.  The Jacob C++ library uses FindClass() to find the Variant class when building the parameter list.  FindClass() uses the system class loader which includes only the classes specified at run time or in the CLASSPATH.  Most of the application classes in this situation live in an alternate set of class loaders that were created when the launcher located and ran the application classes.  This means that the search for Variant will fail usually with the silent and immediate termination of the Java application.  The thread classloader probably can’t be used to try and find the class because this new thread does not have a classloader associated with it other than the system class loader.  The end result is that the Variant class needs to be located via other means and that the thread classloader should be set to be the context class loader of the event handler class.

 

The Jacob EventProxy class has been modified (off of the 1.8 tree) so that it takes a two step approach to towards fixing these problems.

           

1)        EventProxy first attempts to locate the Variant class using FindClass()

2)        Failing that, it looks to see if the event callback object implements getVariantClass() that returns the Variant.class object.  If so, it uses that class to create variants for the callback parameters.

3)        If all that fails, it logs a message and then fails in the spectacular fashion of the previous versions.

 

This means developers can receive call back events in JWS other Java launching programs by implementing getVariantClass() on all of their classes that receive Microsoft Events.  The getVariantClass() method has the added benefit of providing a spot for the thread classloader to be set:

      Public Class getVariantClass(){

            Thread.currentThread().setContextClassLoader(

                  this.getClass().getClassLoader());

            return Variant.class

      }

 

There may still be a dual event queue issue in JWS applications that needs to be looked at.