我正在尝试使用gcloud库。
(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代码是从following code snippet翻译过来的(已省略,点击“Run others”)。
import com.google.cloud.AuthCredentials;
import com.google.cloud.datastore.DatastoreOptions;
DatastoreOptions options = DatastoreOptions.builder()
.projectId(PROJECT_ID)
.authCredentials(AuthCredentials.createForJson(
new FileInputStream(PATH_TO_JSON_KEY))).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
代码can be found here。
2016年6月29日更新:
根据{{3}}下面的建议,我想如果我AOT编译我自己的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}]))
我修改了boot development
任务以包含以下内容:
(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
?
答案 0 :(得分:4)
您可以在clojure jira和google groups上阅读更多内容。
您可能必须创建自己的java包装器以避免这种情况,或者ask the library author将这个旧的已知java错误考虑在内。
如果您不想编写自己的java包装器,并且作者坚持认为&#34;这是最好的设计,比如,永远!&#34;,那么您可以通过设置方法辅助功能来强制它(.setAccessible method true)
以及更多自定义反射代码..
答案 1 :(得分:1)
正如Shlomi所说,这是一个长期存在的错误。按照Noam Ben Ari关于clj-jira的建议,我通过编写一个包装客户端创建的小型java来管理问题。然后我可以直接从我的clj代码中使用它。
SELECT clientId
FROM tblClientinformation
WHERE taskID=21
AND FromDate <='7/29/2016'
AND ToDate >= '7/29/2016';
有关向项目添加Java编译的指导:
https://github.com/technomancy/leiningen/blob/master/doc/MIXED_PROJECTS.md
答案 2 :(得分:1)
所以,我是一个完整的Clojure noob并使用Caffeine Cache遇到了类似的错误:“IllegalArgumentException无法调用非公共类的公共方法:public default void com.github.benmanes.caffeine.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)
)
尽管这不是一个直接的答案而你的问题已经过去了,但我希望这会有所帮助。
答案 3 :(得分:0)
完全受到hironroy's answer的启发,我通过一个孤立的例子来解决这个问题。在the following github project中的src/gcloud/GcloduDatastore.java
中创建了以下文件。
package gcloud;
import com.google.cloud.AuthCredentials;
import com.google.cloud.datastore.Datastore;
import com.google.cloud.datastore.DatastoreOptions;
import com.google.cloud.datastore.DatastoreOptions.Builder;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
public class GCloudDatastore {
public static Datastore getDatastore() throws FileNotFoundException, IOException {
DatastoreOptions.Builder optionsBuilder = DatastoreOptions.builder();
FileInputStream authStream = new FileInputStream(System.getenv("SERVICE_ACCOUNT_DOT_JSON_PATH"));
AuthCredentials creds = AuthCredentials.createForJson(authStream);
return optionsBuilder
.authCredentials(creds)
.projectId(System.getenv("PROJECT_ID"))
.build()
.service();
}
}