appengine-magic
A library designed to make it easy to use Google App Engine from Clojure
I'm trying to work out how to get sessions and flash working in Google App Engine. Could someone provide a clear example using either Ring or Sandbar? I think I have sandbar working, specifically it doesn't tell me that Var sandbar.stateful-session/sandbar-flash is unbound
and when I dump the handler I get :flash
and :session
though I'm not certain if that is a sandbar session or a ring one. For completeness I will mention that I am using the latest versions of appengine-magic, ring, hiccup and sandbar. There do not appear to be any incompatibilities or issues.
So a clear example preferably with use of flash-put!, flash-get, session-put! and session-get
.
Source: (StackOverflow)
I'm specifically trying to generate the boilerplate for crud functions to work with the Google App Engine datastore using appengine-magic in Clojure. I'm having difficulty working out how to generate values from a model that I've reproduced below.
(def *model* {:users [{:name "Adam"
:email "adam@gmail.com"
:registered-on "07-05-2011"}
{:name "Greg"
:email "gregory@gmail.com"
:registered-on "11-05-2011"}]
:post [{:title "A"
:authour "Adam"}
{:title "B"
:author "Greg"}]})
I'm fairly new to appengine-magic, but it provides a defentity which allows you to define entities that you can put into the datastore and save! which allows you to save predefined entities into the datastore.
These take the form of:
(ds/defentity Post [title author])
(ds/save! (Post. title author))
Now just to start with I've defined:
(defn list-entities [model]
"Takes a representation of the model and lists the entities in preparation for generating defentities"
(interleave (vec (map first (partition 1 (map (comp symbol capitalize #(str % ".") name) (keys model)))))
(map vec (map keys (map first (vals model))))))
Calling it with:
(list-entities *model*)
Outputs:
(Users. [:name :email :registered-on] Post. [:title :author])
Now I am having difficulty defining gen-entities which will take the output above and repeatedly call ds/defentities defining as many entities as my model requires.
(defmacro gen-entities [entity fields]
`(ds/defentity 'entity 'fields))
Additionally I am in no way certain that this is a reasonable way to go about solving this problem. I'm still very new to macros and probably making several mistakes. Any help/clarity would be appreciated.
NOTE:
That model I've realised is badly designed, the one below is a lot better:
(def *model* {:users [:name :email :registered-on]
:post [:title :author]})
However it is more complex in terms of writing a macro so I will leave it as is.
Source: (StackOverflow)
somewhere in here I'm using java.rmi.server.UID
which is upsetting GAE.
After :only'ing my dependencies to the bone I'm at an impasse.
(ns helloworld.core
(:use ;[hiccup.core]
[hiccup.page-helpers :only (html5 include-css)]
[clojure.contrib.string :only (split)]
[compojure.core :only (defroutes GET)]
[hiccup.middleware :only (wrap-base-url)])
(:require [appengine-magic.core :as ae]
[compojure.route :as route
:only (resources not-found) ]
[compojure.handler :as handler :only (site)])
(:gen-class :extends javax.servlet.http.HttpServlet))
(defn index-page
([name]
(html5
[:head
[:title (str "Hello " name)]
(include-css "/css/style.css")]
[:body
[:h1 (str "Hello " name)]]))
([] (index-page "World")))
(def match-opperator
{ "add" +
"subtract" -
"multiply" *
"divide" /})
(defroutes hello-routes
(GET "/:f/*" [f & x]
(index-page (apply (match-opperator f)
(map #(Integer/parseInt %)
(split #" " (:* x))))))
(GET "/" [] (index-page))
(route/resources "/")
(route/not-found "Page not found"))
(def app
(-> (handler/site hello-routes)
(wrap-base-url)))
(ae/def-appengine-app helloworld-app #'app)
I can load it up in jetty and it works fine,
after loading it into the dev-appserver i get this:
HTTP ERROR 500
Problem accessing /multiply/1%202%204%208. Reason:
java.rmi.server.UID is a restricted class. Please see the Google App Engine developer's guide for more details.
Caused by:
java.lang.NoClassDefFoundError: java.rmi.server.UID is a restricted class. Please see the Google App Engine developer's guide for more details.
at com.google.appengine.tools.development.agent.runtime.Runtime.reject(Runtime.java:51)
at org.apache.commons.fileupload.disk.DiskFileItem.(DiskFileItem.java:103)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:186)
at ring.middleware.multipart_params$loading__4414__auto__.invoke(multipart_params.clj:1)
at ring.middleware.multipart_params__init.load(Unknown Source)
at ring.middleware.multipart_params__init.(Unknown Source)
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Class.java:264)
at clojure.lang.RT.loadClassForName(RT.java:1578)
at clojure.lang.RT.load(RT.java:399)
at clojure.lang.RT.load(RT.java:381)
at clojure.core$load$fn__4519.invoke(core.clj:4915)
ps: here is my project.clj incase this helps:
(defproject helloworld "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"]
[org.clojure/clojure-contrib "1.2.0"]
[compojure "0.6.2"]
[hiccup "0.3.4"]]
:dev-dependencies [[appengine-magic "0.4.1"]
[swank-clojure "1.2.1"]])
Source: (StackOverflow)
I'm trying get Clojure/Compojure/appengine-magic to work by following the example at https://github.com/gcv/appengine-magic
But when I run lein appengine-prepare
I get:
Exception in thread "main" C:\Users\henrik\IdeaProjects\simple-example\lib\dev not found. (NO_SOURCE_FILE:0)
at clojure.lang.Compiler.eval(Compiler.java:5440)
at clojure.lang.Compiler.eval(Compiler.java:5391)
at clojure.core$eval.invoke(core.clj:2382)
at clojure.main$eval_opt.invoke(main.clj:235)
at clojure.main$initialize.invoke(main.clj:254)
at clojure.main$script_opt.invoke(main.clj:270)
at clojure.main$main.doInvoke(main.clj:354)
at clojure.lang.RestFn.invoke(RestFn.java:457)
at clojure.lang.Var.invoke(Var.java:377)
at clojure.lang.AFn.applyToHelper(AFn.java:172)
at clojure.lang.Var.applyTo(Var.java:482)
at clojure.main.main(main.java:37)
Caused by: C:\Users\henrik\IdeaProjects\simple-example\lib\dev not found.
Have I missed something?
lein new simple-example
edit project.clj:
(defproject simple-example "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.1"] [appengine-magic "0.4.1"]])
lein deps
lein appengine-new
edit core.clj:
(ns simple-example.core
(:use compojure.core)
(:require [appengine-magic.core :as ae]))
(defroutes simple-example-app-handler
(GET "/" req
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello, world!"})
(GET "/hello/:name" [name]
{:status 200
:headers {"Content-Type" "text/plain"}
:body (format "Hello, %s!" name)})
(ANY "*" _
{:status 200
:headers {"Content-Type" "text/plain"}
:body "not found"}))
(ae/def-appengine-app simple-example-app #'simple-example-app-handler)
lein appengine-prepare
Source: (StackOverflow)
The body
field of a form may contain long text, so the default String property won't do.
Looking for how to make the datastore use Text (this is not part of the entity definition like I recall from the Python version), I found this in the source of the ackbar blog:
(ns <snip>
(:import (com.google.appengine.api.datastore
EntityNotFoundException Text)))
<snip>
(ds/save! (Post. url title (Text. body) ts in-feed? category))
But if I do the same, I get: "java.lang.RuntimeException: java.lang.IllegalArgumentException: Don't know how to create ISeq from: com.google.appengine.api.datastore.Text"
(One notable difference is that the ackbar I'm looking at uses appengine-magic 0.3.2.)
I also tried as-text
as briefly mentioned on https://github.com/gcv/appengine-magic#readme, but (as-text body)
in there leads to the same error message as above.
EDIT: Turned out the problem wasn't actually to get a Text property into the store, but to make sense of it when retrieving it. My Submit handler triggers saving and than a reload of the form page, and I failed to think of that. Sorry for the noise.
The way to get the value out without hiccup is (.getValue body)
.
Source: (StackOverflow)
I'm using appengine-magic to set up a web application, more or less as described at http://www.digitalbricklayers.com/2012/03/geotasklist-in-jquery-mobile-and.html. The example works on my local machine, locations and tasks are added to a local datastore etc.
My question is if it is possible to interact with the datastore from within a REPL, e.g. call (ds/save! ...) etc. during interactive development? I ask because when I try I get:
NullPointerException No API environment is registered for this thread.
com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId
(DatastoreApiHelper.java:108)
I'm getting this error no matter if I use an eclipse+counterclockwise based setup or an emacs+slime based setup.
Thanks,
Joachim
Source: (StackOverflow)
I got webapp (made with appengine-magic and lein) working on dev_appserver.sh but because I need more interactivity and less restarting the server I prefer to use repl. Now problem is, that after I do (require '[appengine-magic.core :as ae])
, (use 'myapp.core)
and try to serve application (ae/serve myapp)
I get this exception:
[Thrown class java.lang.NullPointerException]
Backtrace:
0: java.io.File.<init>(File.java:360)
1: sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
2: sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
3: sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
4: java.lang.reflect.Constructor.newInstance(Constructor.java:513)
5: clojure.lang.Reflector.invokeConstructor(Reflector.java:160)
6: appengine_magic.core$start.doInvoke(core_local.clj:85)
7: clojure.lang.RestFn.invoke(RestFn.java:439)
8: appengine_magic.core$serve.doInvoke(core_local.clj:139)
9: clojure.lang.RestFn.invoke(RestFn.java:410)
10: user$eval2264.invoke(NO_SOURCE_FILE:1)
11: clojure.lang.Compiler.eval(Compiler.java:5424)
12: clojure.lang.Compiler.eval(Compiler.java:5391)
13: clojure.core$eval.invoke(core.clj:2382)
14: swank.commands.basic$eval_region.invoke(basic.clj:47)
15: swank.commands.basic$eval_region.invoke(basic.clj:37)
16: swank.commands.basic$eval807$listener_eval__808.invoke(basic.clj:71)
17: clojure.lang.Var.invoke(Var.java:365)
18: user$eval2262.invoke(NO_SOURCE_FILE)
19: clojure.lang.Compiler.eval(Compiler.java:5424)
20: clojure.lang.Compiler.eval(Compiler.java:5391)
21: clojure.core$eval.invoke(core.clj:2382)
22: swank.core$eval_in_emacs_package.invoke(core.clj:92)
23: swank.core$eval_for_emacs.invoke(core.clj:239)
24: clojure.lang.Var.invoke(Var.java:373)
25: clojure.lang.AFn.applyToHelper(AFn.java:167)
26: clojure.lang.Var.applyTo(Var.java:482)
27: clojure.core$apply.invoke(core.clj:540)
28: swank.core$eval_from_control.invoke(core.clj:99)
29: swank.core$eval_loop.invoke(core.clj:104)
30: swank.core$spawn_repl_thread$fn__493$fn__494.invoke(core.clj:309)
31: clojure.lang.AFn.applyToHelper(AFn.java:159)
32: clojure.lang.AFn.applyTo(AFn.java:151)
33: clojure.core$apply.invoke(core.clj:540)
34: swank.core$spawn_repl_thread$fn__493.doInvoke(core.clj:306)
35: clojure.lang.RestFn.invoke(RestFn.java:397)
36: clojure.lang.AFn.run(AFn.java:24)
37: java.lang.Thread.run(Thread.java:680)
I have also tried (in-ns 'myapp.core) but same effect. When I paste web app handler straight on repl and serve then it works, but not from my file.
calling myapp or myapp-handler clearly gives the "object" so I should really be on right namespace...
project.clj
(defproject myapp "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [
[org.clojure/clojure "1.2.1"]
[compojure "0.6.2"]
]
:dev-dependencies [
[appengine-magic "0.4.1"]
[ring/ring-devel "0.3.7"]
])
core.clj is as just simple:
(ns myapp.core
(:use compojure.core)
(:require [appengine-magic.core :as ae]))
(defroutes myapp-handler
(GET "/" req
{:status 200
:headers {"Content-Type" "text/plain"}
:body "Hello, world!!!"}))
(ae/def-appengine-app myapp #'myapp-handler)
Source: (StackOverflow)
I tried to make example to use google appengine with appengine-magic.
I think I did as the usage
but I got the following problem.
Problem accessing /parents. Reason:
clojure/lang/IFn
Caused by:
java.lang.NoClassDefFoundError: clojure/lang/IFn
at java.lang.Class.getDeclaredConstructors0(Native Method)
at java.lang.Class.privateGetDeclaredConstructors(Class.java:2493)
at java.lang.Class.getConstructor0(Class.java:2803)
at java.lang.Class.newInstance(Class.java:345)
this is my source project
Source: (StackOverflow)
I'm having some serious issues with capturing POST and GET parameters with the latest appengine-magic/compojure versions. The parameters always come up as blank, even though the request object clearly has the right stuff in it.
I've seen some stuff around the interwebs about a change in the Compojure protocol where you have to manually put in the wrappers. I've tried this (using the handler/api wrapper to avoid the stuff in handler/site wrapper that breaks GAE) but it still doesn't work.
What am I doing wrong here?
My project.clj file:
(defproject pitch-filter "1.0.0-SNAPSHOT"
:description "FIXME: write description"
:dependencies [[org.clojure/clojure "1.2.0"]
[org.clojure/clojure-contrib "1.2.0"]
[compojure "0.6.4"]
[hiccup "0.3.6"]
[jtidy "4aug2000r7-dev"]
[commons-lang "2.5"]]
:dev-dependencies [[appengine-magic "0.4.2"]
[clj-http "0.1.1"]])
My core.clj file:
(ns pitch-filter.core
(:use compojure.core
[appengine-magic.multipart-params :only [wrap-multipart-params]]
[hiccup.middleware :only (wrap-base-url)])
(:require [pitch-filter.fetch :as fetch]
[compojure.route :as route]
[compojure.handler :as handler]
[appengine-magic.core :as ae]
[appengine-magic.services.url-fetch :as url]
(defroutes pitch-filter-app-routes
(GET "/" [] "Main Page")
(GET "/form" []
(str "<form method='post' action='/post'>"
"<input type='text' name='test'>"
"<input type='submit'>"
"</form>"))
(POST "/post" {params :params}
(pr-str params))
(route/not-found "Page not found"))
(def pitch-filter-app-handler
(-> pitch-filter-app-routes
(handler/api)
(wrap-base-url)
))
(ae/def-appengine-app pitch-filter-app #'pitch-filter-app-handler)
Source: (StackOverflow)