Fork me on GitHub
#beginners
<
2021-07-05
>
stagmoose15:07:21

I tried to follow the instruction from https://github.com/juxt/edge/tree/master/examples/tutorial.vent (I modified cd edge/tutorial.vent to cd edge/examples/tutorial.vent because the path in the doc is wrong) When I run $ ../bin/rebel --cljs -A:dev:build:dev/build , everything is fine and it showed a REPL. But when I enter (go) in the REPL, I got this error. How could I fix this.

marcofiset15:07:54

Did you load the file up into the REPL?

stagmoose16:07:23

@https://app.slack.com/team/U07SWUQTH no. First, I switch to the path edge/examples/tutorial.vent in terminal. And execute ../bin/rebel --cljs -A:dev:build:dev/build , which will bring up a REPL, then I enter (go)

stagmoose16:07:10

and error showed up after (go)

marcofiset19:07:25

I'm not familiar with Edge and this particular tutorial you're following. However, for the REPL to do anything useful like starting a project, you need to evaluate some code inside of it. Are you connected to the REPL through your code editor? If so, navigate to the file where the go function is defined and evaluate that file. Then the go function will be accessible inside your REPL.

marcofiset19:07:39

I read some about Edge, have you seen this particular section in the docs? https://www.juxt.land/edge/docs/dev-guide.html#_starting_your_system

stagmoose13:07:24

@U07SWUQTH yeah.I tried terminal repl and emacs cider. Both have the same error. Below is the error with using cider. It looks like the figweel things have some problems.

Karo15:07:47

Hi team, how can I create Java local date time in clojure for the given time? #object[java.time.LocalDateTime 0x7af2002a "2021-07-05T15:49:30.051"]

noisesmith15:07:34

@vnazaryan OK you want to produce a LocalDateTime - what is the input you are getting to produce it from?

noisesmith16:07:30

eg.

user=> (java.time.LocalDateTime/of 2020 7 5 9 1)
#object[java.time.LocalDateTime 0x737edcfa "2020-07-05T09:01"]

noisesmith16:07:38

if you have all the individual values as numbers

noisesmith16:07:39

anyway, your solution probably exists somewhere in the javadoc for LocalDateTime, it took me a minute and a half to figure that out from the page

Pavel Klavík16:07:37

@vnazaryan if you are unfamiliar with Java interop, I recommend checking this guide: https://clojure.org/reference/java_interop.

bigos16:07:58

I have deps.edn with :paths ["src" "resources" "../reportgenerator/build/web/WEB-INF/classes"] . In the classes folder I have itils folder and in it I have several classes that I want to import into clojure project. I import it like this (:import (utils Result SalXmlDocument Sample)) , but that gives me errors :clojure.error/class java.lang.ClassNotFoundException, :clojure.error/cause "java.lang.SalXmlDocument"},

seancorfield16:07:13

@ruby.object Having :paths outside your project like that is deprecated (and will be disallowed), so that is not a solution.

didibus17:07:04

Any reason why the change? We also often have mixed Clojure/Java projects where some Java code-gen runs as part of the Java build and puts generated classes in some folder that are needed for the REPL.

seancorfield17:07:59

I'll defer to @U064X3EF3 to explain with :paths outside a project was deprecated.

Alex Miller (Clojure team)18:07:41

Having generated classes in a folder is fine, it should just be a folder inside the project

Alex Miller (Clojure team)18:07:45

Accessing arbitrary paths outside the project root is a potential security issue and the Clojure CLI will currently print a warning if you do this (and eventually we plan to error in this case)

2
didibus16:07:18

What's the security issue? If someone can modify my deps.edn, they can as easily just put a class inside the same folder.

didibus17:07:20

In my case, the classes are generated outside the project folder. Because they're actually part of a dependency. The Java build is setup to generate classes, and build multiple projects and dependencies, and then it grabs the union of it all, and puts it in the workspace folder, inside the workspace folder are multiple projects. So now inside one of those projects I want to start a REPL, and so I need to point it to the classes folder of the workspace.

Alex Miller (Clojure team)17:07:35

if they're a dependency, then use a :local/root dep

Alex Miller (Clojure team)17:07:15

we are definitionally saying that a project's paths are descendants of the project root only

Alex Miller (Clojure team)17:07:29

if you pick up a lib with external :paths as a git dep, this will point to some random point on the dependee's drive - this is not meaningful across users

didibus17:07:35

Will local/root work for a folder of .class files?

Alex Miller (Clojure team)17:07:23

if you create a deps.edn pointing to that dir in :paths, yes

didibus17:07:48

That's the problem, I need it to play along with the Java build system

Alex Miller (Clojure team)17:07:02

how is that at odds with a Java build system?

didibus17:07:03

So those Java dependencies will not have deps.edn of their own

didibus17:07:47

And some of them are code-gen packages, they don't even have Java source, but XML that generates Java client code

Alex Miller (Clojure team)17:07:59

are these Java deps you control? if so, you can add a deps.edn

didibus17:07:19

I do not, big company, lots of teams, those are other teams packages

Alex Miller (Clojure team)17:07:33

and you just get folders of classes? not jars?

Alex Miller (Clojure team)17:07:50

:local/root can point to a .jar file

didibus17:07:03

Yes, though there might be a corresponding Jar as well. I would need to verify. The code-gen package is the one I'm not sure if it would.

