Is this bug in Google AppEngine, appengine-clj or Clojure itself?

24 views
Skip to first unread message

Darren Clarke

unread,
Oct 15, 2010, 2:49:36 PM10/15/10
to Clojure
I've been using Clojure 1.2 and appengine-clj for a project on
AppEngine and two days ago it stopped working after the Google team
released some newly refactored code to production. Short discussion of
this problem on the AppEngine-Java discussion group is here:

http://code.google.com/appengine/forum/java-forum.html?place=topic%2Fgoogle-appengine-java%2FSzrdYDTwkYk%2Fdiscussion

I'm trying to figure out what I can patch (either in appengine-clj or
Clojure) to get up and running again. In short, it looks like Google
moved a method into an abstract superclass and now Clojure throws this
error whenever I try to access a datastore transaction:

java.lang.IllegalArgumentException: Can't call public method of non-
public class: public com.google.appengine.api.datastore.Transaction
com.google.appengine.api.datastore.BaseDatastoreService.getCurrentTransaction(com.google.appengine.api.datastore.Transaction)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:85)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)

Questions:

1. Is there any sort of type hinting or other trick I could add to
appengine-clj to avoid this problem?

2. Is this related to these two bugs in Assembla?:

http://www.assembla.com/spaces/clojure/tickets/259-clojure-lang-reflector-invokematchingmethod-is-not-complete-(rejects-pontentially-valid-method-in---

http://www.assembla.com/spaces/clojure/tickets/126-abstract-superclass-with-non-public-accessibility
(AppEngine runs on Java 6, BTW)



Full stacktrace:

