Fork me on GitHub
#beginners
<
2018-12-11
>
macrobartfast00:12:33

when running an uberjar web server locally via java -jar app.jar'' all is well... when running it the same way on ec2 it returns a resource not found error as it can't find resources in resources/public inside the jar; if I create a resources/public/<resources> on the server outside the jar, it works... why the difference, and how do I get the uberjar on the server to get the resources internally?

macrobartfast00:12:58

the resource is returned by a GET route in app-routes which in turn calls (defn get-page [] (slurp "resources/public/index.html")), if that's useful.

noisesmith17:12:35

use io/resource, by default slurp will treat that as a filesystem path, io/resource treats it as a classpath relative path, which will work

TK00:12:22

-- How do you add a conditional inside a threading macro?

(-> {:env (:env options :dev)
     ::http/routes (route/expand-routes (graphql-routes compiled-schema options))
     ::http/port (:port options 8888)
     ::http/type :jetty
     ::http/join? false}
    http/create-server)
I saw that we could use cond->
(cond->
 {:env (:env options :dev)
  ::http/routes (route/expand-routes (graphql-routes compiled-schema options))
  ::http/port (:port options 8888)
  ::http/type :jetty
  ::http/join? false}
  (:graphiql options) (assoc ::http/resource-path "graphiql")
  true http/create-server)
Or add a cond-> inside the threading macro
(-> {:env (:env options :dev)
     ::http/routes (route/expand-routes (graphql-routes compiled-schema options))
     ::http/port (:port options 8888)
     ::http/type :jetty
     ::http/join? false}
    (cond->
     (:graphiql options) (assoc ::http/resource-path "graphiql"))
    http/create-server)
How would handle conditional inside a threading macro?

hiredman00:12:56

I suspect you just need to be set straight on resources

hiredman00:12:28

resources are things you load via io/resource

hiredman00:12:41

slurp doesn't load resources

hiredman00:12:44

slurp loads files

hiredman00:12:57

resources are loaded from the classpath

hiredman00:12:26

in this case the resource folder is bundled in the jar with your code and available on the classpath

hiredman00:12:42

lein gives you a separate resources/ folder to put resources in, but technically anything available through a classloader is a resource (this includes anything in your jar, include clojure source files and or classfiles)

hiredman00:12:27

a common mistake is to load stuff out of resources/ as files only to have it break when you actually deploy stuff as a jar

hiredman00:12:30

if you ran your local jar not from inside your source checkout, you would have the same problem

hiredman00:12:20

when you run locally the reason it is working is you happen to be running in a directory with resources/ in it, you aren't correctly loading the resources from the out of the jar

macrobartfast00:12:20

thank you for helping... that sounds like the problem!

macrobartfast00:12:19

incidentally, I fortunately just looked at https://clojuredocs.org/clojure.java.io/resource which points out you have to 'slurp directly on the result of io/resource' which I'll try now.

macrobartfast01:12:28

great! it all works now... thanks again!

noisesmith17:12:37

also, watch out for io/resource returning nil when there's no resource found, you probably want to stop there instead of getting an NPE from slurp

mfikes01:12:26

Yeah, slurp can work on things that can be passed to io/reader, one of which is a URL, which io/resource returns.

Saikyun08:12:00

I'm using clojure.java.jdbc to talk to a sqlite database. at one point I want to use str on a result of a (query ["select * from ..."]), but all I get is clojure.lang.LazySeq@323004b1. I've tried to wrap the query with doall, but it doesn't seem to matter. please send help

noisesmith17:12:19

the toString of lazy-seq is pretty much useless, try "pr-str" instead of "str"

orestis09:12:35

How about mapping str over that result?

Saikyun09:12:08

@orestis I still get the lazyseq šŸ˜•

orestis09:12:12

Sorry, try (mapv str (query ...))

orestis09:12:21

You should at least get a vector back then.

Saikyun09:12:15

eyy, what do you know, it works! thanks šŸ™‚ a vector is fine, it's generally only 1 element so

Saikyun09:12:49