didibus17:07:50

Currently I use lein and a plugin that lets me add my own paths to the lein classpath. I was hoping to move to deps.edn at some point. That's why I ask

Alex Miller (Clojure team)17:07:56

I imagine there are potentially many ways to accomplish a workaround, but you're out of normal scope for a deps project

didibus17:07:09

So the envisioned development flow if say you work on a Java package and a Clojure package where the Clojure package depends on the Java one is that you'd build the Java one locally to a Jar and use local/root in the Clojure one?

seancorfield17:07:36

I would probably colocate them so I could work on the Java and Clojure together, which solves a lot of these problems, but then I'm a fan of monorepos anyway, even multi-lingual ones.

seancorfield17:07:24

Then you can have the classes folder that the Java builds into be a :paths entry within the (Clojure) projects, since they are both in the same tree.

didibus17:07:09

What if :paths didn't allow paths outside the folder, but it was allowed for :extra-paths? I understand as the main :pathsits weird that a project could depend on things that are environment dependent. But extra-paths will always be used in an alias or other "profile" like things, used for development.

seancorfield17:07:46

:extra-paths is just added to :paths so I think the same rules should apply. If something is external to your project, it's a dependency not a path.

didibus17:07:50

In my case, I have to work with what we have and it's setup to not be a monorepo. So each package is its own repo. In the past I used symlinks, but those require a lot of manual labor to maintain. And every new hire that joined the team you'd have to set it up for them as well. With relative paths, a simple convention works, you just say clone all your repos in the same folder, and it'll all just work with relative paths

didibus17:07:29

As a dependency it works too, but local/root only supports Jar dependencies for Java. So maybe it could also support Java class folders?

didibus17:07:22

Though I can also see an issue with resource folders if treated purely as a dependency.

seancorfield17:07:39

If each project is separate, each project should produce a reusable artifact. A directory full of .class files is not an "artifact".

didibus17:07:27

That's a matter of perspective 😂. The build system is quite sophisticated. So actually when it pull down dependencies it doesn't pull down Jars, but .class files into a global local folder under versioned paths. If you have many packages that all depends on the same version of the class it'll all symlink things so the dependency closure of each package is pointing to the correct place. And it does the closure at a workspace level based on the "main" package as the start entry.

didibus17:07:33

I might experiment with seeing if I can set things up with deps.edn without using :paths and I'll report back. Maybe local/root with Jars can work

seancorfield17:07:35

That's a very strange definition of "sophisticated" in my view... 🙂

didibus17:07:47

I don't know, how deps is encouraging git deps, you could argue in Java Jars are complicated and a build folder of classes with a launch script in it would have been simpler

didibus17:07:10

I think the reason it does that is because it supports more than just Java. The artifact repository has artifacts for all programming languages

didibus17:07:09

So for example I could take a dependency on a package that has an executable script, and it would pull it down as well

Alex Miller (Clojure team)18:07:59

tools.deps as a library is extensible to whatever custom "dep" type you'd like to plugin via the extension points (but you're at that point outside what the Clojure CLI currently supports)

didibus18:07:51

Hum, I just remembered that with lein I even need to custom generate some paths each time it runs dynamically.

didibus18:07:22

If I extend a customer dep type, can I plug my extension into deps.edn in a way that tools will transparently work with it?

didibus18:07:14

Like say I need a custom deps type, and I define things with it in my deps.edn. And now I want Cursive to start a repl with deps.edn but for it to work with my custom deps type?

didibus18:07:42

Like lein has :plugins for that

Alex Miller (Clojure team)18:07:45

the Clojure CLI does not yet have a way to define and load custom extensions

Alex Miller (Clojure team)18:07:25

Cursive can use tools.deps directly but also does not have any place to do that afaik

Alex Miller (Clojure team)18:07:45

but if you use tools.deps as a library, it's just a matter of loading a namespace that extends the multimethods

Alex Miller (Clojure team)18:07:19

I've been delaying doing anything with the CLI until someone actually cared :)

didibus18:07:10

Fair fair. For now I'm happy with lein, the point is mostly to get tools to play nice with our internal package manager. And Lein with some plugins did the trick. Once I experiment with trying to switch to tools.deps instead I'll report my blockers if any.

seancorfield18:07:46

