问题描述
我正在尝试使用库。
(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代码是从(点按一下,单击在其他地方运行)。
The above clojure code is translated from the following code snippet (ellided, click on "Run elsewhere").
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调用此代码时,出现以下错误。
When I call this code from the Clojure REPL, I get the following error.
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
代码。
2016年6月29日更新:
根据的以下建议,我认为也许我AOT可以在<$周围编译自己的包装器c $ c> DatastoreOptions 。
Updated June 29, 2016:Pursuant to Schlomi's advice below, I thought that maybe if I AOT compiled my own wrapper around DatastoreOptions
that it would work.
(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}]))
我修改了引导开发
任务,使其包括以下内容:
I modified my boot development
task to include the following:
(deftask development
"Launch Immediate Feedback Development Environment"
[]
(comp
(aot :namespace '#{firengine.datastore})
(repl :port 6800)
(reload)
(watch)
(cljs)
(target :dir #{"target"})))
我试图像这样构造对象:
And I attempted to construct the object like so:
(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))
不幸的是,我仍然遇到相同的错误吗?
Unfortunately, I still get the same error?
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!
Yeah.... that problem. You wouldnt believe it, but its actually an open bug in the jdk from ... wait for it ... 1999!
您可以在和 。
您可能必须制作自己的Java包装程序以避免这种情况,或者考虑这个已知的Java错误。
You might have to make your own java wrapper to avoid this, or ask the library author to take this old known java bug into consideration.
如果您不想编写自己的Java包装程序,而作者坚持认为这是有史以来最好的设计!,那么您可以随时强制使用它通过使用(。setAccessible method true)
和更多自定义反射代码设置方法的可访问性。
If you dont want to write your own java wrapper, and the author insists that "this is the best design, like, ever!", then you could always force it by setting the method accessibility with (.setAccessible method true)
and some more custom reflection code..
祝您好运!
这篇关于无法调用非公共类的公共方法:公共(Google gcloud库)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!