Web apps with Mux + Plot + Interact do not interact any more

I was considering a simple example of a plot whose underlying model parameters are given by the output of a slider.
While it was working “before”, now the slider doesn’t seems to have effect any more on the plot and I got the error " nested task error: MethodError: no method matching isopen(::HTTP.WebSockets.WebSocket)".

This is a basic example from a 2019 forum post:

using Interact, Plots, Mux
mp = @manipulate throttle=.05 for λ=0:.1:5, μ=0:.1:5
    xs = range(0.0, 1.0, length = 100)
    Plots.plot(xs, x -> λ*x^2 + μ)
end
ui = dom"div"(mp)
WebIO.webio_serve(page("/", req -> ui), 8002)

A slighly more complex example, that I am sure it was working some time ago is instead:

using Interact,Plots,Mux
function myModel(p1,p2)
    xrange = collect(-50:+50)
    model = p1.*xrange .+ p2.* (xrange) .^2
    return model
end
function createLayout()
  p1s = slider(-50:50, label = "Par#1 (linear term):", value = 1)
  p2s = slider(-5:0.1:5, label = "Par#2 (quad term):", value = 1)
  mOutput = Interact.@map myModel(&p1s,&p2s)
  plt = Interact.@map plot(collect(-50:50),&mOutput, label="Model output")
  wdg = Widget(["p1" => p1s, "p2" => p2s], output = mOutput)
  @layout! wdg hbox(plt, vbox(:p1, :p2))
end
function serveLayout(destinationPort)
    try
      WebIO.webio_serve(page("/", req -> createLayout()), destinationPort)
    catch e
      if isa(e, IOError)
        # sleep and then try again
        sleep(0.1)
        serveLayout(destinationPort)
      else
        throw(e)
      end
    end
end
serveLayout(8001)

How do you do basic slider-control-a-plot web page in 2024? I have tried to look at the Genie documentation but there is a huge set of web related terminology/concepts there, including HTML tags, that I would like to avoid (while still coding the page)

Have you tried WGLMakie?

Not really, because I actually consider the “plot” a detail here. Sorry I realize I put Plot is in the title…

I am looking for a way to show how can I have some parametrized model, some widget to expose the parameters to a web user, a way to run the model in the back end with such parameters and a way to expose the new output to the user… the simplest thing is a plot, so I am using this in the example, but the output could be a table or could be a file to download…

(for context, I am updating a 2019 book where I was using Plots+Mux+Interact)

Please click through the link to see how WGLMakie uses Bonito.jl to do what you would like.

Someone probably needs to find a working Manifest.toml file for the example you are trying to run.

1 Like

Thank you I’ll give it a try… I feel it is an issue with either Mux or Interact. There is a similar discussion here

I was able to get this to work by downgrading Mux.jl to v0.7.6 and HTTP.jl to v0.9.17.

Something seems to have been lost as HTTP.jl upgraded to version 1.0.

(interact_plot_mux) pkg> st
Status `~/julia/discourse/interact_plot_mux/Project.toml`
⌅ [cd3eb016] HTTP v0.9.17
  [c601a237] Interact v0.10.5
