Issues subclassing Widget in clojure #316

Closed
opened 2026-01-11 23:12:32 +01:00 by williamahartman · 5 comments
williamahartman commented 2026-01-11 23:12:32 +01:00 (Migrated from github.com)

Hello,
I've been messing around with this library in clojure for a little bit now. I've really enjoyed it -- thanks for your work on this! It's been mostly smooth sailing so far, but I just ran into a bit of a roadblock. I'm not sure what level of clojure support you're aiming for, but I did notice https://github.com/jwharm/java-gi/issues/136 so I figured it would be worth asking about.

I'm having issues subclassing Widget related things in this project. I first noticed this after trying to override Widget.snapshot() to play around with GSK. I tried to use clojure's proxy to make my instance, but this caused a crash.

Here's a simplified example to illustrate what I've been seeing. You should be able to paste this into a clojure 1.12 REPL to test it out.

;; Load libs if running on the REPL (clojure >=1.12)
;; remove this and load deps with lien/deps.edn/whatever if not
(add-libs {`org.java-gi/gtk {:mvn/version "0.13.1"}
           `org.java-gi/adw {:mvn/version "0.13.1"}})

;; Example code
(ns java-gi-test.override-example
  (:import
   (org.gnome.adw Application ApplicationWindow HeaderBar)
   (org.gnome.gio ApplicationFlags)
   (org.gnome.gtk Box Button Orientation)))
(def app (doto (Application. "override" (into-array ApplicationFlags [ApplicationFlags/DEFAULT_FLAGS]))
           (.onActivate (reify org.gnome.gio.Application$ActivateCallback
                          (run [this]
                            (let [app-window (ApplicationWindow. app)]
                              (doto app-window
                                (.setTitle "Override Test")
                                (.setContent (doto (Box. Orientation/VERTICAL 0)
                                               (.append (HeaderBar.))
                                               (.append (doto (proxy [Button] []
                                                                (toString [] "I'm overriding something!"))
                                                          (.setLabel "Button!")))))
                                (.setDefaultSize 300 200)
                                (.present))))))))
(.run app nil)

Not much going on here, we're just making a bare-bones application and putting in an anonymous subclass of Button that overrides toString().

When running it, I'm seeing an error like this in stdout:

(java:376724): java-gi-CRITICAL **: 15:17:12.414: Cannot register type Button$ff19274a: java.lang.IllegalArgumentException: Unsupported property type: ParamSpecBoxed

If you swap the Button proxy out for a regular instance (i.e. replacing (proxy [Button] []...) with (Button.)), the window should open up fine.


A few additional notes:

  • The same thing happens you override a different method, or even nothing at all.
  • Doing the same thing, but with Widget instead of Button, I get a similar error, but the "Unsupported property type" is String [].
  • I also tried out the proxy function with Widget's parent classes. I notice any obvious problems creating them from GObjects or InitiallyUnowneds.
    ;; These run fine
    (-> (proxy [org.gnome.gobject.GObject] [] (toString [] "foo"))
        (.toString)
        (println))
    (-> (proxy [org.gnome.gobject.InitiallyUnowned] [] (toString [] "bar"))
        (.toString)
        (println))
    
  • Doing the same thing with an anonymous Button subclass and a .toString() override works fine in Java, so it seems safe to say that this has something to do with how clojure is creating the object.

I'm not quite sure what to make of all this, but hopefully some of it is useful information...

Using the gen-class function might be an option, but I haven't tested that out yet... I believe it would complicate using these libraries from the REPL, which wouldn't be ideal.

