Want to win a PS4? Go Premium and enter to win our High-Tech Treats giveaway. Enter to Win

x
?
Solved

Callback

Posted on 2003-11-03
21
Medium Priority
?
959 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
[X]
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
  • 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
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
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 2000 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

[Webinar] Lessons on Recovering from Petya

Skyport is working hard to help customers recover from recent attacks, like the Petya worm. This work has brought to light some important lessons. New malware attacks like this can take down your entire environment. Learn from others mistakes on how to prevent Petya like worms.

Question has a verified solution.

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

This was posted to the Netbeans forum a Feb, 2010 and I also sent it to Verisign. Who didn't help much in my struggles to get my application signed. ------------------------- Start The idea here is to target your cell phones with the correct…
Go is an acronym of golang, is a programming language developed Google in 2007. Go is a new language that is mostly in the C family, with significant input from Pascal/Modula/Oberon family. Hence Go arisen as low-level language with fast compilation…
Viewers learn about the “for” loop and how it works in Java. By comparing it to the while loop learned before, viewers can make the transition easily. You will learn about the formatting of the for loop as we write a program that prints even numbers…
Viewers will learn about the regular for loop in Java and how to use it. Definition: Break the for loop down into 3 parts: Syntax when using for loops: Example using a for loop:
Suggested Courses

596 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