I'm trying to understand how to best add something like Jest to Play.
In Play's 2.5.x dependency injection documentation, they show how to add singletons, which can be then be injected when needed via constructor injection.
While this makes perfect sense for classes I write, I don't really understand how to inject something like Jest, which is instantiated via a factory:
JestClientFactory factory = new JestClientFactory();
factory.setHttpClientConfig(new HttpClientConfig
.Builder("http://localhost:9200")
.multiThreaded(true)
//Per default this implementation will create no more than 2 concurrent connections per given route
.defaultMaxTotalConnectionPerRoute(<YOUR_DESIRED_LEVEL_OF_CONCURRENCY_PER_ROUTE>)
// and no more 20 connections in total
.maxTotalConnection(<YOUR_DESIRED_LEVEL_OF_CONCURRENCY_TOTAL>)
.build());
JestClient client = factory.getObject();
In my controllers, how am I supposed to correctly inject Jest? Do I create a jest factory wrapper, and then in the constructor call getObject()
? It doesn't seem like an ideal solution at all.
JestFactoryWrapper.java
@Singleton
class JestFactoryWrapper {
private JestFactory jestFactory;
JestFactoryWrapper() {
this.jestFactory = ...
}
public JestFactory getObject() {
return this.jestFactory.getObject()
}
}
ApiController.java
@Inject
ApiController(JestFactoryWrapper jestFactory) {
this.jestClient = factory.getObject();
}
From documentation:
JestClient
is designed to be singleton, don't construct it for each request!
https://github.com/searchbox-io/Jest/tree/master/jest
So injecting a factory is not a good choice.
I suppose it will be good to create a JestClient
by the factory and bind class to the instance:
Example
Module:
public class Module extends AbstractModule {
@Override
protected void configure() {
...
bind(JestClient.class).toInstance(jestFactory.getObject());
...
}
}
Usage:
@Inject
ApiController(JestClient jestClient) {
this.jestClient = jestClient;
}
Create a provider singleton.
@Singleton
public class JestClientProvider implements Provider<JestClient> {
private final JestClient client;
@Inject
public JestClientProvider(final Configuration configuration, final ApplicationLifecycle lifecycle) {
// Read the configuration.
// Do things on the start of the application.
...
client = jestFactory.getObject();
lifecycle.addStopHook(() -> {
// Do things on the stop of the application.
// Close the connections and so on.
})
}
@Override
public JestClient get() {
return client;
}
}
Bind it in the the module:
bind(JestClient.class).toProvider(JestClientProvider.class).asEagerSingleton();
Use it:
@Inject
ApiController(JestClient jestClient) {
this.jestClient = jestClient;
}