Fork me on GitHub

Does anyone know something about particulars with running simple Swing apps on Linux? (clojure.inspector/inspect (range 10)) gives me a blank window/frame. I can manipulate the returned JFrame with things like (.setSize w 300 200) for expected results.


This also renders an empty window

(def f (new javax.swing.JFrame "My Frame"))
(.setSize f 600 400)
(def p (new javax.swing.JPanel))
(.setLayout p (new java.awt.FlowLayout))
(def l (new javax.swing.JLabel "Hello World"))
(.add p l)
#object[javax.swing.JLabel 0x74b15813 "javax.swing.JLabel[,0,0,0x0,invalid,alignmentX=0.0,alignmentY=0.0,border=,flags=8388608,maximumSize=,minimumSize=,preferredSize=,defaultIcon=,disabledIcon=,horizontalAlignment=LEADING,horizontalTextPosition=TRAILING,iconTextGap=4,labelFor=,text=Hello World,verticalAlignment=CENTER,verticalTextPosition=CENTER]"]
(.add f p)
#object[javax.swing.JPanel 0x3cface79 "javax.swing.JPanel[,0,0,0x0,invalid,layout=java.awt.FlowLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=9,maximumSize=,minimumSize=,preferredSize=]"]
(.setVisible f true)


While, if I do the same on my Mac, I get


FWIW I get the expected result on Ubuntu 20.04 with OpenJDK 11.0.11.


Thanks. I have:

$ uname -a
Linux ws-6b7740ce-c639-4431-8722-a09e2c8d242a 5.4.0-1046-gke #48-Ubuntu SMP Thu Jun 17 19:16:06 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
$ java -version
Picked up JAVA_TOOL_OPTIONS: -Xmx1879m
openjdk version "11.0.12" 2021-07-20 LTS
OpenJDK Runtime Environment Zulu11.50+19-CA (build 11.0.12+7-LTS)
OpenJDK 64-Bit Server VM Zulu11.50+19-CA (build 11.0.12+7-LTS, mixed mode)


A couple of potential causes are mentioned here: Also seems like using remote desktop can cause it - which could be fixed with altering its color depth..


Ah, I am doing this via VNC…


uname -a only tells the kernel version - lsb_release -a also has the distribution info. Just for future reference. :)


> The depth needs to be set to 24, but the place to do so will depend on the server app.


It was ages ago I used a Linux machine…

$ lsb_release -a
No LSB modules are available.
Distributor ID: Ubuntu
Description:    Ubuntu 20.04.2 LTS
Release:        20.04
Codename:       focal


I am not using GCJ, am I?


No, you're using OpenJDK.


Haha, thanks. Checking the VNC config now.


It might to have to do with color depth of both X and VNC, but I am not savvy enough to even check either…


What client and server do you use?


Not sure. It’s a bit opaque to me. But I think I have found a thread where I will be able to find out how to solve this: (Since this is on Gitpod)

👍 4

Indeed. -Dsun.java2d.xrender=false does the trick.


It’s novnc, btw.


Finally. Took me all too much time to figure this out:

👍 4

Please give it a spin, if you like:


Wow, that's amazing!


Haha, yeah, I still find it a bit hard to believe it is actually happening in the browser.


Although it's not the same, it still reminds me of a fun talk about WebAssembly where the speaker was speculating about running something like Firefox within Windows XP within Chrome Within Linux.


I can realate. I installed VS Code in this Gitpod X11 thing just to get that kind of trip. Also Firefox. Didn’t try to open the pirate-lang repo in that firefox instance. Maybe I should.


Web Assembly is pretty mind boggling actually. I wonder where that thing will go!


Ah, found it, in case you have 30 minutes on programming-related humor:

👀 2

Haha, that was great!

🙂 2

Ok, no idea why, but for some reason tarayo isn’t working for me anymore. It crashes right on :require within my namespace.

1. Caused by java.lang.ClassNotFoundException
What could be causing this? I went looking around and it might be because this javax.mail.Message is a java EE class. Is this true?
~ ❯ java --version
openjdk 16.0.2 2021-07-20
OpenJDK Runtime Environment Homebrew (build 16.0.2+0)
OpenJDK 64-Bit Server VM Homebrew (build 16.0.2+0, mixed mode, sharing)


Pretty sure you need this dependency to get that class nowadays:

com.sun.mail/javax.mail {:mvn/version "1.6.2"}


Ok, something bad must’ve happened.


So far I’ve had to install these two dependencies:

com.sun.activation/javax.activation {:mvn/version "1.2.0"}
        com.sun.mail/javax.mail {:mvn/version "1.6.2"}
