1

I am struggling with the following:

  1. The class is constructed through Spring
  2. It implements the interface that consist of two methods (process, shutdown)
  3. It also implements Callable

The problem: process() returns a Type and it is called inside the call(), the problem is that process has input parameters which call() signature doesn’t allow. So I referred to this question: Is there a way to take an argument in a callable method?, unfortunately that wouldn't work for me as my object constructed through Spring, process() gets called from the JSP and the input parameters are variable, depending on the user action.

Will include some code for clarification, bellow:

public class MyClass implements MyClassInterface, Callable<Results> {

   private String fileLocation;
   private final SMTPMailer smtpMalier;

   public MyClass(String fileLocation, SMTPMailer smtpMalier) {
      this.fileLocation = fileLocation;
      this.smtpMalier = smtpMalier;
   }

   public Results call() {
      // to return process(arg1, arg2) here, need to cater for input parameters
   }

   public Results process(String arg1, String arg2) {
      // does some proceeding, returns Results
   }

   public void shutdown() {
      // shut down implementation
   }
}

How can I go around this?

Community
  • 1
  • 1
Sasha
  • 1,500
  • 4
  • 14
  • 25
  • Would be better, if you share with us you use it. From other side why just don't call `process` since it is `public` method? – Artem Bilan Mar 24 '15 at 08:10
  • That is the current implementation, but I need MyClass to be runnable and to take input parameters as well. – Sasha Mar 24 '15 at 08:12

1 Answers1

2

Short answer is, you can't. The contract of Callable is that it can perform an action without any input. If it needs parameters, it isn't Callable.

You need to consider how the code is called. I assume you have code like this:

AsyncTaskExecutor executor = ...;
MyClass theService = ...;
String foo = "apple", bar = "banana";
Future<Results> result = executor.submit(theService); // Needs foo and bar :(

The simple solution is, don't implement Callable in MyClass. It isn't callable, it needs some input parameters! Implement Callable where it makes sense instead, such as where you have all parameters:

AsyncTaskExecutor executor = ...;
MyClass theService = ...;
String foo = "apple", bar = "banana";
Future<Results> result = executor.submit(new Callable<Results>(){
    @Override public Results call(){
        return theService.process(foo, bar);
    }
});
// Or if you're on Java 8:
Future<Results> result = executor.submit(() -> theService.process(foo, bar);

If this is something that happens a lot and you really really want the class to provide you with Callables, you could give it a factory method:

public class MyClass implements MyClassInterface {
   public Results process(String arg1, String arg2) {
      // does some proceeding, returns Results
   }
   public Callable<Results> bind(String arg1, String arg2) {
      return () -> process(arg1, arg2);
   }
   // Other methods omitted
}
gustafc
  • 28,465
  • 7
  • 73
  • 99