Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people, just like you, are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
Solved

Callback

Posted on 2003-11-03
21
943 Views
Last Modified: 2008-03-10
I'm trying to implement a callback in Java (like in C++), and wondering what the best way of doing this is.

Let's say I have a class called CallBack, and a main class called Test.

class Test {
  CallBack callback;
  public static void main(String[] args) throws Exception{
    Test test = new Test();
    test.initCallback();
    Thread.sleep();
  }

  void initCallback() {
    callback = new Callback();
    callback.start();
  }

  void callbackMethod() {
    System.out.println("called from callback");
  }
}

Class CallBack extends Thread {
  public void run() {
    while(true) {
      sleep(10000);
      //call the callback method in Test
    }
  }
}

Now I realize the easiest way to do this is to pass a reference to the Test class to the CallBack class.  I was CallBack to be completely encapsulated though, so it can work as a callback to any class.

Now I was thinking to maybe have the Test class implement some interface that defined in it a callback method.  Anyways, Im looking for ideas that I havnt thought of yet, or if there is some accepted way of doing this that I havn't heard of.
 
0
Comment
Question by:lwinkenb
  • 9
  • 5
  • 4
  • +2
21 Comments
 
LVL 86

Expert Comment

by:CEHJ
ID: 9674936
This is a variant on the Observer pattern, which of course already exists in the API:

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Observer.html

and

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Observable.html

but you're using a Runnable. Is that always going to be the case?
0
 
LVL 92

Expert Comment

by:objects
ID: 9674984
> Now I was thinking to maybe have the Test class implement some interface
> that defined in it a callback method.

Yes thats the general way to handle it.
You just define some interface with your callback method, and pass implementations of that to any class that needs to make callback.

0
 
LVL 6

Expert Comment

by:kotan
ID: 9674988
Pass the Test object into CallBack class. Then, callbackMethod() can be called by Test object reference in CallBack class.

class Test {
  CallBack callback;
  public static void main(String[] args) throws Exception{
    Test test = new Test();
    test.initCallback();
    Thread.sleep();
  }

  void initCallback() {
    callback = new Callback(this);
    callback.start();
  }

  void callbackMethod() {
    System.out.println("called from callback");
  }
}

Class CallBack extends Thread {
  Test test;
  public CallBack(Test test) {
     this.test = test;
  }

  public void run() {
    while(true) {
      sleep(10000);
      //call the callback method in Test
      test.callbackMethod();
    }
  }
}
0
Free Tool: SSL Checker

Scans your site and returns information about your SSL implementation and certificate. Helpful for debugging and validating your SSL configuration.

One of a set of tools we are providing to everyone as a way of saying thank you for being a part of the community.

 
LVL 92

Expert Comment

by:objects
ID: 9674993
interface MyCallback
{
   public void callbackMethod();
}

class Test implements MyCallback {
  CallBack callback;
  public static void main(String[] args) throws Exception{
    Test test = new Test();
    test.initCallback();
    Thread.sleep();
  }

  void initCallback() {
    callback = new Callback(this);
    callback.start();
  }

  void callbackMethod() {
    System.out.println("called from callback");
  }
}

Class CallBack extends Thread {
  private MyCallback cb;
  public CallBack(MyCallback cb) {
    this.cb = cb;
  }

  public void run() {
    while(true) {
      sleep(10000);
      cb.callbackMethod();
    }
  }
}

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9675024
Of course, if you use the API and don't reinvent the wheel, you can simply get your class to implement the Observer interface, and then you do not need to limit the type of what you want called back.
0
 
LVL 92

Accepted Solution

by:
objects earned 500 total points
ID: 9675033
If you wanted something more generic you could also use reflection and just pass the name of the method you wanted to execute.
eg. to callback any method that takes no args you'd do something like:

class Test {
  CallBack callback;
  public static void main(String[] args) throws Exception{
    Test test = new Test();
    test.initCallback();
    Thread.sleep();
  }

  void initCallback() {
    callback = new Callback(this, "callbackMethod");
    callback.start();
  }

  void callbackMethod() {
    System.out.println("called from callback");
  }
}

Class CallBack extends Thread {
  private Object tocb;
  private Method cb;
  public CallBack(Object tocallback, String methodname) throws Exception {
    tocb = tocallback;
    this.cb = tocb.getMethod(methodname, null);
  }

  public void run() {
    while(true) {
      sleep(10000);
      cb.invoke(tocb, null);
    }
  }
}
0
 
LVL 92

Expert Comment

by:objects
ID: 9675064
Observer/Observable classes are really not designed for implementing callbacks.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9675074
So what do think is going on when notifyObservers() or notifyObservers(Object o) gets called?
0
 
LVL 5

Author Comment

