I’m trying to upgrade from pedestal 0.5.3 to 0.5.5, but it breaks some of our url-for
calls, raising this:
[{:type java.lang.IllegalArgumentException
:message "Don't know how to create ISeq from: clojure.lang.Keyword"
:at [clojure.lang.RT seqFrom "RT.java" 553]}]
:trace
[[clojure.lang.RT seqFrom "RT.java" 553]
[clojure.lang.RT seq "RT.java" 533]
[clojure.core$seq__5387 invokeStatic "core.clj" 137]
[clojure.core$empty_QMARK_ invokeStatic "core.clj" 6206]
[clojure.core$empty_QMARK_ invoke "core.clj" 6206]
[io.pedestal.http.route$link_str invokeStatic "route.clj" 252]
[io.pedestal.http.route$link_str invoke "route.clj" 230]
[io.pedestal.http.route$url_for_routes$fn__23926 doInvoke "route.clj" 369]
debug logging shows this:
2019-02-19 15:01:27.001 DEBUG io.pedestal.http.route - {:in :link-str, :path-parts [:profile-handle], :context-path-parts [""], :line 247}
https://github.com/pedestal/pedestal/blob/0.5.5/route/src/io/pedestal/http/route.clj#L252
@kommen, sorry to hear about the issues you are having. Can you share an example url-for
call that is failing?
(url-for :show-named-profile :params {:profile-handle "foo"})
with this route: ["/:profile-handle" :get [profile/fetch profile/show] :route-name :show-named-profile]
ok thanks
I guess the problem is that we don’t have a string before the first url param?
hrm not sure. I drop that route and url-for
invocation into a new pedestal app using version 5.3 and I don’t see an issue.
Can you try this
(def my-url-for (route/url-for-routes (route/expand-routes routes)))
(my-url-for :show-named-profile :params {:profile-handle "foo"})
I’m assuming that your routes are bound to a var named routes
replace with the correct value
ok, thanks. we use table routes, so I did this:
(def my-url-for (route/url-for-routes (table/table-routes routes)))
(my-url-for :show-named-profile :params {:profile-handle "foo"})
which works
ok so it fails in context of a request, right?
right
Ok, so I don’t see that behavior in the quick sample I generated but I generated it using the pedestal-service
template 0.5.5
and just updated the pedestal deps to 0.5.3
ok, thank you. I guess I hoped it was some thing obvious, will investigate further
It’s definitely due to :context ""
(def my-url-for (route/url-for-routes (route/expand-routes routes) :context ""))
(my-url-for :show-named-profile :params {:profile-handle "foo"})
IllegalArgumentException Don't know how to create ISeq from: clojure.lang.Keyword clojure.lang.RT.seqFrom (RT.java:550)
I’m not sure why :context
is set to an empty string. I don’t see that in my sample
I’ll look into that further when I have a chance. I’m curious. Tracking down where :context ""
is being set is where I’d start looking
@ddeaguiar It looks like in pedestal 0.5.5 there is always a :context-path
on the request in https://github.com/pedestal/pedestal/blob/0.5.5/route/src/io/pedestal/http/route.clj#L209
which causes context-path-parts
to be [""]
instead of nil
so I guess this change here: https://github.com/pedestal/pedestal/commit/1d9083421cb8fa407d2093212e048e8420009c29#diff-9be1af57b1dfcec8ea9df18ac98e6777R152
Ok, thanks for digging through that. I’ll take a closer look. I’ll likely update the release notes with breaking change info and possibly open an issue around it.
I’ll file an issue with the info I found
:thumbsup:
it also reproduces with the stock lein example in the context of a request
thanks again 🙂
Does anyone here have any basic examples of a pedestal CRUD project with mount/component and a database?
@decim creating such an example has been on my todo list for a while. If you have specific questions perhaps I can provide some guidance
@ddeaguiar i’m very much at the beginning of it. I’ve gone through the provided tutorials and I’m really just trying to figure out where to go, what all is necessary. Even something as simple as making a post. For starters i’d like to know how to just serve a basic index.html page from my resources folder. As I get a hold on things I’ll start to make blog posts for people in the future interested.
To serve files, add the :io.pedestal.http/resource-path
key to your system map. This will serve any files which match url from that dir
@ddeaguiar ok, nice. I really have to start looking through the source as well today. I’m coming from frameworks like ruby on rails so these libraries are very bare bones which isn’t a bad thing, it’s good to know exactly what’s taking place
I’ve experimented with component and pedestal quite a bit on various projects and I’m now more discerning about bringing the two together.
Pedestal provides a configuration map which you can append anything to at runtime, during system startup
They key concept is to create interceptors which provide access to those things you need (i.e., db connection, etc…)
If you need to start things, you already have the facilities to do it and append the started thing to the service map
same with stopping
but
If you really want to use component or mount or whatever, you can
My current line of thinking here is: - Define routes in one place - Limit components to external dependency needs (db, queueing system, etc…) - Use interceptors as glue to make those dependencies available on the context map and/or request - Do more processing in interceptors and limit handlers to formatting responses - With Component, have the Pedestal component depend on all other components and be responsible for putting their interceptor glue on the interceptor chain
Here are some examples of component+pedestal that I’ve tinkered with: https://github.com/pointslope/elements/blob/master/src/pointslope/elements/pedestal.clj#L1, https://github.com/ddeaguiar/component-pedestal
TBH, I’m not happy with either of them but you can use that for inspiration
Hmm ok, I see. Looking at ‘elements’ now. It almost seems as if it’s better to start from scratch opposed to lein new pedestal service app-name
yeah it’s a different way of building a service
Again, take it with a grain of salt. Those projects are old and I’ve not had the need leverage component + pedestal lately
But if you are just learning pedestal, then stick with the service template
It’s perfectly acceptable to provision dependencies on system startup via -main
or run-dev
and add the interceptors which provide access to those started resources at that point.
@ddeaguiar yeah i’m wondering if using component or mount is overkill as well. I may be experimenting with too many things at once. long term for this toy project i’d like to use it but I suppose I shouldn’t fear a complete rewrite after I know what’s taking place. So you do prefer component over mount? I’ve seen a bit of discussion about that.
@decim I prefer integrant
@decim check out https://lambdaisland.com/episodes/integrant