Hello, I've been messing around with this library in clojure for a little bit now. I've really enjoyed it -- thanks for your work on this! It's been mostly smooth sailing so far, but I just ran into a bit of a roadblock. I'm not sure what level of clojure support you're aiming for, but I did notice https://github.com/jwharm/java-gi/issues/136 so I figured it would be worth asking about. I'm having issues subclassing Widget related things in this project. I first noticed this after trying to override `Widget.snapshot()` to play around with GSK. I tried to use clojure's [`proxy`](https://clojuredocs.org/clojure.core/proxy) to make my instance, but this caused a crash. Here's a simplified example to illustrate what I've been seeing. You should be able to paste this into a clojure 1.12 REPL to test it out. ```clojure ;; Load libs if running on the REPL (clojure >=1.12) ;; remove this and load deps with lien/deps.edn/whatever if not (add-libs {`org.java-gi/gtk {:mvn/version "0.13.1"} `org.java-gi/adw {:mvn/version "0.13.1"}}) ;; Example code (ns java-gi-test.override-example (:import (org.gnome.adw Application ApplicationWindow HeaderBar) (org.gnome.gio ApplicationFlags) (org.gnome.gtk Box Button Orientation))) (def app (doto (Application. "override" (into-array ApplicationFlags [ApplicationFlags/DEFAULT_FLAGS])) (.onActivate (reify org.gnome.gio.Application$ActivateCallback (run [this] (let [app-window (ApplicationWindow. app)] (doto app-window (.setTitle "Override Test") (.setContent (doto (Box. Orientation/VERTICAL 0) (.append (HeaderBar.)) (.append (doto (proxy [Button] [] (toString [] "I'm overriding something!")) (.setLabel "Button!"))))) (.setDefaultSize 300 200) (.present)))))))) (.run app nil) ``` Not much going on here, we're just making a bare-bones application and putting in an anonymous subclass of `Button` that overrides `toString()`. When running it, I'm seeing an error like this in stdout: ``` (java:376724): java-gi-CRITICAL **: 15:17:12.414: Cannot register type Button$ff19274a: java.lang.IllegalArgumentException: Unsupported property type: ParamSpecBoxed ``` If you swap the `Button` proxy out for a regular instance (i.e. replacing `(proxy [Button] []...)` with `(Button.)`), the window should open up fine. --- A few additional notes: - The same thing happens you override a different method, or even nothing at all. - Doing the same thing, but with `Widget` instead of `Button`, I get a similar error, but the "Unsupported property type" is `String []`. - I also tried out the `proxy` function with `Widget`'s parent classes. I notice any obvious problems creating them from `GObject`s or `InitiallyUnowned`s. ```clojure ;; These run fine (-> (proxy [org.gnome.gobject.GObject] [] (toString [] "foo")) (.toString) (println)) (-> (proxy [org.gnome.gobject.InitiallyUnowned] [] (toString [] "bar")) (.toString) (println)) ``` - Doing the same thing with an anonymous `Button` subclass and a `.toString()` override works fine in Java, so it seems safe to say that this has something to do with how clojure is creating the object. I'm not quite sure what to make of all this, but hopefully some of it is useful information... Using the [`gen-class`](https://clojuredocs.org/clojure.core/gen-class) function might be an option, but I haven't tested that out yet... I believe it would complicate using these libraries from the REPL, which wouldn't be ideal.
jwharm commented 2026-01-12 21:53:03 +01:00 (Migrated from github.com)

Thanks for testing java-gi with clojure! I wanted to try this, but I don't have experience with Clojure. So your feedback is really helpful!

The error means that Java-GI found a get/set method pair and tried to register them as a GObject property. The error message clearly needs to be improved, and shouldn't be fatal. I will try to reproduce and fix the issue.

Thanks for testing java-gi with clojure! I wanted to try this, but I don't have experience with Clojure. So your feedback is really helpful! The error means that Java-GI found a get/set method pair and tried to register them as a GObject property. The error message clearly needs to be improved, and shouldn't be fatal. I will try to reproduce and fix the issue.
jwharm commented 2026-01-12 21:53:44 +01:00 (Migrated from github.com)

By the way, I'd appreciate any recommendations you have, to make the API more suitable for Clojure.

By the way, I'd appreciate any recommendations you have, to make the API more suitable for Clojure.
jwharm commented 2026-01-14 22:29:52 +01:00 (Migrated from github.com)

The error happens specifically with classes created by the proxy function in Clojure. I've reproduced the issue, and will fix it in the next release. Thanks again for reporting.

The error happens specifically with classes created by the `proxy` function in Clojure. I've reproduced the issue, and will fix it in the next release. Thanks again for reporting.
williamahartman commented 2026-01-15 16:15:20 +01:00 (Migrated from github.com)

Thank you for the fix! As for the overall experience with the API in clojure, I don't think I have any suggestions at the moment.

The only other thing I've run into in the examples so far that hasn't been smooth is the GtkTemplate stuff -- annotations are a bit of a pain in clojure/java interop. Honestly I don't think it's a big deal though, it doesn't seem to me like you'd get much out of templates with less OO style programs -- just using GTKBuilder directly feels simpler/cleaner here IMO.

Thank you for the fix! As for the overall experience with the API in clojure, I don't think I have any suggestions at the moment. The only other thing I've run into in the examples so far that hasn't been smooth is the GtkTemplate stuff -- annotations are a bit of a pain in clojure/java interop. Honestly I don't think it's a big deal though, it doesn't seem to me like you'd get much out of templates with less OO style programs -- just using GTKBuilder directly feels simpler/cleaner here IMO.
jwharm commented 2026-01-15 21:10:04 +01:00 (Migrated from github.com)

Ok, good to know. Thanks for the feedback!

Ok, good to know. Thanks for the feedback!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
java-gi/java-gi#316
No description provided.