java.lang.IllegalArgumentException: Can't call public method of non-
public class: public com.google.appengine.api.datastore.Transaction
com.google.appengine.api.datastore.BaseDatastoreService.getCurrentTransaction(com.google.appengine.api.datastore.Transaction)
at clojure.lang.Reflector.invokeMatchingMethod(Reflector.java:85)
at clojure.lang.Reflector.invokeInstanceMethod(Reflector.java:28)
at appengine.datastore.service$current_transaction.invoke(service.clj:
72)
at appengine.datastore.service$put_entity.invoke(service.clj:131)
at appengine.datastore.service$fn__176.invoke(service.clj:149)
at appengine.datastore.service$fn__136$G__116__141.invoke(service.clj:
10)
at com.redaranj.ledes.service.servlet
$fn__1902$fn__1903.invoke(servlet.clj:17)
at compojure.core$routes$fn__1706$fn__1707.invoke(core.clj:72)
at clojure.core$some.invokeStatic(core.clj:2297)
at compojure.core$routes$fn__1706.invoke(core.clj:71)
at ring.middleware.params$wrap_params$fn__1468.invoke(params.clj:77)
at ring.middleware.cookies$wrap_cookies$fn__1559.invoke(cookies.clj:
123)
at ring.util.servlet$make_service_method$fn__1881.invoke(servlet.clj:
117)
at com.redaranj.ledes.service.servlet$_service.invoke(servlet.clj:19)
at com.redaranj.ledes.service.servlet.service(Unknown Source)
at org.mortbay.jetty.servlet.ServletHolder.handle(ServletHolder.java:
511)
at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1166)
at
com.google.apphosting.utils.servlet.ParseBlobUploadFilter.doFilter(ParseBlobUploadFilter.java:
97)
at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1157)
at
com.google.apphosting.runtime.jetty.SaveSessionFilter.doFilter(SaveSessionFilter.java:
35)
at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1157)
at
com.google.apphosting.utils.servlet.TransactionCleanupFilter.doFilter(TransactionCleanupFilter.java:
43)
at org.mortbay.jetty.servlet.ServletHandler
$CachedChain.doFilter(ServletHandler.java:1157)
at
org.mortbay.jetty.servlet.ServletHandler.handle(ServletHandler.java:
388)
at
org.mortbay.jetty.security.SecurityHandler.handle(SecurityHandler.java:
216)
at
org.mortbay.jetty.servlet.SessionHandler.handle(SessionHandler.java:
182)
at
org.mortbay.jetty.handler.ContextHandler.handle(ContextHandler.java:
765)
at org.mortbay.jetty.webapp.WebAppContext.handle(WebAppContext.java:
418)
at
com.google.apphosting.runtime.jetty.AppVersionHandlerMap.handle(AppVersionHandlerMap.java:
238)
at
org.mortbay.jetty.handler.HandlerWrapper.handle(HandlerWrapper.java:
152)
at org.mortbay.jetty.Server.handle(Server.java:326)
at org.mortbay.jetty.HttpConnection.handleRequest(HttpConnection.java:
542)
at org.mortbay.jetty.HttpConnection
$RequestHandler.headerComplete(HttpConnection.java:923)
at
com.google.apphosting.runtime.jetty.RpcRequestParser.parseAvailable(RpcRequestParser.java:
76)
at org.mortbay.jetty.HttpConnection.handle(HttpConnection.java:404)
at
com.google.apphosting.runtime.jetty.JettyServletEngineAdapter.serviceRequest(JettyServletEngineAdapter.java:
135)
at
com.google.apphosting.runtime.JavaRuntime.handleRequest(JavaRuntime.java:
261)
at com.google.apphosting.base.RuntimePb$EvaluationRuntime
$6.handleBlockingRequest(RuntimePb.java:8483)
at com.google.apphosting.base.RuntimePb$EvaluationRuntime
$6.handleBlockingRequest(RuntimePb.java:8481)
at
com.google.net.rpc.impl.BlockingApplicationHandler.handleRequest(BlockingApplicationHandler.java:
24)
at com.google.net.rpc.impl.RpcUtil.runRpcInApplication(RpcUtil.java:
418)
at com.google.net.rpc.impl.Server$RpcTask.runInContext(Server.java:
572)
at com.google.tracing.TraceContext$TraceContextRunnable
$1.run(TraceContext.java:448)
at com.google.tracing.TraceContext.runInContext(TraceContext.java:
688)
at com.google.tracing.TraceContext
$AbstractTraceContextCallback.runInInheritedContextNoUnref(TraceContext.java:
326)
at com.google.tracing.TraceContext
$AbstractTraceContextCallback.runInInheritedContext(TraceContext.java:
318)
at com.google.tracing.TraceContext
$TraceContextRunnable.run(TraceContext.java:446)
at
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:
1110)
at java.util.concurrent.ThreadPoolExecutor
$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:636)

gaz jones

unread,
Oct 15, 2010, 4:52:28 PM10/15/10
to clo...@googlegroups.com
i had a similar problem recently. the only way i could find around it
was to create a class that extends the class with the problematic
method in question and create a new method that delegates to the
method you actually want to call. i would love to hear a better
solution...

> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en

Mike Hinchey

unread,
Oct 17, 2010, 3:18:58 AM10/17/10
to clo...@googlegroups.com
I think it is caused by those 2 clojure bugs (which seem to be the same thing).  You may be able to work around that problem by patching appengine-clj to hint the method call to be on the public interface: DatastoreService.

(defn current-transaction
  "Returns the current datastore transaction, or nil if not within a
transaction." [] (.getCurrentTransaction
^com.google.appengine.api.datastore.DatastoreService
(datastore) nil))

Darren Clarke

unread,
Oct 17, 2010, 3:41:56 PM10/17/10
to Clojure
Adding that type hint fixed the problem. Thanks.

Miki

unread,
Nov 3, 2010, 2:07:23 PM11/3/10
to Clojure
Does anybody know if this fix made it to the released jar?

Miki

unread,
Nov 4, 2010, 2:02:13 PM11/4/10
to Clojure
FYI: 0.4.1-SNAPSHOT has this fix
Reply all
Reply to author
Forward
0 new messages