Search code examples
javaazureclojureazure-storageclojure-java-interop

Clojure - No matching method found


Can't figure out why clojure is telling me this function name can't be found. I'm trying to call the setProperties function on a CloudBlockBlob, which inherits from CloudBlob.

(ns my-ns.infra.azure-blob
  (:import (com.microsoft.azure.storage.blob
             CloudBlob
             CloudBlockBlob
             CloudBlobClient
             CloudBlobContainer
             BlobContainerPublicAccessType
             BlobRequestOptions BlobProperties CloudBlob BlobContainerProperties)
           (com.microsoft.azure.storage
             CloudStorageAccount
             OperationContext
             )))

(def blob (-> "img-manip"
           get-container-cached
           (.getBlockBlobReference "some-file.txt")))


(def props (-> blob
           .getProperties))

How does clojure see the setProperties function? Via clojure.reflect/reflect--

#clojure.reflect.Method{:name setProperties,
                                    :return-type void,
                                    :declaring-class com.microsoft.azure.storage.blob.CloudBlob,
                                    :parameter-types [com.microsoft.azure.storage.blob.BlobProperties],
                                    :exception-types [],
                                    :flags #{:final :protected}}

Is blob cast-able to CloudBlob? Yes:

(cast com.microsoft.azure.storage.blob.CloudBlob blob)
=>
#object[com.microsoft.azure.storage.blob.CloudBlockBlob
        0x7f613b97
        "com.microsoft.azure.storage.blob.CloudBlockBlob@7f613b97"]

Are my properties a BlobProperties? Yes:

(cast com.microsoft.azure.storage.blob.BlobProperties props)
=>
#object[com.microsoft.azure.storage.blob.BlobProperties
        0x55cd6938
        "com.microsoft.azure.storage.blob.BlobProperties@55cd6938"]

What happens when i call .setProperties?

(.setProperties blob props)
     java.lang.IllegalArgumentException: No matching method found: setProperties for class com.microsoft.azure.storage.blob.CloudBlockBlob
clojure.lang.Compiler$CompilerException: java.lang.IllegalArgumentException: No matching method found: setProperties for class com.microsoft.azure.storage.blob.CloudBlockBlob, compiling:(/Users/micahsmith/printio/gooten-preview/gooten-preview-api/src/gooten_preview_api/infra/azure_blob.clj:72:1)

I don't understand.


Solution

  • setProperties is a protected method:

    protected final void setProperties(final BlobProperties properties) {
        this.properties = properties;
    }
    

    What you're doing would work if setProperties were a public method. You can reproduce this by defining similar classes in your Clojure project:

    public abstract class Vehicle {
        public final void go(int miles) {
        }
    }
    public class MonsterTruck extends Vehicle { }
    

    And in Clojure:

    (def truck (MonsterTruck.))
    (.go truck 1) ;; resolves base class method, works
    

    But if you change go to protected final void you'll see the same error you're getting.