0

I am working on a maven managed Java project. The goal is to read tasks from a JSON file and process them. We also try to keep the whole project modular. Therefore we have a core-project and many modules. The basic idea is, that the core defines the tasks, how to retrieve them ... and the module is performing the task.

I've read a lot about circular dependencies or Dependency Inversion and how to avoid them in theory. However I am unable to put those examples and methods into practice and I am not quite sure if this is my problem. Therefore I was hoping someone kind point me into the right direction. Here's my issue (simplified):

I read "tasks" from a JSON file and convert them into an array using GSON.

[
  {
    "name": "Do_SOMETHING_1",
    "arguments": "myArgs, myArgs_devided_by_comma",
    "network": [
      {
        "start_ip": "192.168.1.1",
        "end_ip": "192.168.1.255"
      }
    ]
  },
  {
    "name": "Do_SOMETHING_2",
    "arguments": "myArgs, myArgs_devided_by_comma"
  }
]

My Task.class looks like this:

public class Task {
    private String name;
    private String arguments;
    private List<network> network;

    public String getType() {
        return command.toLowerCase();
    }

    public String[] getArgs() {
        String[] args = arguments.split("\\,");
        return args;
    }

    @Override
    public String toString() {
        return name + " - " + arguments;
    }
}


class network {
    private String start_ip;
    private String end_ip;

    @Override
    public String toString() {
        return start_ip + " - " + end_ip;
    }
}

To handle the Tasks I wrote a Jobs class which checks for jobs, builds the array of tasks and then tries to instantiate a new class to process the task depending on what the JSON file specified. It looks like this:

public class Job {
    public static Task[] task;
    ExecutorService executor = Executors.newFixedThreadPool(25);

    public void run() {
        try {
            fetch_jobs();
        } catch (IOException e) {
        //Handle e
        }
        process_jobs();
        executor.shutdown();
        while (!executor.isTerminated()) {
        //Wait until exit
        }

    }

    public void fetch_jobs()  throws UnsupportedEncodingException, IOException  {
        Reader reader = new InputStreamReader(Job.class.getResourceAsStream("/tasks.json"), "UTF-8");
        Gson gson = new GsonBuilder().create();
        task = gson.fromJson(reader, Task[].class);
    }   

    private void process_jobs() {
        for (int i = 0; i < task.length; i++) {
            switch(task[i].getType()) {
            case "Do_SOMETHING_1":
                Runnable worker1 = new Do_SOMETHING_1(task[i]);
                executor.execute(worker1);
                break;
            case "Do_SOMETHING_2":
                Runnable worker2 = new Do_SOMETHING_2(task[i]);
                executor.execute(worker2);
                break;
            default: 
            //Do Nothing
            }}      }
}

Do_SOMETHING_1 and Do_SOMETHING_2 are maven modules which currently depend on the core so they know what a task is and so I can pass along the task-type-variable (task[i]).

The Problem is that in the core application I need to call Do-SOMETHING_1 and Do_SOMETHING_2. Therefore the core needs to depend on the modules, which is not good I guess. However how could I pass the task along so that Do_SOMETHING_1 can access those information. E.g. Network and arguments... ?

Any help is appreciated since I am really stressed out here.

Hierarchy:

Module(Do_SOMETHING_1) depends on CORE

Module(Do_SOMETHING_2) depends on CORE

CORE depends on Module(Do_SOMETHING_1) <-- WRONG

CORE depends on Module(Do_SOMETHING_2) <-- WRONG

Cheers, Stephanie.

Stephanie
  • 101
  • 1
  • 6

1 Answers1

0

You shouldn't hard-code the implementation classes into the switch like that; it essentially eliminates all the advantages of polymorphism. Instead, use an Abstract Factory to instantiate the Runnable for the operation.

This is a case where Java's Service Provider Interface is perfect; it essentially allows you to scan for implementations (plugins) of some interface at runtime, and isn't difficult to use. See the javax.crypto API for an example of how this works in practice.

chrylis -cautiouslyoptimistic-
  • 75,269
  • 21
  • 115
  • 152
  • Hello! Thank you for your reply. However I am still confused. I tried to build an abstract class around the task. Doing so is breaking the GSON mapping. Would you mind clarifying your approach? Maybe even integrate my example above. Thank you again and sorry for being such a pain. --Stephanie – Stephanie Oct 30 '14 at 20:18