(and we can follow-up in #tools-deps)

👍 2
bigos16:07:50

what can i do to accecc the tree of java classes?

Drew Verlee16:07:25

i'm not sure myself, does the :local path key support that?

bigos16:07:36

is symbolic link good enough?

bigos16:07:48

what are the options? how can I do a non trivial java interop?

Drew Verlee16:07:46

there might be a very good reason, i just haven't run into it or i'm confused, why are your class files not in a jar?

2
bigos17:07:16

I have a legacy netbeans app and I was thinking about using it's classes to import to clojure and create a jar file from clojure code to be used by the netbeans app

bigos17:07:47

is it overly too convluted?

bigos17:07:55

is it possible to gradually refactor the old app into clojure? or should I quit the job?

Drew Verlee17:07:45

if you can produce a jar from the netbeans app, then i believe deps should be able to pick it up and use the code. Then you can recompile. But I would wait tell someone with more experience doing this answers. Your question was interesting because i hadn't ever considered the situation.

bigos17:07:39

this trivial example works

bigos17:07:53

problems start with real life app

seancorfield17:07:46

It sounds like you are really more interested in calling into Clojure from the legacy NetBeans app?

seancorfield17:07:20

(and ultimately replacing the Java code with Clojure, working from the ground up)

seancorfield17:07:59

There are two or three possible approaches but the one I prefer -- because it's how we refactored our legacy app to use Clojure (and then, ultimately, replaced the legacy app completely with Clojure) is to leverage Clojure's Java API https://clojure.org/reference/java_interop#_calling_clojure_from_java

seancorfield17:07:31

You can start by adding Clojure as a regular dependency on your legacy app -- Clojure is "just" a library, like anything else you're already using in the legacy code. And gradually, as you write more Clojure to replace the Java code, start adding more Clojure libraries as dependencies.

seancorfield17:07:37

You would also need your Clojure project's src folder added to the classpath of your legacy app (so the legacy project could "see" your Clojure code when it is referenced via the Java API).

bigos17:07:24

that is what I had in mind. to some extent you confirm my idea. But I am stuck at the clojure being a library of my legacy app. For some hope of success that clojure library has to work and finding the examples is not easy. to have a woking library for the legacy app I need to be able to import some classes.

bigos17:07:25

I had success with trivial app https://github.com/bigos/JavaApplication3 also at some point I was able to import legacy java classes to my clojure app, but for some reason it stopped working.

seancorfield17:07:14

I know nothing about NetBeans, but the first step will be to add org.clojure/clojure as a dependency to your Java project (with version "1.10.3") and in your existing Java code, try out what I linked to above: referencing some clojure.core functions.

bigos17:07:21

The problem is calling clojure from java side

bigos17:07:24

public static String passTheData(SalXmlDocument info) { // use the new class for more talking to clojure hmm.report.foo("hello"); hmm.report.passdata(info);

bigos17:07:31

hello did work

bigos17:07:52

but how do i pass to clojure an instance of a class?

bigos17:07:02

is my strategy correct?

seancorfield17:07:41

Did you read the page I linked, explaining Clojure's Java API?

seancorfield17:07:51

You can avoid all the gen-class pain.

bigos17:07:35

not yet, i will now

bigos17:07:37

that page does not say what should be the corresponding code on clojure side

bigos17:07:23

https://clojure.github.io/clojure/javadoc/clojure/lang/IFn.html mentions only Objects, how do I pass a hash, or instance of an object

seancorfield17:07:07

Everything in Java is an Object. You can pass in anything.

seancorfield17:07:54

And the Clojure code is just regular Clojure code.

bigos17:07:29

so why does medthod give me errors

bigos17:07:52

:methods [#^{:static true} [foo [String] void] #^{:static true} [ldata [SalXmlDocument] void] #^{:static true} [tryme [Object] void]]

bigos17:07:10

do i even need to declare the types of arguments

seancorfield17:07:38

You don't need any of that if you call into Clojure from Java via Clojure's Java API that I linked to.

bigos18:07:56

i'll give it a try

bigos18:07:25

found good example

bigos18:07:11

question how to do it with deps edn

seancorfield18:07:02

No, you don't want deps.edn for this: just add Clojure to your existing Java project. You'll use whatever tool your Java project uses to build the Java code already.

seancorfield18:07:07

You know how to build the existing NetBeans Java project, yes @ruby.object?

seancorfield18:07:33

And you have a list of its current dependencies in some NetBeans config?

bigos18:07:54

i can find it

bigos18:07:05

i have a project.xml file with jar dependencies

seancorfield18:07:06

Excellent! So you can add Clojure to that.

bigos18:07:22

how do i do it?

bigos18:07:52

because at the moent i was using clojurte to create jar file

seancorfield18:07:11

Your project.xml has sections like this?

<groupId>javax.media</groupId>
  <artifactId>jmf</artifactId>
  <version>2.1.1e</version>

seancorfield18:07:59

Clojure is "just" a dependency like:

<groupId>org.clojure</groupId>
  <artifactId>clojure</artifactId>
  <version>1.10.3</version>

seancorfield18:07:39

And you should be able to rebuild your Java project and it will add Clojure to it.

bigos18:07:43

<library dirs="200"> <file>${file.reference.mockito-all-1.10.16.jar}</file> <path-in-war>WEB-INF/lib</path-in-war> </library>

bigos18:07:59

i was looking in the wrong place, one moment please

bigos19:07:58

mind you it's netbeans 8 😞

seancorfield19:07:06

The NetBeans UI probably has an option somewhere to "add dependency" if you're used to doing it that way...

seancorfield19:07:20

(like I say, I have never used NetBeans...)

bigos19:07:52

well i use ant

bigos19:07:57

it is so old

seancorfield19:07:26

Well, something somewhere in the project has to have the list of dependencies. When you find that, you can add Clojure to it.

bigos19:07:57

i foud a dialog for it

bigos19:07:51

and it leads to the jar dialog

bigos19:07:39

has the option to download the jar file, I'm back on track

seancorfield19:07:49

That will not work. You need to specify Clojure as a dependency not a downloaded library.

seancorfield19:07:25

Clojure itself depends on two other libraries. Downloading the JAR will not give you those libraries so your code will fail (in ways you will find hard to debug).

seancorfield19:07:57

Please figure out how to add dependencies to your Java project and add Clojure that way.

bigos20:07:30

so does that mean that i need to find ways to convert the project to maven first?

seancorfield20:07:36

As I keep saying, I know nothing about NetBeans. Somehow, somewhere, your existing Java project must have a way of declaring/specifying its existing dependencies. Those are being fetched from Maven. Clojure is on Maven. So you can add Clojure as a dependency to the existing Java project somehow and that's all you need.

seancorfield20:07:42

NetBeans itself definitely lets you add new dependencies to a project (not JAR files, not class libraries, actual dependencies). You need something that understands Maven-style dependencies to fetch Clojure for you, so that transitive dependencies are also fetched.

seancorfield20:07:04

Who built this project in the first place? Can you ask them about adding a dependency?

seancorfield20:07:32

(since you said "or should I quit the job?" I assume you have colleagues you can ask about this project)

bigos20:07:32

they no longer work here

bigos20:07:07

the company is interviewing a java programmer this week I am not a java programmer

seancorfield20:07:08

Well, then you're probably not going to be able to mix Clojure and Java if you can't find out or figure out how to add Maven-style dependencies to that existing project, sorry.

seancorfield20:07:37

Once they hire a Java programmer, there will be someone who can set that up for you.

bigos20:07:06

I'm sure there are a lot of legacy projects that would benefit from clojure, but why is is so hard, are people so fed up with the old projects so that they rewrite them from scratch?

seancorfield20:07:33

It isn't hard. It just assumes some knowledge about the Java ecosystem which you don't have, unfortunately.

bigos20:07:46

thank you very much for your help, especially for your deps.edn that I regularly copy

bigos20:07:02

have a good night

seancorfield20:07:06

Sorry I can't really help you with this 😞

bigos20:07:21

you are not the first one

bigos20:07:34

usually people give up much sooner

seancorfield20:07:45

Haha... OK, fair enough.

bigos20:07:46

I have emailed my boss saying i am making progress. i will have some explaining tomorrow

seancorfield20:07:48

If it was publicly accessible, I could probably dig into it some more, but right now I don't even know what to suggest you look for in the project (since I gather it doesn't have pom.xml which would be the telltale sign of Maven?).

seancorfield20:07:38

Is the build.xml file just running javac with no dependency management stuff in place at all?

seancorfield20:07:09

(I can't imagine the code uses no external libraries at all but I suppose that is technically possible)

bigos20:07:30

$ tree ./nbproject/ ./nbproject/ ├── ant-deploy.xml ├── build-impl.xml ├── build-impl.xml~ ├── genfiles.properties ├── private │   ├── private.properties │   └── private.xml ├── project.properties ├── project.xml └── rest-build.xml

bigos20:07:32

$ ls ./*.xml ./build.xml

bigos20:07:16

jacekp@EID6043:~/code/AAA-java/reportgenerator$ tree ./lib/ ./lib/ ├── bcmail-jdk15on-1.67.jar ├── bcpg-jdk15on-1.67.jar ├── bcpkix-jdk15on-1.67.jar ├── bcprov-jdk15on-1.67.jar ├── cds.astro.jar ├── clojure-1.10.2.jar ├── commons-lang-2.6.jar ├── core-renderer-R8.jar ├── javacsv.jar ├── javax.mail-1.6.2.jar ├── lidlcsvreport.jar ├── mockito-all-1.10.16.jar ├── multipart.jar ├── opencsv-5.1.jar ├── openpdf-1.3.23.jar └── unbescape-1.1.6-SNAPSHOT.jar

bigos20:07:33

the code is 10-15 years old

seancorfield20:07:12

Out of curiosity, what version of Java is it running with?

bigos20:07:57

$ tree -d ./src/ ./src/ ├── conf └── java ├── emailing ├── exceptions ├── sal │   ├── calculations │   ├── reports │   │   ├── animal_feed │   │   ├── content_producers │   │   ├── micro │   │   └── tools │   ├── stamps │   └── user_options ├── servlets ├── utils └── xml └── regulatory_methods

bigos20:07:13

$ java -version java version "1.8.0_162" Java(TM) SE Runtime Environment (build 1.8.0_162-b12)

bigos20:07:35

src folder has dozens of classes in the src folder

seancorfield20:07:49

At least you're on Java 8 🙂

seancorfield20:07:27

OK, so since you've gotten as far as manually downloading Clojure 1.10.2, here are the other libs you'll need to download to at least move forward:

org.clojure/clojure 1.10.2
  . org.clojure/spec.alpha 0.2.194
  . org.clojure/core.specs.alpha 0.2.56

seancorfield20:07:39

If you download those manually from Maven, like you did for Clojure, and put them in lib, you should at least be able to try the Java -> Clojure calls into clojure.core per the example linked somewhere above.

seancorfield20:07:08

It'll be painful to add any new Clojure libraries or update Clojure etc but it should at least get you to a working state for something basic.

seancorfield20:07:08

Then, in some Java code in the project, you should be able to import clojure.java.api.Clojure; and import clojure.lang.IFn; and then do this:

IFn plus = Clojure.var("clojure.core", "+");
plus.invoke(1, 2);

seancorfield20:07:24

As for writing your own Clojure code and being able to require and invoke that, you'll need your (Clojure) src folder to be on the project's classpath but I'm sure where to suggest putting that or how to configure the app to add it...

seancorfield20:07:12

In the Java code you could call System.getProperty( "java.class.path" ); to see what is on the current classpath and maybe there's an "obvious" safe place to put your src folder in some directory on that classpath...?

bigos20:07:34

no error bu bnothing is printed

bigos20:07:37

i guess i can try to figure it out later

bigos20:07:08

you think about the question i was asking myself about the src for clojure

seancorfield20:07:13

I expect you'd have to log the result or print it -- however the current project writes stuff to a console log...

bigos20:07:29

sadly i do not know where to star and I need to call it a day

seancorfield20:07:37

That getProperty() call is just going to return a string.

seancorfield20:07:52

OK, well, good luck tomorrow. We'll be here 🙂

bigos20:07:56

ant -f /home/jacekp/code/AAA-java/reportgenerator -Djavac.includes=servlets/GeneratorServlet.java -Dnb.internal.action.name=debug.single -Ddirectory.deployment.supported=false -DforceRedeploy=false -Dbrowser.context=/home/jacekp/code/AAA-java/reportgenerator/src/java/servlets/GeneratorServlet.java -Ddebug.class=servlets.GeneratorServlet debug-single-main init: deps-module-jar: deps-ear-jar: deps-jar: compile-single: Generating Report - ReportID : 1388907 - Report Type : +44 - UserName : jacekp - Location : Concept Loading KeyStore File URL: http://localhost:10000/xml/report/generate/1388907Converting stream to string Starting loading groups from XML group = Pesticide Screen (GC CSOPP611 & LC CSOPP603 Reg) group = Fosetyl-Al (sum fosetyl + phosphorous acid and their salts, express as fosetyl) group = Miscellaneous group = Miscellaneous group = Pesticide Screen (GC CSOPP611 & LC CSOPP603 Reg) Finished Loading Groups from XML Report Unit : 1' : kg Report Unit : 3' : mg for 5 : null Parsing new report : before trying clojure after trying clojur

bigos20:07:21

public static String passTheHash(SalXmlDocument info) { System.out.println("before trying clojure"); IFn plus = Clojure.var("clojure.core", "+"); plus.invoke(1, 2); System.out.println("after trying clojure");

seancorfield20:07:01

System.out.println( plus.invoke(1, 2) );

seancorfield20:07:12

Then at least you should see the result printed 🙂

bigos20:07:48

before trying clojure 3 after trying clo

bigos20:07:20

now how do i invoke real clojure code?

seancorfield20:07:46

Well, you have to figure out how to add a src folder to the app's classpath somehow.

seancorfield20:07:14

Then you just write your Clojure code in that folder, and use var/`require` to make it accessible to Java.

bigos20:07:27

i just had idea

bigos20:07:37

i will just commit what i have so far

bigos20:07:47

i do not want to lose your precious code

seancorfield20:07:38

IFn require = Clojure.var("clojure.core", "require");
require.invoke("your.namespace");
IFn yourFunc = Clojure.var("your.namespace","your-func");
yourFunc.invoke(...);

bigos20:07:51

do i put the hole project?

bigos20:07:15

lidlcsvreport$ tree . ├── CHANGELOG.md ├── classes │   └── sal │   └── reports │   └── LIDL_Pesticide_Report.class ├── copy-java-classes ├── deps.edn ├── doc │   └── intro.md ├── LICENSE ├── lidlcsvreport.jar ├── pom.xml ├── README.md ├── http://README.org ├── resources ├── src │   └── sgs │   └── lidlcsvreport.clj └── test └── sgs └── lidlcsvreport_test.clj

bigos20:07:39

or just src of the clojure project?

seancorfield20:07:58

Start small. Start by just adding a src folder and some simple code and make sure you can call it.

seancorfield20:07:20

Remember that this is a Java project: the deps.edn etc is irrelevant.

bigos20:07:39

i did not know that

seancorfield20:07:52

You're not building Clojure to a JAR or compiling it to classes.

bigos20:07:05

perhaps i shold remove the jar cleated by deps.edn

seancorfield20:07:22

You're using Clojure source code inside the Java project, and relying on the require invocation to load and compile it.

bigos20:07:44

in netbeans i hace sources dialog with src and test declared

bigos20:07:53

maybe this is the way out

seancorfield20:07:19

I don't think so. For a Java project, that's just where to find the Java source code -- it's not about the classpath.

seancorfield20:07:25

System.out.println( System.getProperty( "java.class.path" ) );
^ that in your Java code will print out what the class path is when the Java code runs.

bigos20:07:41

i have created clojure-src folder at the root of java project and uses the properties/sources dialog to add it to the project

seancorfield20:07:04

I don't think that will work because I don't think that will affect the classpath.

bigos20:07:34

claspath is void

bigos20:07:42

do i need to import systemk?

seancorfield20:07:03

What does System.out.println( System.getProperty( "java.class.path" ) ); print?

bigos20:07:21

before classpath /home/jacekp/code/AAA-java/reportgenerator/build/web/WEB-INF/classes:/home/jacekp/code/AAA-java/reportgenerator/lib/bcmail-jdk15on-1.67.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/bcpg-jdk15on-1.67.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/bcpkix-jdk15on-1.67.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/bcprov-jdk15on-1.67.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/cds.astro.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/commons-lang-2.6.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/core-renderer-R8.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/javacsv.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/javax.mail-1.6.2.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/mockito-all-1.10.16.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/multipart.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/opencsv-5.1.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/openpdf-1.3.23.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/unbescape-1.1.6-SNAPSHOT.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/clojure-1.10.2.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/core.specs.alpha-0.2.56.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/spec.alpha-0.2.194.jar:/home/jacekp/netbeans-8.2rc/enterprise/modules/ext/jaxrs-2.0/javax.ws.rs-api-2.0.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jboss-javaee.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/activation.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/jaxb-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/jbossws-native-jaxrpc.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/jbossws-native-jaxws-ext.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/jbossws-native-jaxws.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/jbossws-native-saaj.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/resolver.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/serializer.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/stax-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/xalan.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/endorsed/xercesImpl.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/concurrent.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/dom4j.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/getopt.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/javassist.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jaxb-impl.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jaxb-xjc.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-asintegration-core.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-asintegration-jmx.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-asintegration-mc.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-deployers.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-jboss5.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop-mc-int.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-aop.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-bootstrap.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-classloader.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-classloading-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-classloading-vfs.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-classloading.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-common-core.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-dependency.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-client-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-client.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-core-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-core.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-impl.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-structure-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-vfs-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-deployers-vfs.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-j2se.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-jmx.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-kernel.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-logbridge.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-logging-jdk.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-logging-log4j.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-logging-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-logmanager.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-main.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-managed.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-mbeans.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-mdr.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-metatype.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-profileservice-spi.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-reflect.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-system-jmx.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-system.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-vfs.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/jboss-xml-binding.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/log4j-boot.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/osgi.core.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/trove.jar:/home/jacekp/apps/jboss-5.1.0.GA/lib/wstx.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jbossws-native-jaxws-ext.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/ejb3-persistence.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/mail.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/el-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jbossws-native-jaxrpc.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jbossws-native-saaj.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jbossws-native-jaxws.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/servlet-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/hibernate-entitymanager.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jsp-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/common/lib/jboss-jsr77.jar:/home/jacekp/apps/jboss-5.1.0.GA/server/default/deployers/ejb3.deployer/jboss-ejb3-deployer.jar:/home/jacekp/apps/jboss-5.1.0.GA/server/default/deployers/ejb3.deployer/jboss-ejb3-iiop.jar:/home/jacekp/apps/jboss-5.1.0.GA/server/default/deploy/jbossweb.sar/jsf-libs/jsf-api.jar:/home/jacekp/apps/jboss-5.1.0.GA/server/default/deploy/jbossweb.sar/jsf-libs/jsf-impl.jar:/home/jacekp/apps/jboss-5.1.0.GA/server/default/deploy/jbossweb.sar/jstl.jar after classpat

seancorfield20:07:32

Thanks. Just a sec...

bigos20:07:39

lots of jboss

seancorfield20:07:22

Hmm, so /home/jacekp/code/AAA-java/reportgenerator/build/web/WEB-INF/classes is the only actual folder on the classpath...

bigos21:07:34

that is where the classes appear when I press compile button

seancorfield21:07:07

Yeah, expected. I was hoping for some other folder where you could safely put Clojure source code 🙂

seancorfield21:07:28

When we were adding Clojure to our legacy app, we edited the app's config to add an additional folder to the classpath at startup (our Clojure src folder).

seancorfield21:07:05

Do you always run the project via ant like that? Or does it normally run as a web app?

bigos21:07:40

its a web app when it's deployed

seancorfield21:07:55

OK, so ant is just for testing it?

bigos21:07:57

but i use mockito to cheat around that

bigos21:07:09

mockito is for testing

bigos21:07:27

ant is for buildung war file that is rsynced to the server

seancorfield21:07:07

It looked like you were using ant to actually run the code for testing that the Clojure invocation worked.

bigos21:07:15

public static void main(String[] args) throws ServletException, FileNotFoundException, IOException, MissingValuesException, NoSuchAlgorithmException, CertificateException, KeyStoreException { HttpServletRequest request = mock(HttpServletRequest.class); HttpServletResponse response = mock(HttpServletResponse.class); // insert parameters here // when(request.getParameter("reportid")).thenReturn("1366796"); when(request.getParameter("reportid")).thenReturn("1388907")

seancorfield21:07:32

Right, and that's the "single-debug-main"?

bigos21:07:11

yes, almost some classes have their debug mains

bigos21:07:56

could that be a clue?

seancorfield21:07:42

I wouldn't bother trying to follow something so old.

seancorfield21:07:17

If you have a small, simple Clojure project, you can ask Clojure to compile a namespace to .class files in a specific target directory from the REPL:

user=> (binding [*compile-path* "/home/jacekp/code/AAA-java/reportgenerator/build/web/WEB-INF/classes"]
          (compile "your.namespace"))
That would let you write Clojure in a separate folder, and compile it into that classes folder so it would be accessible to the Java code (via the var/`invoke` calls).

seancorfield21:07:05

What I'm trying to help you avoid is having to write all the gen-class stuff since that's so painful and also it requires the compiled Java classes to be on your Clojure classpath -- which would mean your Clojure project would have to live in that same tree so it could be on your :paths. Code compiled per above, into the WEB-INF/classes folder, would then be on the classpath when the Java code runs so that your Java code could require it -- but I worry that classes folder gets cleaned out each time to build the Java code (which would erase your Clojure code).

seancorfield21:07:51

You could also build an uberjar of your Clojure project -- without AOT -- and put that in lib (you wouldn't need the Clojure JARs in lib then because Clojure would be in your uberjar) and, again, access the Clojure code via require as above.

bigos21:07:40

.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/clojure-1.10.2.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/core.specs.alpha-0.2.56.jar:/home/jacekp/code/AAA-java/reportgenerator/lib/spec.alpha-0.2.194.jar:/home/jacekp/code/AAA-java/reportgenerator/src/clojure:/home/jacekp/netbeans-8.2r

bigos21:07:20

i have :/home/jacekp/code/AAA-java/reportgenerator/src/clojure: in the classpath

bigos21:07:37

the dialog for adding jars is confusing

bigos21:07:47

it allows aslo to add folders

seancorfield21:07:03

Yay! :thumbsup::skin-tone-2:

seancorfield21:07:44

So now you can put example.clj unto that src/clojure folder with (ns example) and a function in it, and try requiring/invoking it from the Java code.

seancorfield21:07:20

(baby steps, to verify each new piece works!)

bigos21:07:58

i tried somethis else and now i will be wiser and will follow the baby steps

bigos21:07:27

Exception in thread "main" java.lang.IllegalStateException: Attempting to call unbound fn: #'example/requi

bigos21:07:38

// any other namespace than clojure.core needs to be "required" IFn require = Clojure.var("example", "require"); require.invoke(Clojure.read("example")); IFn foo = Clojure.var("", "foo"); System.out.println(foo.invoke());

bigos21:07:46

after classpath we have another failure add: null

bigos21:07:13

(ns example) (defn foo [] (println "we have another failure"))

bigos22:07:07

we never agreed on paying you evening rate so I am not expecting to give you lots of money

bigos22:07:20

but your effort needs some reward

seancorfield22:07:02

IFn require = Clojure.var("clojure.core", "require"); // this is a core function

seancorfield22:07:26

Then

require.invoke(Clojure.read("example"));
IFn foo = Clojure.var("example", "foo"); // needs the ns for example/foo

bigos08:07:11

I got it working 🙂 thank you. I am sure I will ask more questions on slack, but I will always remain grateful for your help.

2
stopa17:07:51

Hey team, I am playing with the slack api. To use their thing, I need to reify the https://github.com/slackapi/java-slack-sdk/blob/ce13f06e99d3b2c9234d871bbb2ebeedb9fdf282/bolt/src/main/java/com/slack/api/bolt/handler/builtin/SlashCommandHandler.java#L9 To do that, I wrote this:

(let [config ;;
        app (App. config)
        server  (SlackAppServer. app)]
    (.command app "/hello"
              (reify SlashCommandHandler
                (apply [this req ctx]
                  (.ack ctx ":wave Hello!"))))
    (.start server))
The error I get is:
[qtp740546585-42] ERROR com.slack.api.bolt.servlet.SlackAppServlet - Failed to handle a request - class java.lang.String cannot be cast to class com.google.gson.JsonElement (java
.lang.String is in module java.base of loader 'bootstrap'; com.google.gson.JsonElement is in unnamed module of loader 'app')                          
java.lang.ClassCastException: class java.lang.String cannot be cast to class com.google.gson.JsonElement (java.lang.String is in module java.base of loader 'bootstrap'; com.googl
e.gson.JsonElement is in unnamed module of loader 'app')
        at consistent_slack.core$_main$reify__1646.apply(form-init998480002803844197.clj:15)
My understanding of reify, is a bit wonky. Any guidance on how I can think about what is happening here, much appreciated!

seancorfield17:07:55

ack is here https://github.com/slackapi/java-slack-sdk/blob/master/bolt/src/main/java/com/slack/api/bolt/context/Context.java#L92 and expects JsonElement but you passed a String -- which is what the error says.

👍 4
stopa17:07:48

Thanks for the resp Sean! Based on the SlashCommandHandler interface, I thought the context was this: https://github.com/slackapi/java-slack-sdk/blob/ce13f06e99d3b2c9234d871bbb2ebeedb9fdf282/bolt/src/main/java/com/slack/api/bolt/context/builtin/SlashCommandContext.java#L51-L53 which has a ack(String implementation. Am I misunderstanding how above is functioning?

Drew Verlee17:07:04

what the heck java

😕 4
Drew Verlee17:07:51

what does clash command response.builder do

Drew Verlee17:07:15

i mean , imagine it tries to build a json from a string

seancorfield17:07:32

I think the issue here is that those types are available via generics to the Java compiler -- but generic types don't exist in compiled code -- they are erased -- so the information that Clojure has available only has the raw types.

seancorfield17:07:04

(generics are compile-time polymorphism, effectively, but not actual dynamic polymorphism)

phronmophobic17:07:15

Most of slack's APIs are just http calls that receive and return json. I would probably ignore their Java library and just interface with their http API

2
☝️ 6
seancorfield17:07:51

Yes, that's how we interact with Slack from Clojure. Far easier than their ridiculously convoluted Java SDK.

seancorfield17:07:54

The addition of generics was about when I quit Java. Having spent years on the C++ Standards Committee, working on the specification of templates, I didn't want to deal with a watered down version of that in Java!

stopa17:07:49

Thanks team! > I think the issue here is that those types are available via generics to the Java compiler -- but generic types don’t exist in compiled code -- they are erased -- so the information that Clojure has available only has the raw types. Appreciate the depth Sean. Would love to understand this more. Which type is being erased here? (i.e I am not sure what you mean by “this type is available via generics to the Java compiler”, but not to our compiled code via Clojure) (indeed http api may be best, but am trying to smack a few things together as demo, and ideally would like to get this guy to work. Though yeah — oof — very darn convoluted)

Drew Verlee17:07:48

I think of you pass a valid Json string I think it might work. I don't think :hello is valid

seancorfield17:07:03

@stopachka Java generics only exist in the (Java) compiler. They don't exist at runtime -- they're not in the .class files -- which is what Clojure has to work with.

stopa17:07:12

@U0DJ4T5U1 I’m not quite sure I understand:

(.command app "/hello"
          (reify SlashCommandHandler
            (apply [this req ctx]
              (.ack ctx ":wave Hello!"))))
Do you mean wrap ":wave Hello!" like this ? "\":wave Hello!\""

stopa17:07:24

@seancorfield — wanted to confirm — in this context is the generic “JsonElement”?

seancorfield17:07:48

The <CTX extends Content> stuff is the generics.

stopa17:07:58

Aha! I see

stopa17:07:08

(wait, maybe not — apologies for the noob questions — looking now at where this is written)

stopa17:07:44

I think I understand what you mean, but am not sure where this is happening. https://github.com/slackapi/java-slack-sdk/blob/ce13f06e99d3b2c9234d871bbb2ebeedb9fdf282/bolt/src/main/java/com/slack/api/bolt/context/builtin/SlashCommandContext.java#L24 ^ this says CTX extends Context, but why is this a generic? (I thought this was inheritence)

Drew Verlee17:07:08

I was thinking "1", instead of ":hello..."

seancorfield17:07:59

Generics are compile-time only for Java. They do not exist in the bytecode so no other languages see any of that generic stuff when compiling against Java .class files. I don't know how to say it any differently.

stopa17:07:43

Thanks for bearing with me Sean. What I don’t understand is the following: I don’t see where a generic is written in the source code above.

The <CTX extends Content> stuff is the generics.
Where is this stuff?

stopa18:07:17

Aah! Okay, this makes sense. Thank you!

stopa18:07:14

So if I understand correctly: • The above interface is only understood by java, as it uses generics • From clojure side, it doesn’t know the class of CTX when our SlashCommandHandler runs, and defaults to the base Context type

stopa18:07:08

Okay,

(.command app "/hello"
          (reify SlashCommandHandler
            (apply [this req ctx]
              (let [^SlashCommandContext x ctx]
                (.ack x "hello!")
                )
              )))
The following makes it work! Thanks for bearing with me and for the time @seancorfield @U0DJ4T5U1

seancorfield18:07:40

Woohoo! 🙂

🔥 2
2
2
stopa18:07:30

Okay, one more esoteric java noob q:

import com.slack.api.methods.response.chat.ChatPostMessageResponse;
import com.slack.api.model.event.ReactionAddedEvent;

app.event(ReactionAddedEvent.class, (payload, ctx) -> {
If I wanted to convert this to clojure, how would I convert passing in ReactionAddedEvent.class ? I am trying:
(.event app
        (class MessageEvent)
        (reify BoltEventHandler
          (apply [this evt ctx]
            (log/info "ctx")
            (log/info ctx))))
But am getting:
{:type java.lang.IllegalArgumentException                                              
   :message Unexpectedly failed to register the handler                                  
   :at [ event App.java 564]}]     
Which makes me think I am not correctly converting MessageEvent.class https://github.com/slackapi/java-slack-sdk/blob/416ab0415983c42c88ff3b266858462edebf8c91/bolt/src/main/java/com/slack/api/bolt/App.java

noisesmith18:07:16

@stopachka (class MessageEvent) should be just returns Class , you actually want MessageEvent which is the clojure equivalent of java's MessageEvent.class

noisesmith18:07:40

eg.

(ins)user=> (class Number)
java.lang.Class
(ins)user=> Number
java.lang.Number

noisesmith18:07:20

it's a good example of boilerplate elimination I think, what would Number be other than the class Number?

noisesmith18:07:09

I'm wondering now whether there's any value other than nil that returns something other than Class from (comp class class)

noisesmith18:07:28

probably nothing

noisesmith18:07:53

user=> (into #{} (map (comp class class))
              [nil 1 Number "" String Double/NaN 'foo])
#{nil java.lang.Class}

stopa19:07:21

ah, makes a loot of sense! Thanks @noisesmith, and clojure ftw!!

Maxime D20:07:22

Hi everyone. Brand new to Clojure and can't stop reading for the last two weeks. Interested to start a SaaS (learning) project with Clojure and was wondering if it is considered OK to use Vue or React without going the SPA road. A bit like adding some React or Vue components only in the html templates (using Semler). I guess it is possible but would like to hear about your experiences.

borkdude21:07:27

I don't see a problem with that. I've also made something for pages that need a tiny bit of CLJS, for quickly setting up something, without going through the hoops of setting up a CLJS project first. https://borkdude.github.io/scittle/

👍 2
👀 2
sova-soars-the-sora22:07:30

😮 clojurescript in the <script> tag!

👀 2
Maxime D02:07:05

Thanks. Not sure to see the plus side of using cljs here though. Will have to tinker a bit. Enough reading, coding time.

bigos22:07:10

big thanks to @seancorfield for his help 🙂

❤️ 2