⌃ [a975b10e] Mux v0.7.6
  [91a5bcdd] Plots v1.40.5
Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated`
Output of `]st -m`
(interact_plot_mux) pkg> st -m
Status `~/julia/discourse/interact_plot_mux/Manifest.toml`
  [bf4720bc] AssetRegistry v0.1.0
  [70588ee8] CSSUtil v0.1.1
  [35d6a980] ColorSchemes v3.26.0
  [3da002f7] ColorTypes v0.11.5
  [c3611d14] ColorVectorSpace v0.10.0
  [5ae59095] Colors v0.12.11
  [34da2185] Compat v4.16.0
  [d38c429a] Contour v0.6.3
  [9a962f9c] DataAPI v1.16.0
  [864edb3b] DataStructures v0.18.20
  [8bb1440f] DelimitedFiles v1.9.1
  [ffbed154] DocStringExtensions v0.9.3
  [c87230d0] FFMPEG v0.4.1
  [53c48c17] FixedPointNumbers v0.8.5
  [1fa38f19] Format v1.3.7
  [de31a74c] FunctionalCollections v0.5.0
  [28b8d3ca] GR v0.73.7
  [42e2da0e] Grisu v1.0.2
⌅ [cd3eb016] HTTP v0.9.17
  [9fb69e20] Hiccup v0.2.2
  [83e8ac13] IniFile v0.5.1
  [c601a237] Interact v0.10.5
  [d3863d7c] InteractBase v0.10.10
  [92d709cd] IrrationalConstants v0.2.2
  [1019f520] JLFzf v0.1.7
  [692b3bcd] JLLWrappers v1.5.0
  [97c1335a] JSExpr v0.5.4
  [682c06a0] JSON v0.21.4
  [bcebb21b] Knockout v0.2.6
  [b964fa9f] LaTeXStrings v1.3.1
  [23fbe1c1] Latexify v0.16.5
  [2ab3a3ac] LogExpFunctions v0.3.28
  [1914dd2f] MacroTools v0.5.13
  [739be429] MbedTLS v1.1.9
  [442fdcdd] Measures v0.3.2
  [e1d29d7a] Missings v1.2.0
⌃ [a975b10e] Mux v0.7.6
  [77ba4419] NaNMath v1.0.2
  [510215fc] Observables v0.5.5
  [bac558e1] OrderedCollections v1.6.3
  [69de0a69] Parsers v2.8.1
  [fa939f87] Pidfile v1.3.0
  [b98c9c47] Pipe v1.3.0
  [ccf2f8ad] PlotThemes v3.2.0
  [995b91a9] PlotUtils v1.4.1
  [91a5bcdd] Plots v1.40.5
  [aea7be01] PrecompileTools v1.2.1
  [21216c6a] Preferences v1.4.3
  [3cdcf5f2] RecipesBase v1.3.4
  [01d81517] RecipesPipeline v0.6.12
  [189a3867] Reexport v1.2.2
  [05181044] RelocatableFolders v1.0.1
  [ae029012] Requires v1.3.0
  [6c6a2e73] Scratch v1.2.1
  [992d4aef] Showoff v1.0.3
  [a2af1166] SortingAlgorithms v1.2.1
  [82ae8749] StatsAPI v1.7.0
  [2913bbd2] StatsBase v0.34.3
  [62fd8b95] TensorCore v0.1.1
  [5c2747f8] URIs v1.5.1
  [1cfade01] UnicodeFun v0.4.1
  [1986cc42] Unitful v1.21.0
  [45397f5d] UnitfulLatexify v1.6.4
  [41fe7b60] Unzip v0.2.0
  [0f1e0344] WebIO v0.8.21
⌃ [104b5d7c] WebSockets v1.5.9
  [cc8bc4a8] Widgets v0.6.6
  [6e34b625] Bzip2_jll v1.0.8+1
  [83423d85] Cairo_jll v1.18.0+2
  [ee1fde0b] Dbus_jll v1.14.10+0
  [2702e6a9] EpollShim_jll v0.0.20230411+0
  [2e619515] Expat_jll v2.6.2+0
⌅ [b22a6f82] FFMPEG_jll v4.4.4+1
  [a3f928ae] Fontconfig_jll v2.13.96+0
  [d7e528f0] FreeType2_jll v2.13.2+0
  [559328eb] FriBidi_jll v1.0.14+0
  [0656b61e] GLFW_jll v3.4.0+1
  [d2c73de3] GR_jll v0.73.7+0
  [78b55507] Gettext_jll v0.21.0+0
  [7746bdde] Glib_jll v2.80.2+0
  [3b182d85] Graphite2_jll v1.3.14+0
  [2e76f6c2] HarfBuzz_jll v2.8.1+1
  [aacddb02] JpegTurbo_jll v3.0.3+0
  [c1c5ebd0] LAME_jll v3.100.2+0
⌅ [88015f11] LERC_jll v3.0.0+1
  [1d63c593] LLVMOpenMP_jll v17.0.6+0
  [dd4b983a] LZO_jll v2.10.2+0
⌅ [e9f186c6] Libffi_jll v3.2.2+1
  [d4300ac3] Libgcrypt_jll v1.8.11+0
  [7e76a0d4] Libglvnd_jll v1.6.0+0
  [7add5ba3] Libgpg_error_jll v1.49.0+0
  [94ce4f54] Libiconv_jll v1.17.0+0
  [4b2f31a3] Libmount_jll v2.40.1+0
⌅ [89763e89] Libtiff_jll v4.5.1+1
  [38a345b3] Libuuid_jll v2.40.1+0
  [e7412a2a] Ogg_jll v1.3.5+1
  [458c3c95] OpenSSL_jll v3.0.14+0
  [91d4177d] Opus_jll v1.3.2+0
  [36c8627f] Pango_jll v1.52.2+0
  [30392449] Pixman_jll v0.43.4+0
  [c0090381] Qt6Base_jll v6.7.1+1
  [629bc702] Qt6Declarative_jll v6.7.1+2
  [ce943373] Qt6ShaderTools_jll v6.7.1+1
  [e99dba38] Qt6Wayland_jll v6.7.1+1
  [a44049a8] Vulkan_Loader_jll v1.3.243+0
  [a2964d1f] Wayland_jll v1.21.0+1
  [2381bf8a] Wayland_protocols_jll v1.31.0+0
  [02c8fc9c] XML2_jll v2.13.1+0
  [aed1982a] XSLT_jll v1.1.41+0
  [ffd25f8a] XZ_jll v5.4.6+0
  [f67eecfb] Xorg_libICE_jll v1.1.1+0
  [c834827a] Xorg_libSM_jll v1.2.4+0
  [4f6342f7] Xorg_libX11_jll v1.8.6+0
  [0c0b7dd1] Xorg_libXau_jll v1.0.11+0
  [935fb764] Xorg_libXcursor_jll v1.2.0+4
  [a3789734] Xorg_libXdmcp_jll v1.1.4+0
  [1082639a] Xorg_libXext_jll v1.3.6+0
  [d091e8ba] Xorg_libXfixes_jll v5.0.3+4
  [a51aa0fd] Xorg_libXi_jll v1.7.10+4
  [d1454406] Xorg_libXinerama_jll v1.1.4+4
  [ec84b674] Xorg_libXrandr_jll v1.5.2+4
  [ea2f1a96] Xorg_libXrender_jll v0.9.11+0
  [14d82f49] Xorg_libpthread_stubs_jll v0.1.1+0
  [c7cfdc94] Xorg_libxcb_jll v1.17.0+0
  [cc61e674] Xorg_libxkbfile_jll v1.1.2+0
  [e920d4aa] Xorg_xcb_util_cursor_jll v0.1.4+0
  [12413925] Xorg_xcb_util_image_jll v0.4.0+1
  [2def613f] Xorg_xcb_util_jll v0.4.0+1
  [975044d2] Xorg_xcb_util_keysyms_jll v0.4.0+1
  [0d47668e] Xorg_xcb_util_renderutil_jll v0.3.9+1
  [c22f9ab0] Xorg_xcb_util_wm_jll v0.4.1+1
  [35661453] Xorg_xkbcomp_jll v1.4.6+0
  [33bec58e] Xorg_xkeyboard_config_jll v2.39.0+0
  [c5fb5394] Xorg_xtrans_jll v1.5.0+0
  [3161d3a3] Zstd_jll v1.5.6+0
  [35ca27e7] eudev_jll v3.2.9+0
⌅ [214eeab7] fzf_jll v0.43.0+0
  [1a1c6b14] gperf_jll v3.1.1+0
  [a4ae2306] libaom_jll v3.9.0+0
  [0ac62f75] libass_jll v0.15.1+0
  [1183f4f0] libdecor_jll v0.2.2+0
  [2db6ffa8] libevdev_jll v1.11.0+0
  [f638f0a6] libfdk_aac_jll v2.0.2+0
  [36db933b] libinput_jll v1.18.0+0
  [b53b4c65] libpng_jll v1.6.43+1
  [f27f6e37] libvorbis_jll v1.3.7+2
  [009596ad] mtdev_jll v1.1.6+0
  [1270edf5] x264_jll v2021.5.5+0
  [dfaa095f] x265_jll v3.5.0+0
  [d8fb68d0] xkbcommon_jll v1.4.1+1
  [0dad84c5] ArgTools v1.1.1
  [56f22d72] Artifacts
  [2a0f44e3] Base64
  [ade2ca70] Dates
  [8ba89e20] Distributed
  [f43a241f] Downloads v1.6.0
  [7b1f6079] FileWatching
  [b77e0a4c] InteractiveUtils
  [b27032c2] LibCURL v0.6.4
  [76f85450] LibGit2
  [8f399da3] Libdl
  [37e2e46d] LinearAlgebra
  [56ddb016] Logging
  [d6f4376e] Markdown
  [a63ad114] Mmap
  [ca575930] NetworkOptions v1.2.0
  [44cfe95a] Pkg v1.10.0
  [de0858da] Printf
  [3fa0cd96] REPL
  [9a3f8284] Random
  [ea8e919c] SHA v0.7.0
  [9e88b42a] Serialization
  [6462fe0b] Sockets
  [2f01184e] SparseArrays v1.10.0
  [10745b16] Statistics v1.10.0
  [fa267f1f] TOML v1.0.3
  [a4e569a6] Tar v1.10.0
  [8dfed614] Test
  [cf7118a7] UUIDs
  [4ec0a83e] Unicode
  [e66e0078] CompilerSupportLibraries_jll v1.1.1+0
  [deac9b47] LibCURL_jll v8.4.0+0
  [e37daf67] LibGit2_jll v1.6.4+0
  [29816b5a] LibSSH2_jll v1.11.0+1
  [c8ffd9c3] MbedTLS_jll v2.28.2+1
  [14a3606d] MozillaCACerts_jll v2023.1.10
  [4536629a] OpenBLAS_jll v0.3.23+4
  [05823500] OpenLibm_jll v0.8.1+2
  [efcefdf7] PCRE2_jll v10.42.0+1
  [bea87d4a] SuiteSparse_jll v7.2.1+1
  [83775a58] Zlib_jll v1.2.13+1
  [8e850b90] libblastrampoline_jll v5.8.0+1
  [8e850ede] nghttp2_jll v1.52.0+1
  [3f19e933] p7zip_jll v17.4.0+2
Info Packages marked with ⌃ and ⌅ have new versions available. Those with ⌃ may be upgradable, but those with ⌅ are restricted by compatibility constraints from upgrading. To see why use `status --outdated -m`

Manifest.toml (38.3 KB)

1 Like

I’m working on a fix here:

You can try the fix by grabbing my branch:

using Pkg
Pkg.add("https://github.com/mkitti/WebIO.jl.git#mkitti-fix-mux-integration")

If this goes stale, please feel free to follow up by pinging me here.

Have you tried the Stipple package in the Genie Framework? It’s all in Julia with no HTML or JavaScript. You can see a minimum example in the docs here

Check out the app gallery too for more examples

While I confirm that using the Manifest you provided the example works, using the latest version with your patch I have the same error:

using Pkg
cd(@__DIR__)
Pkg.activate(".")
Pkg.add(["Interact","Mux","Plots"])
Pkg.add(url="https://github.com/mkitti/WebIO.jl.git#mkitti-fix-mux-integration")
using Interact, Plots, Mux
mp = @manipulate throttle=.05 for λ=0:.1:5, μ=0:.1:5
    xs = range(0.0, 1.0, length = 100)
    Plots.plot(xs, x -> λ*x^2 + μ)
end
ui = dom"div"(mp)
WebIO.webio_serve(page("/", req -> ui), 8003)

Status:

(testWebIO) pkg> status
Status `~/CloudFiles/beta-lorraine-sync/Documents/JuliaApressBook/2024Update/bookSrc/julia_source_code/ch13/testWebIO/Project.toml`
  [c601a237] Interact v0.10.5
  [a975b10e] Mux v1.0.2
  [91a5bcdd] Plots v1.40.5
  [0f1e0344] WebIO v0.8.21 `https://github.com/mkitti/WebIO.jl.git#mkitti-fix-mux-integration#master`
