Как переопределить `org.elasticsearch.client.FilterClient#doExecute()` в Scala?

Конкретно с "org.elasticsearch" % "elasticsearch" % "2.4.x" (он работает с более поздними версиями ElasticSearch, где ActionRequest больше не принимает тип параметра, но мы пока не можем его обновить!).

Метод Java, который мы пытаемся переопределить, определяется следующим образом ( источник):

protected <Request extends ActionRequest, Response extends ActionResponse, RequestBuilder extends ActionRequestBuilder<Request, Response, RequestBuilder>> void doExecute(Action<Request, Response, RequestBuilder> action, Request request, ActionListener<Response> listener) {
    in().execute(action, request, listener);
}

Наивная попытка переопределить это...

import org.elasticsearch.action._
import org.elasticsearch.client.{Client, FilterClient}

class DemoFilterClient(underlyingClient: Client) extends FilterClient(underlyingClient) {
  override def doExecute[
    Request <: ActionRequest[_],
    Response <: ActionResponse,
    RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]
  ](
    action: Action[Request, Response, RequestBuilder],
    request: Request,
    listener: ActionListener[Response]
  ) = super.doExecute(action, request, listener)
}

... происходит сбой во всех версиях Scala, которые мы пробовали (2.11.11, 2.11.12 и 2.12.4):

[info] Compiling 1 Scala source to /home/roberto/development/elasticsearch-scala-client-test/target/scala-2.11/classes ...
[error] /home/roberto/development/elasticsearch-scala-client-test/src/main/scala/com/gu/DemoFilterClient.scala:7:101: type arguments [Request,Response,RequestBuilder] do not conform to class ActionRequestBuilder's type parameter bounds [Request <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],Response <: org.elasticsearch.action.ActionResponse,RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]]
[error]   override def doExecute[Request <: ActionRequest[_], Response <: ActionResponse, RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]](action: Action[Request, Response, RequestBuilder], request: Request, listener: ActionListener[Response]) = super.doExecute(action, request, listener)
[error]                                                                                                     ^
[error] one error found

Чтобы более четко изложить эту ошибку компилятора:

type arguments
[Request,Response,RequestBuilder]
do not conform to class ActionRequestBuilder's type parameter bounds
[
  Request <: 
    org.elasticsearch.action.ActionRequest[_ <: 
      org.elasticsearch.action.ActionRequest[_ <: 
        org.elasticsearch.action.ActionRequest[_ <: AnyRef]]],
  Response <: org.elasticsearch.action.ActionResponse,
  RequestBuilder <: org.elasticsearch.action.ActionRequestBuilder[Request,Response,RequestBuilder]
]

Обратите внимание, что удивительная рекурсивная декларация Request тип!

пример проекта SBT доступен по адресу https://github.com/guardian/elasticsearch-scala-client-test

1 ответ

Решение

Я сталкивался с ситуациями, когда у вас есть такой F-ограниченный полиморфизм с необработанным Java-типом, и если я правильно помню, что-то вроде этого должно работать (по крайней мере, это компилируется в вашем примере проекта):

package com.gu

import org.elasticsearch.action._
import org.elasticsearch.client.{Client, FilterClient}

class DemoFilterClient(underlyingClient: Client)
    extends FilterClient(underlyingClient) {

  type AR[x <: ActionRequest[x]] = ActionRequest[x]

  override def doExecute[
    Request <: AR[_],
    Response <: ActionResponse,
    RequestBuilder <: ActionRequestBuilder[Request, Response, RequestBuilder]
  ](
    action: Action[Request, Response, RequestBuilder],
    request: Request,
    listener: ActionListener[Response]
  ) = super.doExecute(action, request, listener)
}

Похоже, что это также должно быть возможно сделать в forSome, но ни одна из итераций, которые я только что попробовал, не сработала.

Другие вопросы по тегам