2

I'm working on a networking project in Java where I want to send some executable code from Node A to Node B and have Node B return the result of the executed code back to Node A.

The way I went about trying to do this (Which I now know isn't suitable for my use case) was to define an abstract class called Job which had an abstract method run(). It looks something like this:

import java.io.Serializable;

public abstract class Job implements Serializable {

  public String id;

  public Job(String id) {
      this.id = id;
  }

  public abstract void run();

}

I was then planning to be instantiate children classes from Job, defining the run method and to send the derived class from Node A to Node B using the built in ObjectOutputStream and ObjectInputStream and have simply have Node B call the run() method when it received a job.

However this goes beyond what can be done with a Serialized Object sent though the ObjectOutputStream as Node B would need the exact definition of the class being sent from Node A - which it can't have as each Job will be of a different sub type and will have different definitions of the run() method.

Does anyone know of any other way to do this? A way to send executable code from Node A to Node B and have Node B execute the code?

I know I could probably just create .jars and send them through the OutputStream, and have Node B execute them. But if there is any way I could do this with having a base Job class that I can extend and instantiate from to define different types of Jobs and send those Jobs to Node B?

Any help or suggestions would be greatly appreciated!! Thanks in advance! :)

mickzer
  • 5,958
  • 5
  • 34
  • 57

3 Answers3

2

I think you are right - this is not possible. If you use object output streams, the name of the concrete class is part of the transferred operation; so you need the class definition on the other side (because the JVM will want to load the .class file for the object you transferred). So the .class file needs to exist on both sides.

I don't see any other option than sending .class or .jar files and to use reflection to execute the corresponding code.

EDIT: but using reflection ... does still allow you to build different job classes on node A. It still makes sense to organize your classes in a meaningful way; even when you have to transfer them first and then use reflection to invoke them.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
  • Yeah this is what I was thinking too, it slightly takes away from what I'm trying to achieve but I can't seem to find any other way to do it... Thanks for your help! – mickzer Mar 22 '15 at 15:26
2

You can do exactly this via RMI and the codebase feature.

user207421
  • 305,947
  • 44
  • 307
  • 483
2

To add to EJP's answer, what you need is a dynamic networked class loading facility, which must be able to fetch the bytecode of classes that are not in the local classpath of your application.

Yes, the codebase feature of an RMI Server should allow you to do that, provided the location of the jars can be expressed as a URL and you have a server infrastructure (or URL handler) to serve it.

I also know of two open source grid computing frameworks which provide this kind of facility implicitely and transparently for the API users: JPPF and GridGain.

Disclaimer: I'm the main JPPF developer.

Lolo
  • 4,277
  • 2
  • 25
  • 24
  • The codebase link in the answer actually points to javadoc of `java.util.List`, maybe [codebase](http://docs.oracle.com/javase/7/docs/technotes/guides/rmi/codebase.html)? – prunge Mar 23 '15 at 06:44
  • yes, thanks for catching this! The link is now fixed – Lolo Mar 23 '15 at 06:55