I need to make a Server socket in a web application that listen for Asterisk AGI requests but i need to enable CDI injection in the socket, don't know how to do that.
Today i already have this socket working very well, the problem is i can't inject a CDI bean with the socket.
Ex:
class RequestProcessor implements Runnable
{
private Socket socket;
@Inject
private PhoneService phoneService;
@Override
public void run()
{
// Do the logic here
}
}
Method that receives the request and send to a pool.
ExecutorService pool = Executors.newCachedThreadPool();
ServerSocket server = new ServerSocket(25000);
Socket client = server.accept();
pool.execute(new RequestProcessor(client));
It's not the production code, it's just a illustrated example!
I can't make the @Inject PhoneService phoneService works.
As we've already established, new
ing the RequestProcessor
won't populate the @Inject
-annotated field since new
completely cuts out the DI system. So you need a way to bring it in.
Your goal looks particularly non-trivial because RequestProcessor
wants a DI-provided dependency (phoneService
) and one that you provide programmatically (socket
). As a general rule I would advise against mixing the two where possible – once you're using DI, it wants to spread like a virus. Let that happen. If you can design your system so that (almost) everything is injected for you, that's fanstastic!
That said, your situation is completely workable.
It looks like you have some method in some class which is a potential injection site. Assuming that this unknown class is in fact created by CDI you could @Inject
the PhoneService
into that class, and then pass it to the RequestProcessor
constructor:
public class SomeClass {
@Inject
private PhoneService phoneService;
private void someMethod() {
ExecutorService pool = Executors.newCachedThreadPool();
ServerSocket server = new ServerSocket(25000);
Socket client = server.accept();
pool.execute(new RequestProcessor(client, phoneService));
}
}
Or you could use a factory to create RequestProcessor
instances, which will basically have the same effect in the end. You can write this factory by hand, which will look pretty familiar:
public class RequestProcessorFactory {
@Inject
private PhoneService phoneService;
public RequestProcessor createNewProcessor(Socket socket) {
return new RequestProcessor(socket, phoneService);
}
}
then inject an instance of that factory into your class:
public class SomeClass {
@Inject
private RequestProcessorFactory requestProcessorFactory;
private void someMethod() {
ExecutorService pool = Executors.newCachedThreadPool();
ServerSocket server = new ServerSocket(25000);
Socket client = server.accept();
pool.execute(requestProcessorFactory.createNewProcessor(client));
}
}
There's a third way that you can do it, which is similar to Guice's assisted injection. Effectively it just generates that factory implementation for you, if you provide the interface. To my knowledge, CDI does not support this, but there is at least one CDI extension which does.
Happy DI-ing!