I just started using dagger 2 and have not used any other dependency injection framework before. Now I'm stuck with a cyclic dependency and I don't know how to solve it properly. Consider the following example in a server application, which uses the Reactor pattern with Java NIO:
I have a Handler
object attached to a selection key that is executed when new information arrives on the network:
class Handler implements Runnable {
Server server;
Client client;
public void run {
// static factory method that eventually calls a method on server, passing in 'client' as argument
Command.parse(input).execute(server, client);
}
public void send(String string) {
// enqueu string and inform reactor about interest in sending
}
}
The Client
class holds some state about the connected client. All connected Clients are managed in the Server
class.
class Client {
Handler h;
public send(String response) {
h.send(response);
}
}
When new input arrives, the Handler creates the Command
objects, executes them on the server, and the server eventually will respond to the client.
So what I'm doing right now, is creating a Client
object manually in Handler
, passing in a this
reference, in order to be able to send the response:
client = new Client(this);
So my question now is: Is something wrong with the design? Is it possible to decouple Client
and Handler
? Or should I just live with this and don't use dependency injection everywhere
?
I appreciate your suggestions
If you want the client to be able to send a message back through handler, then the following can break your cycle:
// lives in a common package both classes access
public interface ResponseClass {
public void sendSomeMessage(String message);
}
public class Handler { // handler can also implement ResponseClass directly but I prefer using an additional class for flexibility.
public void whenYouCreateClient() {
Client client = new Client(new HandlerWrapper(this));
}
public static class HandlerWrapper implements ResponseClass {
private final Handler handler;
public HandlerWrapper(Handler handler) { this.handler = handler; }
public void sendSomeMessage(String message) {
handler.send(message);
}
}
public void send(String string) {
// enqueu string and inform reactor about interest in sending
}
}
public class Client {
ResponseClass rc; // naming should be improved :)
public void sendMessage(String message) {
rc.sendSomeMessage(message);
}
}
Now runtime your classes are still tied together but as far as your design is concerned your Client is only attached to a generic ResponseClass.
you can have a hierarchy like:
common <-- client <-- handler
where handler knows of client and common and client only knows of common. (assuming you put the interface in the common package)
instead of client <--> handler
I deliberately used sendSomeMessage to highlight that it's a different method you call ont he wrapper/interface but ofcourse you can name them however you like.
One remark: I didn't use dagger2 so I cannot say for sure that what I do can be done using that product, but this is how I would decouple this sort of cyclic dependency
I realized that what I really was trying to solve was not breaking the dependency between Client
and Handler
, but to use dependency injection instead of the new
operator.
The solution I was looking for: Inject a ClientFactory
into the constructor of Handler
and use clientFactory.create(this)
to create a Client
object instead. The brilliant library AutoFactory allows you to create such a factory with a simple @AutoFactory
annotation. The constructor of the created class is automatically annotated with @Inject
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With