didn't know about mapv either, so thanks for that as well! I'm guessing I can replace all (into [] (map with (mapv?

orestis09:12:45

AFAIK, yes. But just FYI, if you have are expecting just a single element, then you should be able to do (first (query ...)). Iā€™ve no idea about java.jdbc and how itā€™s supposed to work. It makes sense to return a lazy seq because usually SQL results map to some cursor in the DB, and you might want to consume that at your leisure. So be careful when eagerly consuming a Lazy Seq as it might give you more data than you expected šŸ™‚

Saikyun09:12:19

yeah, it should be a single element, but I don't want to make any assumptions, and in this particular case I'm throwing an error, so I felt I might as well include as much information as possible. šŸ™‚

Saikyun09:12:36

thanks anyway ^^

Ali Ebadian16:12:59

Hey all, I have a bit of a stupid question. What the point of the namespaces?

manutter5116:12:33

It just helps organize your functions and such so you can keep track of them.

manutter5116:12:36

It also makes it possible to re-use names, so you can have a foo/update function that does something different from a bar/update function (and the namespaces usually give some hint as to what that difference might be).

Ali Ebadian16:12:36

Not sure what is meant by organizing functions. What would disorganized functions look like?

dpsutton16:12:16

have you worked on a project before?

dpsutton16:12:31

take all of the files, cat them together, and then scramble theorder of the functions

manutter5116:12:03

ā€œOrganizing functionsā€ as opposed to not having namespaces and having to write all your functions in one big file, each with a unique name, etc.

šŸ‘ 4
Ali Ebadian16:12:45

@dpsutton No, just learning Clojure from ground up, hopefully then I find a job that uses it

dpsutton16:12:03

i mean any programming project

dpsutton16:12:47

any language. files, modules, directories. they all exist for our benefit, the code reader.

manutter5116:12:02

So in other words you can have a db namespace with a function called read that reads values from the database, and you can have a file namespace with a function called read that reads from files. Thereā€™s different code required for reading from files versus reading from databases, but itā€™s kinda doing the same sort of thing.

Alex Miller (Clojure team)16:12:06

there are a finite number of good names. namespaces let us use them in different contexts

šŸ‘ 8
manutter5116:12:31

Iā€™m using an example thatā€™s kind of contrived, but you get the idea.

Akash18:12:04

Hi, I have a requirement wherein I wanna read the inputstream twice. i.e., the body in my response. Apparently, if I use slurp then the stream will consumed. Currently, I am copying it to a new stream. Is there a better way of doing it ?

noisesmith18:12:08

You can copy the stream to two destinations, but anything which consumes it will alter its state. Sometimes the reset method on streams works, but this isn't guaranteed for all stream implementations.

noisesmith18:12:07

@akashhc depending on what you are doing with the stream, it's a lot easier to just use the ingested stream data again (eg. make a string first, then parse the string into data with json from the string)

Akash01:12:54

@U051SS2EU Here is my scenario : I have my routes where in its consuming the stream and converting into a clojure map ( slurp and json decode basically). However, Now, I need to add a middleware during my sever start, where I need to check for some data in body and make decisions. I want to do this without changing my routes logic. So I need to read the stream twice.

noisesmith01:12:20

You can attach the decoded data to the request object, there's standard middleware that does this for you

dfcarpenter21:12:31

Where can I find a list of all of the types I can use with spec like string, int, etc. Also, should I be trying to model datetime in a spec or am I misusing spec here?

hiredman21:12:01

you can't use types in spec

hiredman21:12:13

spec operates on predicates

hiredman21:12:32

so not a "string" type, but the clojure.core/string? predicate

hiredman21:12:51

and you can use any arbitrary predicate in spec

hiredman21:12:37

most predicates in clojure.core have a defined mapping to some generator which is useful, if you use some other arbitrary predicate, if you want a generator you will have to provide one

dfcarpenter21:12:02

Okay. I found in the clj-time repo that they have defined some predicates for date-time. Helpful

seancorfield22:12:30

Bear in mind that clj-time is no longer recommended (I'm one of the maintainers). If you're on Java 8+, use the built in Java Time or a wrapper like clojure.java-time...

seancorfield22:12:38

...depending on what you're trying to spec, Clojure has inst? built-in (with generators) and clojure.spec.alpha has inst-in and inst-in-range? that might be useful.

RodgerDodger21:12:20

@kirankuppa I am not able to pull it up either. Hopefully it will be back up soon.

dfcarpenter21:12:24

Can anyone direct me to more open source apps like https://github.com/braidchat/braid/?

dfcarpenter21:12:34

Looking to learn from more examples