Not sure what I’ve changed, but I keep getting errors when trying to use either tarayo or postal.
1. Unhandled java.util.ServiceConfigurationError
   jakarta.mail.Provider: com.sun.mail.imap.IMAPProvider not a subtype
What could I have done to screw up my dependencies this badly?


The project seems to use the Jakarta mail APIs which changed their package names in their 2.x.x release from javax.mail to jakarta.mail.


The weird thing is that I was working with this library yesterday and I had no problems.


Wait, I think deleting .cpcache might have fixed it.


Now I just have to figure out how to get a minimal smtp server going so I can send email to myself.


I can’t seem to figure out why the example from the readme doesn’t work:

(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
  (tarayo/send! conn {:from ""
                      :to ""
                      :subject "hello"
                      :body "world"}))
;; => {:result :success, :code 250, :message "250 OK\n"}
I get the following errors:
3. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling src/notifier/core.clj at (80:1)
   #:clojure.error{:phase :compile-syntax-check,
                   :line 80,
                   :column 1,

2. Caused by com.sun.mail.util.MailConnectException
   Couldn't connect to host, port: localhost, 25; timeout -1

1. Caused by
   Connection refused
Not sure how to make sense of this. Do I need an SMTP server? I’m pretty sure I was able to use localhost when postal was working (which strangely now isn’t).


Is there an SMTP server running on your machine and listening on port 25?


Definitely not.


So that’s the missing ingredient eh? Unless there was some built-in smtp server on my mac. Could that have been the case when it was working? I just found out about postfix and sendmail.


Aha! sudo postfix start was a pretty easy solution making use of built-in macOS cli tools. Now I just need it to actually send something instead of just queue it.

👍 2

I am curious to know if the sequence abstraction approach of Clojure can be viewed as ‘monadic’, in a way that it enables composition of functions (eg. 100 functions on 1 data structure VS 10 functions on 10 data structures). Or should it be viewed as just an interface abstraction that makes use of upcast method calls?


I can’t seem to figure out why the example from the readme doesn’t work:

(with-open [conn (tarayo/connect {:host "localhost" :port 25})]
  (tarayo/send! conn {:from ""
                      :to ""
                      :subject "hello"
                      :body "world"}))
;; => {:result :success, :code 250, :message "250 OK\n"}
I get the following errors:
3. Unhandled clojure.lang.Compiler$CompilerException
   Error compiling src/notifier/core.clj at (80:1)
   #:clojure.error{:phase :compile-syntax-check,
                   :line 80,
                   :column 1,

2. Caused by com.sun.mail.util.MailConnectException
   Couldn't connect to host, port: localhost, 25; timeout -1

1. Caused by
   Connection refused
Not sure how to make sense of this. Do I need an SMTP server? I’m pretty sure I was able to use localhost when postal was working (which strangely now isn’t).


Anyone have an example of how to debounce a function in clojure (sans cljs). I can't seem to find anything that doesn't assume a javascript runtime. I see some core.async channel examples but they seem to assume that you are debouncing input is another channel. (use case I have a file watcher that calls a function on modifications and I would like to debounce that call).


I believe the figwheel-main source has an example of this 🙂


This seems like a fairly legit approach:


The alternative I can think of is to keep an atom with a map of {:state :running|idle, :next-scheduled? true}. On every invocation you check the atom. If it’s running, set :next-scheduled? true. After the fn runs, it sets :running :idle, :next-scheduled? false , if :next-scheduled? was previously true it runs itself one more time.


Hmmm… On second thought, using a go-loop and a (chan 1) makes the most sense. Then you’re only allowed to queue 1 task while the fn is running.


You can ape that with atoms, but a bound queue makes a ton of sense.


Alright, I figured it out. Took a while before core.async clicked in my mind. Took a debounce channel in/out example and wrapped it to take in a function and return a function


I put together a silly example of a zero install desktop app dev environment with full Interactive Coding. Please give it a spin, anyone. It is pretty amazing what we can do in the browser these days. I think I’ll add a cljfx example to it next. Thanks, @p-himik, for unblocking me when I was stuck! gratitude gratitude ❤️ gratitude gratitude UPDATE: 1-minute video demo in the thread.

👍 2

Shared it with a friend. His response: "Is this year 3000 already?"

🚀 2

If you can add a link to already working file to edit it without write access, this could be great demo.


PS I don’t know how gitpod work


You can already do that! Just follow the link in the README, and it will allow you to edit anything.


@U0WL6FA77, click the link at step 1 under Usage and it will open in a workspace with write access. Yeah, like @p-himik said.


