EventCallbacks.html 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. <html>
  2. <head>
  3. <title>Jacob can register Java classes for MS application events or callbacks</title>
  4. <BODY>
  5. <H2>Overview</H2>
  6. Jacob can register Java classes for MS application events or callbacks.
  7. <H2>Sequence of Events</H2>
  8. The normal flow for this is:
  9. <OL>
  10. <LI>Application thread creates an instance of the event handler and registers it with Jacob</li>
  11. <LI>The application continues on doing other work.</li>
  12. <LI>Some time later, the MS application takes some action and initiates the event callback.</li>
  13. <LI>The Java VM receives the event and spins up a new thread to handle it.</li>
  14. <LI>The Jacob jni EventProxy in the dll is called by the VM.</li>
  15. <LI>The Jacob jni EventProxy creates Variant objects to handle the parameters of the passed in event.</li>
  16. <LI>The Jacob jni EventProxy sends the name of the callback and the array of Variant objects to the Java InvocationProxy
  17. that was registered to catch events.</li>
  18. <LI>The Java InvocationProxy uses reflection to map the event name to a method name with the exact same name.</li>
  19. <LI>The Java InvocationProxy sends the message to the registered event handler and returns if the event handler
  20. is of type void (standard behavior). </li>
  21. <LI>The Java InvocationProxy sends the message to the registered event handler and returns the Variant that
  22. resulted from the call back to the Jacob jni EventProxy that then returns it to the windows calling
  23. program.
  24. </li>
  25. </OL>
  26. <H2>SWING Issues</H2>
  27. Swing developers should note that this message comes in on a thread other than the event thread. All objects receiving events
  28. that require user intervention or drawing in the UI should use invokeLater() to post requests for actions onto
  29. the event queue. Failure to do so will insure random failures in the GUI. Java Web Start (JWS) and other launchers
  30. can have additional issues related to the class loader. The Jacob C++ library uses FindClass() to find the Variant
  31. class when building the parameter list. FindClass() uses the system class loader which includes only the classes
  32. specified at run time or in the CLASSPATH. Most of the application classes in this situation live in an alternate
  33. set of class loaders that were created when the launcher located and ran the application classes. This means
  34. that the search for Variant will fail usually with the silent and immediate termination of the Java application.
  35. The thread classloader probably can�t be used to try and find the class because this new thread does not have
  36. a classloader associated with it other than the system class loader. The end result is that the Variant class
  37. needs to be located via other means and that the thread classloader should be set to be the context class loader
  38. of the event handler class.
  39. <H2>1.8 and 1.9 behavior</H2>
  40. The Jacob EventProxy class has been modified (off of the 1.8 tree) so that it takes a two step approach towards fixing these
  41. problems.
  42. <OL>
  43. <LI>The EventProxy constructor now accepts an extra object, an instance of the Variant class. This gives the
  44. EventProxy a way to get to the Variant class and thus to its classloader. All of the callers of the
  45. constructor have been modified to pass a Variant object to the EventProxy without programmer intervention.</li>
  46. <LI>EventProxy first attempts to locate the Variant class using FindClass()</li>
  47. <LI>Failing that, it looks to see if a variant object had been passed in. If so, it calls class() and goes
  48. from there. </li>
  49. <LI>If all that fails, it logs a message and then fails in the spectacular fashion of the previous versions.</li>
  50. </OL>
  51. <H2>1.10 behavior</H2>
  52. The Jacob EventProxy class has been modified so that it takes a different approach towards fixing this problem.
  53. <OL>
  54. <LI>All objects that request event notification are now wrapped in a Java InvocationProxy so that a standard
  55. interface is always presented to the JNI EventProxy object.</li>
  56. <LI>The EventProxy constructor accepts any Java class. It wraps the class if it is not an InvocationProxy or
  57. uses just the passed in object if it is an InvocationProxy. The JNI layer talks to the InvocationProxy
  58. instead of talking directly to the event listener as in previous releases.</li>
  59. <LI>The Java InvocationProxy has a method on it that will return the Variant class that the EventProxy. The
  60. JNI code uses this method to acquire the class so that it can call newInstance().</li>
  61. </OL>
  62. Developers can receive call back events in JWS other Java launching programs without implementing any additional code. They
  63. should be aware that their callback methods may need to set the class loader. If they expect to create any objects.:
  64. <pre>
  65. Public xxx someHandler(Variant[] foo){
  66. Thread.currentThread().setContextClassLoader(
  67. this.getClass().getClassLoader());
  68. // do something
  69. }
  70. </pre>
  71. <p></p>
  72. There may still be a dual event queue issue in JWS applications that needs to be looked at.
  73. <p></p>
  74. <H2>1.12 Experimental Behavior</H2>
  75. Release 1.12 adds experimental support for event handlers that accept java objects as parameters to closer match the signature
  76. of the windows callback. New ActiveXDispatchEvents and ActiveXInvocationProxy operate in tandem in the same way
  77. as DispatchEvents and InvocationProxy. DispatchEvents overrides getInvocationProxy() to create a new ActiveXInvocationProxy
  78. in place of the normal InvocationProxy. ActiveXInvocationProxy has its own invoke() method that uses reflection
  79. to call back using java objects as parameters.
  80. <p></p>
  81. Issues with this approach
  82. <ul>
  83. <li>Event callbacks that use java signatures do not support parameter modification. Many windows callbacks
  84. let a user reject an event that is about to happen by modifying one of the parameters. In this situation,
  85. the old DispatchEvents/InvocationProxy pair must be used instead of the new handlers.</li>
  86. </ul>
  87. </body>
  88. </html>