0

I am writing a library in Java. A object in the library is referenced by the main application.

The application requires a method to be called at a certain point on one of its objects. The library object wants to invoke this method in the application, with parameters.

I do not want to pass the application object to the library object as a reference because I want it loosely coupled and the Application object is specific to that application. If I pass it just as a Object data type, it will not have the method attached as not that type without casting.

As they are separate jars, static will not work either and want it loosely coupled again.

Example

Application A is running and has class watched. In its own jar.

public class WatchedInApplication extends BaseRichBolt { 
// has a reference to the lib class
private WatcherInLibrary lib;
...
  public void invoke (string.. args) {
    // invoke this method from another jar reference as a API.
    // to replay some data.
    outputCollector.emit(args)
  }    
}

The library B is referenced by Application A and it wants to invoke a method in a object in Application A at a certain point. This library B is also another jar, that is running and monitoring Application A.

public class WatcherInLibrary {
  public void invokeApplicationsinvokeMethod() {
     // invoke the applications method invoke, but with no specific      reference to it
    // basically want to invoke the output collector.emit to replay tuples.
  } 

}

Points

I could simply pass the outputcollector or the BaseRichBolt to the library class B. But I want to keep it loosely coupled. Also both applications are referencing Storm which may cause future issues, even if no issues it is tied closely to Storm if I start passing outputcollector or BaseRichBolt around.

  • Does a clever design pattern exist? Simply user interface see below
perkss
  • 1,037
  • 1
  • 11
  • 37
  • Unclear, post some sample code. Have you defined an interface for the object type your code expects? – PM 77-1 Aug 01 '15 at 02:09
  • @PM77-1 tried to explain further. – perkss Aug 01 '15 at 02:18
  • 1
    You have not answered my interface question. Between specific type and just plain Object there's a nice middle point: interface type. – PM 77-1 Aug 01 '15 at 02:34
  • @PM77-1 the object I do not want to pass explicitly is not written by me its a library. An Apache Storm OutputCollector to be precise. Thats the application A that is required and it is in a BaseRichBolt. Unless I create my own interface to wrap around this object? Could you expand a little please? I will try and add more detail to the question. – perkss Aug 01 '15 at 02:40
  • This is exactly where you should use an interface. – chrylis -cautiouslyoptimistic- Aug 01 '15 at 02:59
  • Ok I think I get you now. Make an interface with the method to invoke defined signature. Then implement in WatchedInAppllication. Pass the interface as parameter type. Then can invoke from the watcher. – perkss Aug 01 '15 at 03:04

1 Answers1

0

Following on the comments it was simple. Use an interface that defines a invoke(args) method. Implement the interface on the Bolt object. This can then be passed and is generic. Then called from the library method.

Quick toy example, could be improved by generics on the interface.

WatchedApplication

public class WatchedInApplication implements Invoke {

  private WatcherInLibrary lib;

  public WatchedInApplication(WatcherInLibrary lib) {
    super();
    this.setLib(lib);
  }

  public WatcherInLibrary getLib() {
    return lib;
  }

  public void setLib(WatcherInLibrary lib) {
    this.lib = lib;
  }
  // where the method is implemented. 
  @Override
  public void invokeRemote(String data) {
    System.out.println("Method Invoked " + data.toString());
  }
}

WatcherLibrary

public class WatcherInLibrary {

  private Invoke obj;

  public void setWatchedApplication(Invoke object) {
    this.obj = object;
  }

  public void invokeRemoteObject() {
    this.obj.invokeRemote("data passed");
  }

}

The interface solution

public interface Invoke {
  public void invokeRemote(String data);
}

Example Main

WatcherInLibrary lib = new WatcherInLibrary();
WatchedInApplication watched = new WatchedInApplication(lib);
lib.setWatchedApplication(watched);
lib.invokeRemoteObject();

The use of the interface enables this solution to work with any data type.

perkss
  • 1,037
  • 1
  • 11
  • 37