java

seancorfield 2019-02-25T00:00:16.005200Z

So it's (.create s blob-info (bytes b) (into-array BlogTargetOption []))

2019-02-25T02:52:23.005400Z

user=> (.create s blob-info (bytes b) (into-array Storage$BlobTargetOption []))

java.lang.IllegalArgumentException: No matching method create found taking 3 args for class com.google.cloud.storage.StorageImpl
user=> 

2019-02-25T02:53:00.005900Z

variadic is the ellipsis after the BlobTargetOption, ya?

2019-02-25T02:54:51.006300Z

got the same exception when using just b instead of (bytes b) as well

2019-02-25T02:55:41.006700Z

i got access to BlobStorageOption from user=> (import [com.google.cloud.storage Storage$BlobTargetOption])

seancorfield 2019-02-25T03:05:17.007400Z

@hoopes You may need to type hint blob-info as well... It depends how many overloads create has...

2019-02-25T03:07:58.008100Z

user=> (.create s [^BlobInfo blob-info] b (into-array Storage$BlobTargetOption []))

java.lang.IllegalArgumentException: No matching method create found taking 3 args for class com.google.cloud.storage.StorageImpl

seancorfield 2019-02-25T03:08:00.008300Z

Hmm, it has half a dozen overloads... no wonder it's tough to call šŸ˜ž

2019-02-25T03:08:08.008600Z

is that right? just pulled from the java interop page

2019-02-25T03:08:24.009200Z

this function call is looking funnier and funnier šŸ™‚

seancorfield 2019-02-25T03:08:28.009300Z

(.create ^BlobInfo blob-info ...) -- you passed a vector there

2019-02-25T03:09:01.009500Z

user=> (.create s ^BlobInfo blob-info b (into-array Storage$BlobTargetOption []))

java.lang.IllegalArgumentException: No matching method create found taking 3 args for class com.google.cloud.storage.StorageImpl

2019-02-25T03:09:24.009800Z

also tried with (bytes b)

2019-02-25T03:09:26.010Z

same result

seancorfield 2019-02-25T03:10:55.010600Z

I've seen people struggle with Google libraries because of this sort of stuff... ĀÆ\(惄)/ĀÆ

2019-02-25T03:11:14.011Z

haha, so obviously i don't want or expect you to sit here and fiddle with this with me, but it IS possible, right?

seancorfield 2019-02-25T03:11:25.011200Z

Sure. Definitely possible šŸ™‚

seancorfield 2019-02-25T03:12:04.011900Z

I'm happy to try it locally if I know what library you're pulling in (lein/deps coords) and what the code around this looks like

2019-02-25T03:12:07.012100Z

user=> (set! *warn-on-reflection* true)
true
user=> (.create s ^BlobInfo blob-info (bytes b) ^Storage$BlobTargetOption (into-array Storage$BlobTargetOption []))
Reflection warning, /tmp/form-init4534991595574875173.clj:1:1 - call to method create can't be resolved (target class is unknown).

2019-02-25T03:12:12.012300Z

does that make any sense?

2019-02-25T03:12:29.012700Z

[com.google.cloud/google-cloud-storage "1.63.0"]

seancorfield 2019-02-25T03:12:32.012800Z

What are s and b?

2019-02-25T03:13:15.013Z

(import [com.google.cloud.storage
            StorageOptions
            BlobId
            BlobInfo])

2019-02-25T03:13:54.013400Z

(def s (-> (StorageOptions/getDefaultInstance) (.getService)))

2019-02-25T03:14:24.013600Z

(defn ->blob-info [bucket storage-key]
  (let [content-type "text/plain" 
        blob-id (BlobId/of bucket storage-key)
        blob-info (doto
                    (BlobInfo/newBuilder blob-id)   
                    (.setContentType content-type)  
                    (.build))]
    blob-info))

2019-02-25T03:14:59.014100Z

(def b (.getBytes "whoa baby"))

seancorfield 2019-02-25T03:18:37.014900Z

Dinner time here. Will try the code in 10-15 mins

2019-02-25T03:18:56.015300Z

would greatly appreciate - i have a new baby, and must go attend, but i will check back

2019-02-25T03:19:01.015500Z

thanks so very much!

2019-02-25T03:25:10.015900Z

a hopefully more usable version:

2019-02-25T03:25:12.016100Z