Error: ```text [ Info: Listening on: 0.0.0.0:8003, thread id: 1

(testWebIO) pkg> add Error handling websocket connection:
TaskFailedException
Stacktrace:
[1] wait(t::Task)
@ Base ./task.jl:370
[2] create_socket(req::Dict{Any, Any})
@ WebIO ~/.julia/packages/WebIO/8Xm9p/src/providers/mux.jl:47
[3] #5
@ ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:17 [inlined]
[4] (::Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#29#30"{Vector{SubString{String}}}, typeof(WebIO.create_socket)}, Mux.var"#1#2"{typeof(Mux.wclose), Mux.var"#1#2"{Mux.var"#19#20"{Mux.var"#23#24"{Symbol, Int64}}, Mux.var"#21#22"{String}}}})(x::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:10
[5] splitquery(app::Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#29#30"{Vector{SubString{String}}}, typeof(WebIO.create_socket)}, Mux.var"#1#2"{typeof(Mux.wclose), Mux.var"#1#2"{Mux.var"#19#20"{Mux.var"#23#24"{Symbol, Int64}}, Mux.var"#21#22"{String}}}}, req::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/u4vsZ/src/basics.jl:31
[6] #1
@ ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:10 [inlined]
[7] wcatch(app::Mux.var"#1#2"{typeof(Mux.splitquery), Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#29#30"{Vector{SubString{String}}}, typeof(WebIO.create_socket)}, Mux.var"#1#2"{typeof(Mux.wclose), Mux.var"#1#2"{Mux.var"#19#20"{Mux.var"#23#24"{Symbol, Int64}}, Mux.var"#21#22"{String}}}}}, req::Dict{Any, Any})
@ Mux ~/.julia/packages/Mux/u4vsZ/src/websockets_integration.jl:11
[8] #1
@ ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:10 [inlined]
[9] todict
@ ~/.julia/packages/Mux/u4vsZ/src/basics.jl:25 [inlined]
[10] #3 (repeats 2 times)
@ ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:14 [inlined]
[11] (::Mux.var"#1#2"{Mux.var"#3#4"{Mux.var"#3#4"{typeof(Mux.todict), typeof(Mux.wcatch)}, typeof(Mux.splitquery)}, Mux.var"#1#2"{Mux.var"#5#6"{Mux.var"#29#30"{Vector{SubString{String}}}, typeof(WebIO.create_socket)}, Mux.var"#1#2"{typeof(Mux.wclose), Mux.var"#1#2"{Mux.var"#19#20"{Mux.var"#23#24"{Symbol, Int64}}, Mux.var"#21#22"{String}}}}})(x::HTTP.WebSockets.WebSocket)
@ Mux ~/.julia/packages/Mux/u4vsZ/src/Mux.jl:10
[12] (::Mux.var"#9#10"{Mux.App})(sock::HTTP.WebSockets.WebSocket)
@ Mux ~/.julia/packages/Mux/u4vsZ/src/server.jl:48
[13] upgrade(f::Mux.var"#9#10"{Mux.App}, http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}}; suppress_close_error::Bool, maxframesize::Int64, maxfragmentation::Int64, nagle::Bool, quickack::Bool, kw::@Kwargs{})
@ HTTP.WebSockets ~/.julia/packages/HTTP/sJD5V/src/WebSockets.jl:456
[14] upgrade
@ ~/.julia/packages/HTTP/sJD5V/src/WebSockets.jl:425 [inlined]
[15] (::Mux.var"#14#15"{Mux.App, Mux.App})(http::HTTP.Streams.Stream{HTTP.Messages.Request, HTTP.Connections.Connection{Sockets.TCPSocket}})
@ Mux ~/.julia/packages/Mux/u4vsZ/src/server.jl:81
[16] #invokelatest#2
@ ./essentials.jl:1043 [inlined]
[17] invokelatest
@ ./essentials.jl:1040 [inlined]
[18] handle_connection(f::Function, c::HTTP.Connections.Connection{Sockets.TCPSocket}, listener::HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, readtimeout::Int64, access_log::Nothing)
@ HTTP.Servers ~/.julia/packages/HTTP/sJD5V/src/Servers.jl:469
[19] (::HTTP.Servers.var"#16#17"{Mux.var"#14#15"{Mux.App, Mux.App}, HTTP.Servers.Listener{Nothing, Sockets.TCPServer}, Set{HTTP.Connections.Connection}, Int64, Nothing, ReentrantLock, Base.Semaphore, HTTP.Connections.Connection{Sockets.TCPSocket}})()
@ HTTP.Servers ~/.julia/packages/HTTP/sJD5V/src/Servers.jl:401

nested task error: MethodError: no method matching isopen(::HTTP.WebSockets.WebSocket)
The function `isopen` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  isopen(::WebIO.WebSockConnection)
   @ WebIO ~/.julia/packages/WebIO/8Xm9p/src/providers/mux.jl:54
  isopen(::SimpleBufferStream.BufferStream)
   @ SimpleBufferStream ~/.julia/packages/SimpleBufferStream/N1BA4/src/BufferStream.jl:30
  isopen(::FileWatching.FDWatcher)
   @ FileWatching ~/lib/julia-1.11.0-rc2/share/julia/stdlib/v1.11/FileWatching/src/FileWatching.jl:393
  ...

Stacktrace:
 [1] (::WebIO.var"#98#99"{WebIO.WebSockConnection, HTTP.WebSockets.WebSocket})()
   @ WebIO ~/.julia/packages/WebIO/8Xm9p/src/providers/mux.jl:40
</details>

Yes I did, but I personally find it too complicated. The documentation seems to be for another target of users, not for data analysis people that want to just expose their models to the web.

I did web development long time ago, and I still find the documentation too difficult, with terminology and concepts that are very far away…

2 Likes

You might need to clear your compile cache for WebIO.jl. It should be under ~/.julia/compiled/v1.10/WebIO.

done, deleted everything but still got the error arghh…
thank you any how, I will just delete that section… lots of problems also in Genie, really not as simple in Julia as in R Shiny unfortunately :-//

2 Likes

To be fair, R Shiny is incredible and really found a great stack that is robust. I have also been searching for such a stack in julia but not found it. I use Oxygen.jl for my APIs which works well. It’s not as mature as FastAPI but I get to stay in Julia. :slightly_smiling_face: I saw a few cool html generators that could be combined with Oxygen and I think it was HTMX.jl but I might be mistaken. See the following discussion What can we learn from FastHTML? - #7 by tp2750

1 Like

The approach you are taking is not the start of the art for how to do this in Julia.

The leading methods are Pluto.jl and WGLMakie.jl:

  1. Interactivity
  2. Beautiful Makie

I would first delete the compiled code for WebIO, and then run the Pkg commands in this order. Adding by branch has to come first, otherwise the older code will get compiled and cached.

As I mentioned this is using some older technology.

using Pkg
cd(@__DIR__)
Pkg.activate(".")
Pkg.add(url="https://github.com/mkitti/WebIO.jl.git#mkitti-fix-mux-integration")
Pkg.add(["Interact","Mux","Plots"])
using Interact, Plots, Mux
mp = @manipulate throttle=.05 for λ=0:.1:5, μ=0:.1:5
    xs = range(0.0, 1.0, length = 100)
    Plots.plot(xs, x -> λ*x^2 + μ)
end
ui = dom"div"(mp)
WebIO.webio_serve(page("/", req -> ui), 8003)

I see. Genie was indeed first designed as a full stack web framework, but we’re making an effort to make it easier to create simple apps to interact with your models/data. I’d also suggest that you check out Genie Builder, which lets you create the UI part without having to write any code.

2 Likes