I can’t. I don’t have account in gitpod.


If you have a Github account, you just log in with that option.


I should probably update the README some. 😃


If you can make people to try this without making account in gitpod, then more people can be interested in. Just trying to help with uninvited advices 😉


For me it is blocker. I don’t want to create account there to try what it is.


You don't create an account there - you allow it to access your email through GitHub's OAuth. Or GitLab, or something else that GitPod supports. I imagine not having any form of authorization (what I think you mean) is a no-go for GitPod - imagine how bots could thrive otherwise.


> You don’t create an account there - you allow it to access your email through GitHub’s OAuth. Or GitLab, or something else that GitPod supports. This is what I am calling “create an account” 😉 > I imagine not having any form of authorization (what I think you mean) is a no-go for GitPod - imagine how bots could thrive otherwise. (edited) Sorry then. I don’t know how GitPod works.


Basically, they run your code for you, on their own infrastructure. Your browser serves just as an editor and a way to input/output data.

👍 2

Oh I see the issue now. I thought it is webrowser js script to edit files.


The in-browser editing/creating of an app is the whole point with the example repo.


Here’s a screen recording for people who don’t want to click the SIgn-up with Github button. 😃


nice, it really looks like VSC


Because it is. :D But in the browser.


The swing app to the right is displayed using VNC, The VS Code + Calva part to the left is really VS Code in the browser, with a cloud virtual Linux box with full root access backing it. That’s where the VNC server is running too.

👍 2

I know this is stupid, but, is there a way to gitpod without signing up/in?


That's exactly what kwladyka and I discussed above in this thread. :) Doesn't seem like it, and IMO wouldn't make sense for such a way to exist.


Oh, ha! 😄


Sorry, it's late and I am lazy 🙂


Personally I think a solution to that is captcha.


I hate captcha, but this is exactly what it is for.


I have never analyzed this, but there are services that let you pass captcha challenges at scale. As long as you can get more money out of something than you have to spend on captcha, it's not a viable solution. Unless you want to get into arms race with such services and people that use them.


So, we (myself and another dev) have got a bit of a conundrum. We're dealing with obfuscated java, and the tooling we're using to apply class name remappings seems to be tripping over how clojure :imports work. We're AOTing everything before we try to re-obfuscate, and the tool is picking up the actual references we're making to the obfuscated classes in the AOT'd code, but clojure's compiler is also emitting code which sets up the namespaces by passing strings to a class loader. Those strings, naturally, are being ignored by the tool and the final jar throws errors in production by trying to load the de-obfuscated names. Does anyone have suggestions for how we could deal with this? Is there a compiler flag, perhaps, that might help?


I think my suggestion would be "Don't do that!" -- why are y'all using a tool to rewrite Java class names in the first place? What mad, paranoid world are your bosses living in?


We're dealing with minecraft


And that requires obfuscated class names why?


Minecraft is distributed as an obfuscated jar.


So, if you want your code to link against stock minecraft you have to deal with its obfuscated names.


They talk about alternatives to trying to use AOT -- because of the obfuscator.


> The point is that I used Clojure to generate Java source code, on compile time (the type of metaprogramming you always have the option to use, no matter the platform or base language you are based on). > This is done by the script, which actually imports the de-obfuscated code and generates a Java file mapping all block, item and material names to their actual objects (the result cannot be published without breaking both Minecraft and MCP licenses, but reading the code you can get an idea of what the result looks like). Oh dear god...


(TL;DR: use a Java stub and have it call into Clojure directly via Clojure's Java API and avoid AOT)


Actually from that last bit what it sounds like is they used the name maps to generate a file that carries the translations into runtime.


We're actually at the point now where if we AOT then everything works as long as we use fully qualified class names everywhere.


There are a handful of Clojure projects out there modding Minecraft. Don't know if they've all gone down the same path but I'm sure they've all had to deal with working around the obfuscator in "entertaining" ways 🙂


Many of them are quite old, and the Minecraft API has changed significantly over the years. New versions of the obfuscation/deobfuscation tools have come out and all the mods I could find really try to avoid working with core Minecraft functionality


And basically all of them require hooking into a Java stub


(I had forgotten about that post until you mentioned the obfuscator but I remember being fascinated by it at the time -- OMG nine years ago!)


Hmm... their comments about how the obfuscator works don't line up with the workflow we've been using.


Because we can get it to work with AOT, and the high-level structure of the packages does seem to survive into the runtime. The trouble at this point really does just come down to how :import is implemented.


Like, the names of our packages aren't being rewritten- just the ones from minecraft's own package.