(ns my-lib.utils.gcp.storage
  (:require [<http://clojure.java.io|clojure.java.io> :as io])
  (:import [com.google.cloud.storage
            StorageOptions
            BlobId
            BlobInfo
            Storage$BlobTargetOption ]))

(defn get-storage []
  (-&gt; (StorageOptions/getDefaultInstance)
      (.getService)))

(defn get-blob-info [bucket storage-key]
  (let [content-type "text/plain"
        blob-id (BlobId/of bucket storage-key)]
    (doto
      (BlobInfo/newBuilder blob-id)
      (.setContentType content-type)
      (.build))))

(defn upload-str [bucket storage-key str-to-store]
  (let [storage (get-storage)
        blob-info (get-blob-info bucket storage-key)
        byte-arr (.getBytes str-to-store)]
    (.create storage blob-info byte-arr (into-array Storage$BlobTargetOption []))))

2019-02-25T03:25:39.016400Z

user=&gt; (require '[my-lib.utils.gcp.storage :as storage])
user=&gt; (storage/upload-str "my-bucket" "some-new-file.txt" "whoa buddy")

java.lang.IllegalArgumentException: No matching method create found taking 3 args for class com.google.cloud.storage.StorageImpl

seancorfield 2019-02-25T03:29:12.017300Z

Based on that, you almost certainly need to type hint the get-storage and get-blob-info functions (add a type hint before the arglist).

2019-02-25T03:33:43.017600Z

(ns my-lib.utils.gcp.storage
  (:require [<http://clojure.java.io|clojure.java.io> :as io])
  (:import [com.google.cloud.storage
            Storage
            StorageOptions
            BlobId
            BlobInfo
            Storage$BlobTargetOption ])) 

(defn get-storage ^Storage []
  (-&gt; (StorageOptions/getDefaultInstance)
      (.getService)))

(defn get-blob-info ^BlobInfo [bucket storage-key]
  (let [content-type "text/plain"
        blob-id (BlobId/of bucket storage-key)]
    (doto
      (BlobInfo/newBuilder blob-id)
      (.setContentType content-type)
      (.build))))

(defn upload-str [bucket storage-key str-to-store]
  (let [storage (get-storage)
        blob-info (get-blob-info bucket storage-key)
        byte-arr (.getBytes str-to-store)]
    (.create storage
             blob-info
             byte-arr
             (into-array Storage$BlobTargetOption []))))

2019-02-25T03:34:02.018100Z

still same šŸ™‚ type hint the stuff in the (.create ...) call as well?

seancorfield 2019-02-25T03:34:33.018300Z

Try (bytes byte-arr)

2019-02-25T03:35:16.018500Z

(defn upload-str [bucket storage-key str-to-store]
  (let [storage (get-storage)
        blob-info (get-blob-info bucket storage-key)
        byte-arr (.getBytes str-to-store)]
    (.create storage
             ^BlobInfo blob-info
             (bytes byte-arr)
             (into-array Storage$BlobTargetOption []))))

2019-02-25T03:35:21.018700Z

aaaaaaaaaand still same error

seancorfield 2019-02-25T03:35:41.019200Z

You don't need the type hint on blob-info if you have the type hint on the function

2019-02-25T03:35:51.019500Z

yeah, i didn't think so, just grasping at straws a bit

seancorfield 2019-02-25T03:36:51.020Z

This works

user=&gt; (import '(com.google.cloud.storage Storage))
com.google.cloud.storage.Storage
user=&gt; (import '(com.google.cloud.storage BlobInfo))
com.google.cloud.storage.BlobInfo
user=&gt; (import '(com.google.cloud.storage Storage$BlobTargetOption))
com.google.cloud.storage.Storage$BlobTargetOption
user=&gt; (defn get-storage ^Storage [] nil)
#'user/get-storage
user=&gt; (defn get-blob-info ^BlobInfo [] nil)
#'user/get-blob-info
user=&gt; (.create (get-storage) (get-blob-info) (byte-array []) (into-array Storage$BlobTargetOption []))
Execution error (NullPointerException) at user/eval158 (REPL:1).
null

seancorfield 2019-02-25T03:37:10.020500Z

(The NPE is from inside the call -- so it resolves the constructor just fine)

2019-02-25T03:38:03.020800Z

so you think the functions might be doing the wrong thing

seancorfield 2019-02-25T03:38:33.021300Z

The only variable at this point is byte-arr -- so that needs to be the correct type.

2019-02-25T03:40:42.021500Z

dumb question:

2019-02-25T03:40:44.021700Z

user=&gt; (def blob-info (storage/get-blob-info "bossjock-convert" "new-file.txt"))
#'user/blob-info
user=&gt; blob-info
#object[com.google.cloud.storage.BlobInfo$BuilderImpl 0x3c690936 "com.google.cloud.storage.BlobInfo$BuilderImpl@3c690936"]

2019-02-25T03:41:17.022400Z

it's a BuilderImpl, not explicitly a BlobInfo - but that shouldn't matter to java - does it matter to clojure matching the function to a java method signature?

seancorfield 2019-02-25T03:42:40.022900Z

That's why I used nil -- I'm trying to eliminate the values and focus on the type hints first.

seancorfield 2019-02-25T03:43:44.023600Z

Since that works (for me), the possibilities are that your byte-arr is the wrong type (or needs a type hint).

seancorfield 2019-02-25T03:44:04.024100Z

once you have the types working, you can look at the mechanics of your functions.

seancorfield 2019-02-25T03:44:47.025100Z

I certainly would not expect a function that returns a BuildImpl to be compatible with a BlobInfo tho'... that seems wrong to me...

2019-02-25T03:47:20.025500Z

ok - i'm sorry, i have to handle real-life stuff for a bit

2019-02-25T03:47:28.025800Z

i really appreciate your help, and will continue working

2019-02-25T03:47:38.026100Z

if we ever meet, i owe you whatever drink you choose

seancorfield 2019-02-25T03:49:42.026800Z

OK, your problem is calling .build inside doto -- that will return the builder instead of the built thing.

seancorfield 2019-02-25T03:50:19.027400Z

You want (.build (doto (BlobInfo/newBuilder blob-id) (.setContentType content-type)))

2019-02-25T03:51:44.027600Z

BOO YAH

2019-02-25T03:51:53.027900Z

that baby can wait! (jk jk jk jk)

2019-02-25T03:52:50.028800Z

ok, seriously, i have to attend to the baby - you are the man, and if we ever meet, it's a party

2019-02-25T03:52:57.029Z

thanks man, you're a hero

seancorfield 2019-02-25T03:53:21.029200Z

glad it worked