Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure Can';t调用非公共类的public方法:public(谷歌云库)_Clojure_Gcloud - Fatal编程技术网

Clojure Can';t调用非公共类的public方法:public(谷歌云库)

Clojure Can';t调用非公共类的public方法:public(谷歌云库),clojure,gcloud,Clojure,Gcloud,我正试图使用图书馆 (ns firengine.state (:import [com.google.cloud AuthCredentials] [com.google.cloud.datastore DatastoreOptions])) (-> (DatastoreOptions/builder) (.projectId "<project_id>") (.authCredentials (AuthCredentia

我正试图使用图书馆

(ns firengine.state
  (:import
   [com.google.cloud AuthCredentials]
   [com.google.cloud.datastore DatastoreOptions]))

(-> (DatastoreOptions/builder)
      (.projectId "<project_id>")
      (.authCredentials
       (AuthCredentials/createForJson
        (clojure.java.io/input-stream service-account-path)))
      .build)
当我从Clojure REPL调用此代码时,我得到以下错误

Unhandled java.lang.IllegalArgumentException
   Can't call public method of non-public class: public
   com.google.cloud.ServiceOptions$Builder
   com.google.cloud.ServiceOptions$Builder.projectId(java.lang.String)

            Reflector.java:   88  clojure.lang.Reflector/invokeMatchingMethod
            Reflector.java:   28  clojure.lang.Reflector/invokeInstanceMethod
boot.user4590132375374459695.clj:  168  firengine.state/eval17529
boot.user4590132375374459695.clj:  167  firengine.state/eval17529
             Compiler.java: 6927  clojure.lang.Compiler/eval
                              ... elided ...
com.google.cloud.datastore.DatastoreOptions
code

2016年6月29日更新: 根据下面的建议,我认为如果我围绕
DatastoreOptions
编译自己的包装器,它可能会工作

(ns firengine.datastore
  (:import
   [com.google.cloud AuthCredentials]
   [com.google.cloud.datastore Datastore DatastoreOptions Entity Key KeyFactory])
  (:gen-class
   :state state
   :init init
   :constructors {[String String] []}))

(defn -init
  [^String project-id ^String service-account-path]
  (let [service-account (clojure.java.io/input-stream service-account-path)
        credentials (AuthCredentials/createForJson service-account)
        dsoptions (-> (DatastoreOptions/builder)
                      (.projectId project-id)
                      (.authCredentials credentials)
                      .build)]
      [[] {:project-id project-id
                 :service-account-path service-account-path
                 :datastore-options dsoptions}]))
我修改了我的
启动开发任务
以包括以下内容:

(deftask development
  "Launch Immediate Feedback Development Environment"
  []
  (comp
   (aot :namespace '#{firengine.datastore})
   (repl :port 6800)
   (reload)
   (watch)
   (cljs)
   (target :dir #{"target"})))
我试图这样构造这个对象:

(def service-account-path (System/getenv "FIRENGINE_SERVICE_ACCOUNT_PATH"))

(def project-id (System/getenv "PROJECT_ID"))

(def datastore-options (firengine.datastore. project-id service-account-path))
不幸的是,我仍然得到同样的错误

    clojure.lang.Compiler$CompilerException: java.lang.reflect.InvocationTargetException, compiling:(state.clj:15:1)
java.lang.reflect.InvocationTargetException: 
         java.lang.IllegalArgumentException: Can't call public method of non-public class: public com.google.cloud.ServiceOptions$Builder com.google.cloud.ServiceOptions$Builder.projectId(java.lang.String)

我不是真的在编译
firengine.datastore

是的。。。。这个问题。你不会相信的,但它实际上是来自。。。等等。。。1999!

你可以更多地了解它

为了避免这种情况,您可能必须制作自己的java包装器,或者考虑到这个众所周知的java bug

如果您不想编写自己的java包装器,并且作者坚持认为“这是最好的设计,就像有史以来一样!”,那么您可以通过使用
(.setAccessible-method-true)
和一些更自定义的反射代码设置方法可访问性来强制实现


祝你好运

正如Shlomi所说,这是一个长期运行的bug。根据Noam Ben Ari关于clj jira的建议,我编写了一个小型java类来封装客户端创建,从而解决了这个问题。然后我可以直接从我的clj代码中使用它

package pubsub_echo.pubsub;

import com.google.cloud.AuthCredentials;
import com.google.cloud.pubsub.PubSub;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;

public class GCloudPubSub {

    public PubSub getClient() throws FileNotFoundException, IOException {
        PubSubOptions.Builder optionsBuilder = PubSubOptions.builder();
        ClassLoader classLoader = getClass().getClassLoader();
        FileInputStream authStream = new FileInputStream(classLoader.getResource("SERVICE_ACCOUNT.json").getPath());
        AuthCredentials creds = AuthCredentials.createForJson(authStream);

        return optionsBuilder
            .authCredentials(creds)
            .projectId("PROJECT_ID")
            .build()
            .service();
    }

}
有关将Java编译添加到项目中的指导信息:

完全受此启发,我通过一个单独的示例来实现这一点。在中的
src/gcloud/gcloudatastore.java
中创建了以下文件


因此,我是一个完全的Clojure noob,在使用咖啡因缓存时遇到了类似的错误:“IllegalArgumentException无法调用非公共类的公共方法:public default void com.github.benmanes.caffee.Cache.LocalManualCache.put(java.lang.Object,java.lang.Object)Clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:88)”

我最初的函数签名是:

(defn get
  [cache key]
  (.getIfPresent cache key)
  )
我认为问题在于Clojure无法确定在何处应用Cache的.getIfPresent函数。将类型添加到它:

(defn get
  [^Cache cache key]
  (.getIfPresent cache key)
  )
即使这不是一个直接的答案,你的问题也超出了我的理解,我希望这能有所帮助

(defn get
  [cache key]
  (.getIfPresent cache key)
  )
(defn get
  [^Cache cache key]
  (.getIfPresent cache key)
  )