by:lwinkenb
ID: 9675124
Thanks for the fast replies guys, looking over the responses now.  I'll answer the quick questions first though:

>>but you're using a Runnable. Is that always going to be the case?
Not always.  Actually what I want is for the CallBack class to load a JNI class which will provide it's own callback to the CallBack class.  Then CallBack will call the Test class.  In this case it would not use Runnable.  I just used Runnable to make my example a bit simpler.

>>Pass the Test object into CallBack class.
That would defeat the whole encapsulation idea.  In my origonal post I stated why this wouldn't work.

CEHJ and Object >> Going to look over your idea's now.
0
 
LVL 92

Expert Comment

by:objects
ID: 9675135
> So what do think is going on when notifyObservers() or notifyObservers(Object o) gets called?

Well you can call any method call a callback using that logic :-D

From the Observer javadoc:

"A class can implement the Observer interface when it wants to be informed of changes in observable objects."

a. we are not necessarily interested in changes in objects
b. we are not dealing with observable objects

You could certainly shoehorn the Observer/Observable classes to perform the callbacks but it would certainly not be an optimal solution and would be unnecessarily limiting.

0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9675211
You should also be careful about tight coupling/circular references. At the moment you have

a. a reference to a Callback in Test
b. an implied reference to Test in Callback (the latter needs to call a method in the former)
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9675287
I'm late to the game on this one, but on balance, I think I side with CEHJ.

I'm not sure why you qualified your initial comment with regards to the Runnable interface.

>> b. an implied reference to Test in Callback (the latter needs to call a method in the former)

Surely all implementations of callbacks will rely on this to some extent.  Even with the Observer/Observable, the update method has to be called.

However, it is more general than using the specific interface.
0
 
LVL 92

Expert Comment

by:objects
ID: 9675337
> However, it is more general than using the specific interface.

Surely an approach that allows you to define the exact callback that you want to use would be preferable to using a generic interface that may not meet your needs. And what if you had different methods that needed to be called depending on circumstance.
Using Observer would also require any class that wants to use it to extend Observable which is another unnecesary limitation, which may in fact preclude it's use in some cases.

0
 
LVL 5

Author Comment

by:lwinkenb
ID: 9675354
>>You should also be careful about tight coupling/circular references.
This is exactly what I am trying to avoid.  This is why I dont want to have any sort of reference to the Test class in my CallBack class.

>> an implied reference to Test in Callback
I'm not sure exactly what you mean by implied reference.  
>> (the latter needs to call a method in the former)
Isnt this exactly what a callback is in the first place?

Maybe I need to clarify a little bit here.

In c++ you would accomplish this task by doing something like:

//this code is in the test class
Callback callback = new Callback("myMethodInTest");

Then in your test class you would have the method myMethodInTest declared.

Another way is you could pass Callback a pointer to the function in test.

0
 
LVL 5

Author Comment

by:lwinkenb
ID: 9675362
Objects >> I like the idea of using reflection, but what if the method takes arguments?  Would it still work?
0
 
LVL 15

Expert Comment

by:jimmack
ID: 9675369
>> And what if you had different methods that needed to be called depending on circumstance.

Isn't this why the update method can take an object as a parameter.  (Bit of a stretch, less efficient, but more general ;-))

Can anyone clarify why CEHJ qualified the first comment?  Why does the use of Runnable make a difference?
0
 
LVL 92

Expert Comment

by:objects
ID: 9675374
> Another way is you could pass Callback a pointer to the function in test.

Thats basically what my first example does.

> but what if the method takes arguments?

Then you need to also pass any array specifying the parameter types.
0
 
LVL 92

Expert Comment

by:objects
ID: 9675377
> Why does the use of Runnable make a difference?

It doesn't.
0
 
LVL 5

Author Comment

by:lwinkenb
ID: 9675650
Thanks for the comments everyone.  I think Reflection is the way I'm going to go with this, because it provides the most flexibility.

Thanks for all the help.
0
 
LVL 92

Expert Comment

by:objects
ID: 9675703
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9677802
>>Can anyone clarify why CEHJ qualified the first comment?

Well, it's not that it would make any difference if it were a Runnable or not. I just thought the final form might be different and was trying to get a bit closer to that.
A false emphasis ;-)
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

An old method to applying the Singleton pattern in your Java code is to check if a static instance, defined in the same class that needs to be instantiated once and only once, is null and then create a new instance; otherwise, the pre-existing insta…
In this post we will learn how to connect and configure Android Device (Smartphone etc.) with Android Studio. After that we will run a simple Hello World Program.
Viewers learn about the third conditional statement “else if” and use it in an example program. Then additional information about conditional statements is provided, covering the topic thoroughly. Viewers learn about the third conditional statement …
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…

828 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question