Joachim would you be interested to write a little Chpater for the Pharo for the entreprise book? I can help.
Ste On 05 Apr 2014, at 14:32, Joachim Geidel <joachim.gei...@onlinehome.de> wrote: > Am 31.03.2014 um 21:25 schrieb Tudor Girba <tu...@tudorgirba.com>: >> Now, the next question. I saw that it is possible to enable callbacks, but I >> could not find an example of how it works. >> >> For example, could we model this: >> >> - in a JavaClassOriginator class we have a method like >> execute(JavaClassTargetInterface target) { target.m() } >> - In Pharo we create PharoClassTargetImplementation as an implementation of >> JavaClassTargetInterface >> - passing an instance of PharoClassTargetImplementation to >> JavaClassOriginator results in calling PharoClassTargetImplementation>>m >> >> ? >> >> >> Cheers, >> Doru > > Hi Doru, > > it’s not completely straightforward, but also not really complicated. Chris > Uppal’s JNIPort documentation contains examples, and you can also get some > information from the test cases for callbacks. You will need the jniport.jar > file which can be downloaded from http://jniport.wikispaces.com/Downloads (it > is contained in JNIPort_Extras.zip). The Java classes needed for callback > support have names starting with „Dolphin“ - they come directly from Chris’ > implementation for Dolphin Smalltalk. > > A simple example: To set up sending a simple notification without parameters > to a Smalltalk object, you need a Java class similar to the following: > > ----------------- > package my.package; > import org.metagnostic.jniport.*; > public class MyClass > { > private static final Object notifyTag = new > String("MyClass.sendNotification()“); > public static Object notifyTag () { return notifyTag; } > public void sendNotification() > throws RequestNotHandedException > { > new DolphinNotification(notifyTag, this).send(); > } > } > ----------------- > > You have to install the callback in Smalltalk: > > ----------------- > NotificationHandler := … "the object which receives the notifications" > classStatic := jvm findClass: 'my.package.MyClass'. > jvm callbackRegistry > setCallback: classStatic notifyTag "the tag can be an arbitrary String" > handler: [:this :param | NotificationHandler handleNotificationFor: > this]. > ----------------- > > When you send sendNotification() to an instance of MyClass, > NotificationHandler should receive the message #handleNotificationFor:. > > In the example code, the tag is a static variable in MyClass. Of course, you > can also give every instance of MyClass its own tag. In this case, you have > to set up a callback in Smalltalk for every tag which is used. > > The example is a short version of the test code for handling notifications in > JNIPortCallbackNotificationsTest and the corresponding Java class > org.metagnostic.jniport.test.regression.Notifications. The source code of > this Java class is in the archive JNIPort-Tests.zip which is contained in > JNIPort_Extras.zip. > > If you need an example for a notification which has parameters and where the > Smalltalk code returns a result, have a look at > JNIPortCallbackRequestsTest>>testCallbackWithOneParameterAndReturn and the > corresponding Java class org.metagnostic.jniport.test.regression.Callbacks. > > In the Java class, you need something like this (copied from Callbacks and > simplified) which enables a callback taking an int parameter and returning an > instance of the Java class Integer: > > private static final Object callbackTag = new String(„callback with > parameters"), > > // callback with return value > public int callbackAndReturn(int i) > throws Throwable > { > Object returnValue = new DolphinRequest(callbackTag, this, > i).value(); > return ((Integer) returnValue).intValue(); > } > > A DolphinRequest is created with the tag which identifies the callback in > Smalltalk, the object sending the callback (this), and an arbitrary number of > parameters. For example, the following creates a DolphinRequest with two > parameters: > > DolphinRequest dr = new DolphinRequest( > s_callbackTag, > this, > new Integer(i), > new Double(d)); > > Calling the value() method of the DolphinRequest sends the request to > VisualWorks and returns the result of the Smalltalk callback block. > > In Smalltalk, you can create callbacks accepting parameters like this (see > JNIPortCallbackRequestsTest): > > "No parameters" > jvm callbackRegistry setCallback: classStatic callbackTag > handler: [:this :param | self handleCallbackFor: this]. > > "One parameter" > jvm callbackRegistry setCallback: classStatic callbackTag > handler: [:this :param | self handleCallbackFor: this > with: param]. > > "Arbitrary number of parameters" > jvm callbackRegistry setCallback: classStatic callbackTag > handler: [:this :params | self handleCallbackFor: this > withArguments: params asArray]. > > If the callback has a result which should be passed from Smalltalk to Java, > it must be a Java object. Here is an example from the test class > (callbacksStatus is just an instance variable of JNIPortCallbackRequestsTest): > > handleCallbackFor: aJavaObject with: anotherJavaObject > > | jliClass | > > jliClass := jvm findClass: #'java.lang.Integer'. > > callbacksStatus addLast: (aJavaObject = instance). "identity test > on the Java object" > callbacksStatus addLast: ((anotherJavaObject static = jliClass) and: > [anotherJavaObject intValue = 1]). > > ^ jliClass new_int: 15. "Do not return a Smalltalk Integer. It must be > a Java Integer“ > > Johan Brichau’s JavaConnect had a more direct way of creating callbacks, > using Java’s dynamic proxies. However, it had an open issue, as it relied on > different Java objects having different identity hashes, which is not true in > all cases. JNIPort’s implementation is relatively complicated because it had > to take into account that the callbacks can be triggered from a different > thread than the Smalltalk thread. In VisualWorks, that’s not a problem, as > the VM handles this, and Pharo simply does not support callbacks from foreign > threads. So, it could be simplified in JNIPort as well. > > Does this help? > Joachim > >