Fork me on GitHub
#clojure
<
2022-09-21
>
Drew Verlee14:09:21

How do i translate this line of my stack trace?

foo_web.datomic$loading__6789__auto____4238.invoke(datomic.clj:1)
1. foo_web.datomic is a namespace 2. what does $ mean? 3. what does loading mean? it's not a function in the foo_web.datomic namespace. 4. it seems to fail invoking the first line of datomic.clj:1, i assume thats not foo_web.datomic but something from the actual datomic namespace right?

Drew Verlee14:09:39

This is the first line in the stack trace that mentions something from our app (as opposed to clojure core), so i assume i should be useful for figuring out the problem 🙂 .

Ed14:09:25

the foo_web.datomic is a class name with the $ meaning there's an inner class called loading__6789__auto____4238 which is probably an anon function because it's got an invoke method that's being called on the stack

Ed14:09:37

it's possible that this is an exception that's getting thrown during a require? so maybe it's a problem with one of the dependencies being incuded by foo-web.datomic?

p-himik15:09:44

That loading[...] comes probably from clojure.core/with-loading-context:

(defmacro with-loading-context [& body]
  `((fn loading# [] 
        (. clojure.lang.Var (pushThreadBindings {clojure.lang.Compiler/LOADER  
                                                 (.getClassLoader (.getClass ^Object loading#))}))
        (try
         ~@body
         (finally
          (. clojure.lang.Var (popThreadBindings)))))))

Drew Verlee15:09:38

Thanks for the information, that's useful to know. I see a more "on the nose error" further down that i can use. But it's helpful for me to build up an intuition on these things in general. E. G $ denotes an inner class.

Ben Sless15:09:35

Is there a convention for qualifying a package I want to include in my project in a way that would prevent name collisions?

R.A. Porter16:09:36

It's pretty rare in Clojure projects, but as it's a JVM language, you could use the Java package naming standard: https://docs.oracle.com/javase/tutorial/java/package/namingpkgs.html

R.A. Porter16:09:49

Sometimes you'll see a variation on the reverse-domain name where the common elements (`com`, org, etc.) are elided.

Ben Sless16:09:10

Clarifying, I mean an existing package, or part of it, I want to include in my project instead of as a dependency

seancorfield19:09:23

@UK0810AQ2 Perhaps https://github.com/benedekfazekas/mranderson might help? It's intended to let you inline-and-rename dependencies to avoid conflicts.

🎉 1
Ben Sless19:09:53

That's what I was looking for, wondering if there's something similar for a java dep

didibus00:09:21

I believe Maven supports something similar. I think it's called shading: https://maven.apache.org/plugins/maven-shade-plugin/

Nazral20:09:04

Hi all, is there by any chance an example on how to use ring+compojure with deps.edn instead of lein (which is the only way documented on the repo https://github.com/weavejester/compojure)

Nazral20:09:25

perfect thank you very much

Nazral20:09:14

Ok this is using very different things than I am used to (namely component)

seancorfield20:09:05

@UGH9KH1DF the usermanager repo is a good beginner example and shows quite a few things with deps.edn and build.clj / tools.build. Learning Component is useful, as are things like Selmer and next.jdbc etc. In general, where Leiningen has

:dependencies [[foo/bar "1.2.3"]
               [org.quux/wibble "4.56"]]
the equivalent in deps.edn is
:deps {foo/bar {:mvn/version "1.2.3"}
       org.quux/wibble {:mvn/version "4.56"}}
You'll find a lot of projects out there that only offer Leiningen style dependencies/versions but they'll all work with deps.edn too (except for stuff like plugins for Leiningen itself). If you are truly on a beginners journey, you'll find #beginners is more likely to give you longer, more helpful answers. There's an assumption here in #clojure that you have all the basics under your belt already.

1
Nazral23:09:54

@U04V70XH6 thanks for the in detail answer and my bad, my question was not clear, I am just trying to find the equivalent of the lein ring plugin without using lein, apart from that I am using deps.edn in pretty much all my projects 😅

Nazral23:09:20

and I am using next.jdbc in multiple projects already, and I don't think I have any use for Component at the moment

Nazral23:09:45

(my goal is to move existing repos away from lein to deps.edn)

seancorfield01:09:03

What things do you use lein ring for? I generally recommend folks just start a REPL and start their servers that way (say, from a comment form in your main ns -- https://github.com/seancorfield/usermanager-example/blob/develop/src/usermanager/main.clj#L218 )

Nazral10:09:05

lein ring with server-headless and to generate the uberjar, I'll look into it thanks, I remember doing something like that long time ago but I forgot how 😶

Steph Crown23:09:00

Hi guys, Is there a standard library for managing environmental variables in Clojure?

Max01:09:15

Mostly I’ve just seen people use System/getEnv

âž• 1
pavlosmelissinos05:09:11

I agree with Max. Why do you need a library for that?

vemv07:09:07

Java System properties are often a best bet (can be managed by http://t.de/leindeps/lein + can be modified at runtime)

kwladyka12:09:17

I strongly don’t recommend to use extra libs like https://github.com/weavejester/environ Why? Because it generate file with values during build, but in final environment you may want to have different values, than during build. Besides of that you have to remember to copy that file to final environment. Even if you use dockerfile it makes issues. This is very short explanation, but in general it adds unnecessary complexity. Use the simplest System/getenv. like (some-> (System/getenv "PORT") (Integer/parseInt) or with or to have default value if variable is empty. This is all what you need.

didibus15:09:21

I've never used it, but the readme doesn't mention generating files. Are you sure? Why would it generate a file?

kwladyka18:09:18

It generates .lein-env to read values later in the app from the file.

didibus21:09:28

That's just for development though, you're meant to use environment variables on your actual dev and prod environments

didibus21:09:08

As I understand, all it does is just look in the .lein-env or .boot-env file first, and if it doesn't find a value there, it'll look in the environment for an environment variable

didibus21:09:33

And then a lein/boot task let's you create those files so you can keep your overrides in the same project file.

kwladyka21:09:21

exactly and if you have during building value foo to true it will make .lein-env with this value. On the server you will set foo to false, but it will be true. Also you have to remember to copy .lein-env if to final image. Especially an issue when use multi step build in dockerfile.

didibus21:09:02

Is this because you deploy your app to prod with lein?

kwladyka21:09:04

the variables are designed to use them in environment and change there, not to use during build

didibus21:09:39

So why do you have a .lein-env in your docker image and prod environment?

kwladyka21:09:04

because otherwise I will lose all values used during build and all default values

kwladyka21:09:15

in general there is no point to use extra lib

kwladyka21:09:37

why even consider this?

kwladyka21:09:46

you can do your own research, but my experience saying me for 100% to not use any library of this kind

kwladyka21:09:21

it only increase complexity and make issues, which you will never have using System/getenv. And this is much simpler code.

didibus21:09:12

Well, if you want to use environment variables to configure things in your app per-environment. Then the issue is in development, it's annoying to set environment variables when launching a REPL or running tests. So you can set those variables locally when developing without using environment variables.

kwladyka21:09:02

I use .envrc if I want to set variables locally for the project

kwladyka21:09:55

Settings values for environment in project is bad design IMO. Including developing. Variables should be used as variables.

didibus21:09:16

Okay, so it's the same as using .envrc, what's the problem?

didibus21:09:23

Except it's a .lein-env file

kwladyka21:09:16

I don’t know if I can make it clearer :)

kwladyka21:09:52

It is just my recommendation based on my experience and this one I am very sure. Of course everyone can have own opinion and mine is mine 🙂

💯 1
didibus21:09:53

What I don't understand, so with .envrc, you copy that file into your docker container and deployment as well?

didibus21:09:16

Personally I recommend aero or something similar, and not to use environment variables. I was just curious

kwladyka21:09:28

no .envrc is only for developing. In all kind of enviornment on server variables are assigned by kubernetes manifest or other config for deployment.

Max21:09:28

The missing piece of info here might be the existence of https://direnv.net/, which is a program that reads .envrc and sets env vars when you go into a directory

kwladyka21:09:57

and plugins for editors to read values from .envrc

kwladyka21:09:21

variables are also unloaded when you leave project directory

kwladyka21:09:04

in general variables are for environment, should not pass to docker image

didibus21:09:53

I just don't understand why you don't do the same with environ as with .envrc

kwladyka21:09:59

PS I recommend to learn base of DevOps. It help to make much better architecture of the system and everything around.

didibus21:09:24

The same use of .envrc is what you do with environ from what I understand, except you define the variables in a profiles.clj instead

kwladyka21:09:52

.envrc is only for developing on software developer computer. It makes load / unload variables by automate for you for the project. You don’t copy it to docker image.

kwladyka21:09:12

it is totally different use

didibus21:09:15

Ya, so is environ. On prod, it's expected you've configured environment variables

didibus21:09:47

Copying the .lein-env file to docker is a huge mistake, I don't know why you would do that.

kwladyka21:09:04

no, it is expected to have configured variables during build and time of geneation .lein-env - huge difference

kwladyka21:09:24

But you have .lein-env in docker image to make it work. It is generated during the build in docker.

didibus21:09:28

Basically, all environ does is look for the variable as a Java property, if not found, as a system environment variable, if not found, in a .boot-env file, if not found in a .lein-env file. So what you do is during dev, you have in your Leon dev profile some overrides for development, so your app will pick those up, and in prod or dev stages it will use either Java property or system environment

didibus21:09:17

Look at readme:

The most common way during development is to use a local profiles.clj file in your project directory. This file contains a map with profiles that will be merged with the profiles specified in the standard project.clj, but can be kept out of version control and reserved for local development options.
{:dev  {:env {:database-url "jdbc:postgresql:}}
  :test {:env {:database-url "jdbc:postgresql:
l://localhost/test"}}}

kwladyka21:09:25

run your dokcer image and do cat .lein-env

kwladyka21:09:45

you really miss the point which I am talking about

kwladyka21:09:57

Maybe someone can help me to say this in other words

didibus21:09:22

I mean, if your docker image generated it, you've not configured things properly.

kwladyka21:09:44

you have this file. Do you use default values set in environ?

kwladyka21:09:31

so this values are in this file

didibus21:09:04

Default values, no. If you want default you'd do (or (environ/env :my-var) "default"))

kwladyka21:09:32

hmm so what is the reason why you use it?

didibus21:09:00

Same as .envrc and dotenv, but Clojure based for Clojure projects.

didibus21:09:34

I agree, if used as you describe it's a bad idea. I guess I just didn't think of using it like that haha

kwladyka21:09:49

most people do

kwladyka21:09:06

because they can 🙂

didibus21:09:32

Ya, then I agree with you. Maybe it isn't obvious how are the best way to use it and not. So I guess it could be dangerous recommendation if people end up using it like that.

kwladyka21:09:50

anyway everyone should use own favourite tools. I can’t shortly explain it, but in my opinion .envrc is better choice. Even for the reason it prevents developers to do mistakes which we were talking above and it doesn’t increase complexity of the code.

💯 1
didibus21:09:29

In any case, I personally recommend aero, and to minimize the use of environment variables as much as possible. Just is environment variable to tag the environment and then have the config for each in aero, so rollbacks and commits are in-sync with your code. And for secrets, use a secret manager that pushed the secrets in a file that only has read permission from the user that your app is running with.

didibus21:09:59

I'll check out .envrc, didn't know about dotenv, seems a more generic solution not exclusive to Clojure. Thanks!

kwladyka21:09:21

At least I like to not mix code of the project with things for environment. I mean if I modify system to simulate something for the environment I probably do something wrong. I like to keep system as pure as possible.

kwladyka21:09:39

.envrc is not part of the system and this is approach which I prefer

kwladyka21:09:50

the system is not affected

kwladyka21:09:00

I really recommend

kwladyka21:09:59

and you can use it with project.clj, deps.edn or with Python or whatever you like. Always the same.

kwladyka21:09:52

you can also do this with .envrc

cat .envrc
#export JAVA_HOME=/Library/Java/JavaVirtualMachines/adoptopenjdk-8.jdk/Contents/Home/
export JAVA_HOME=/Library/Java/JavaVirtualMachines/openjdk-11.jdk/Contents/Home

kwladyka21:09:22

no need to have any tools to manage java versions

didibus23:09:06

Does it work with editors? I guess if they go through shell it would, but if they start process directly?

kwladyka14:09:37

if start from shell it works, if not then it needs plugin