Injection for ActionPlugin

A plugin we use has stopped working after upgrading to 5.6 from 5.1. The plugin adds a RestHandler. Here is the old constructor for the RestHandler:
public class TranslateAction implements RestHandler {

	private final Provider<aTranslator> aTranslatorProvider;
	private final Provider<bTranslator> bTranslatorProvider;

    @Inject
    public TranslateAction(final RestController controller, 
            final Provider<aTranslator> aTranslatorProvider,
            final Provider<bTranslator> bTranslatorProvider) {

        controller.registerHandler(Method.GET, "/_translate", this);
        controller.registerHandler(Method.POST, "/_translate", this);
        this.aTranslatorProvider = aTranslatorProvider;
        this.bTranslatorProvider = bTranslatorProvider;
    }
...

In 5.6 upon startup we get the exception

org.elasticsearch.common.inject.CreationException: Guice creation errors:

  1. Could not find a suitable constructor in org.elasticsearch.rest.RestController. Classes must have either one (and only one) constructor annotated with @Inject or a zero-argument constructor that is not private.

Fine. Elsewhere on this site (I cannot find it now) I found a suggestion to NOT inject the RestController but instead have th Plugin implement ActionPlugin and override getRestHandlers in a method that would look like this:

    @Override 
public List<RestHandler> getRestHandlers(Settings settings, RestController restController, ClusterSettings clusterSettings,
        IndexScopedSettings indexScopedSettings, SettingsFilter settingsFilter,
        IndexNameExpressionResolver indexNameExpressionResolver, Supplier<DiscoveryNodes> nodesInCluster) {
    List<RestHandler> list = new ArrayList<>();
    
    Injector injector = Guice.createInjector(new C3POModule());
    TranslateAction ta = injector.getInstance(TranslateAction.class);
    restController.registerHandler(Method.GET, "/_translate", ta);
    restController.registerHandler(Method.POST, "/_translate", ta);
    list.add(ta);
    
    return Collections.unmodifiableList(list);
}

BUT, the problem now is that the TranslateAction class depended on GuiceInjection and gets new errors. One of the dependencies has an @Inject for org.elasticsearch.client.Client. We get an error now saying no implementation for Client is bound.
Prior to this change, the Client injected fine, I believe due to the bind calls in org.elasticsearch.node.Node (line 459):
b.bind(NodeClient.class).toInstance(client);

Without being good at Guice or knowing the proper vocab, I believe the error is this line in the new code:

    Injector injector = Guice.createInjector(new C3POModule());

and instead we need to get the injector created in Node. Is this possible?

Further info:
The plugin relies on the NodeClient class to get an IndicesAdminClient to peform analyze requests.

You should construct your handler without using Guice. The NodeClient is passed in at runtime to rest handlers, for example in prepareRequest, so you should not need it at construction.

Thanks for the reply Ryan. This is what I needed!

This topic was automatically closed 28 days after the last reply. New replies are no longer allowed.