Istvan
Istvan

Reputation: 8582

How to implement an interface with concrete type parameters in Clojure?

I am trying to use AWS Lambda from Clojure. This is the Java code that works:

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;

public class Dbmgmt implements RequestHandler<Object, Object> {

    @Override
    public String handleRequest(Object in, Context ctx) {
        System.out.println("ok");
        ctx.getLogger().log("ok");
        return "ok";
    }
}

This is the Clojure code that does not work.

(defn -handleRequest [this in ctx]
  (reify RequestHandler
    (handleRequest [this in ctx] "ok")))

Using Javap on both classes:

Java:

Compiled from "Dbmgmt.java"
public class com.streambright.Dbmgmt implements com.amazonaws.services.lambda.runtime.RequestHandler<java.lang.Object, java.lang.Object> {
  public com.streambright.Dbmgmt();
  public java.lang.String handleRequest(java.lang.Object, com.amazonaws.services.lambda.runtime.Context);
  public java.lang.Object handleRequest(java.lang.Object, com.amazonaws.services.lambda.runtime.Context);
}

Clojure:

public class dbmgmt implements com.amazonaws.services.lambda.runtime.RequestHandler {
  public static {};
  public dbmgmt();
  public boolean equals(java.lang.Object);
  public java.lang.String toString();
  public int hashCode();
  public java.lang.Object clone();
  public java.lang.Object handleRequest(java.lang.Object, com.amazonaws.services.lambda.runtime.Context);
  public static void main(java.lang.String[]);
}

I was wondering what is the best way to implement an interface with concrete return type. With the current code AWS complains:

"errorMessage": "Class dbmgmt does not implement RequestHandler with concrete type parameters"

Upvotes: 3

Views: 851

Answers (2)

Svante
Svante

Reputation: 51541

It seems that you do not implement the handleRequest method with return class String, only Object. You can give it as a "type hint" to the method name:

(reify RequestHandler
  (^String handleRequest [this ^Object in ^Context ctx] "ok")))

(EDIT: revert edit, but add complete type hints, which seem to be required.)

Upvotes: 3

Istvan
Istvan

Reputation: 8582

The closest I could get to solve this is the following:

(ns dbmgmt
  (:gen-class
    :implements [com.amazonaws.services.lambda.runtime.RequestHandler]
    :methods [[handleRequest [Object com.amazonaws.services.lambda.runtime.Context] String]]))

This generates the following class:

public class dbmgmt implements com.amazonaws.services.lambda.runtime.RequestHandler {
  public static {};
  public dbmgmt();
  public boolean equals(java.lang.Object);
  public java.lang.String toString();
  public int hashCode();
  public java.lang.Object clone();
  public java.lang.Object handleRequest(java.lang.Object, com.amazonaws.services.lambda.runtime.Context);
  public java.lang.String handleRequest(java.lang.Object, com.amazonaws.services.lambda.runtime.Context);
  public static void main(java.lang.String[]);
}

However it still does not have RequestHandler that the Java version has. I believe it is not possible to implement this purely in Clojure as of now.

Upvotes: 0

Related Questions