Search code examples
javaclojureclojure-java-interop

calling clojure from Java (Clojure Interop)


Calling Java from Clojoure is quite simple and straightforward but the inverse has proven to be unpredictable.

They seem to be two ways of doing it:

1)the following classes

      i) import clojure.java.api.Clojure; ,
     ii) import clojure.lang.IFn;

2)compile your clojure into an uberjar then import it into the java code.

I have opted for the 2nd option as it's more straight forward.

Here is the clojure code

(ns com.test.app.service
 (:gen-class
       :name com.test.app.service
       :main false
       :methods [^{:static true} [returned [int] int]]))

    (defn returned
      [number]
      (* 2 number))

    (defn -returned
      [number]
      (returned number))

Here is the Java code.

package com.s.profile;

import java.util.*;
import com.microsoft.azure.serverless.functions.annotation.*;
import com.microsoft.azure.serverless.functions.*;
import com.test.app.service;


/**
 * Azure Functions with HTTP Trigger.
 */
public class Function {
    /**
     * This function listens at endpoint "/api/hello". Two ways to invoke it using "curl" command in bash:
     * 1. curl -d "HTTP Body" {your host}/api/hello
     * 2. curl {your host}/api/hello?name=HTTP%20Query
     */
    @FunctionName("hello")
    public HttpResponseMessage<String> hello(
            @HttpTrigger(name = "req", methods = {"get", "post"}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {
        context.getLogger().info("Java HTTP trigger processed a request.");

        // Parse query parameter
        String query = request.getQueryParameters().get("name");
        String name = request.getBody().orElse(query);

        if (name == null) {
            return request.createResponse(400, "Please pass a name on the query string or in the request body");
        } else {
            service.returned(4);
            context.getLogger().info("process data" );
            return request.createResponse(200, "Hellos, " + name );
        }
    }
}

When ever I make the "service.returned(4);" the system never returns. I can't quite figure out why to me it comes off like the function doesn't return from Clojure but I can't see the cause.

Just to add some context I have tried it when its a simple hello world java app which just prints out the result and it works. It's when I try implement it in the Azure functions.


Solution

  • I followed these instructions and it seemed to resolve the error of class not found. It seems as though when running the command

    mvn azure-functions:run
    

    It doesn't automatically find all imported libraries. You either have to use

    1. maven-assembly-plugin
    2. maven-shade-plugin