Scripting language support in Quarkus

100 views
Skip to first unread message

Eric Wittmann

unread,
Mar 26, 2025, 7:28:52 AM3/26/25
to Quarkus Development mailing list
I did some quick searching on this topic and didn't find anything. :)

Let's say I have a Quarkus based application and I want my users to be able to extend its functionality at runtime by providing one or more custom script in some scripting language (e.g. javascript or lua).  Nothing too complex - the script would essentially just be a function that takes some content and then returns either a boolean or something like a list of tuples.

Are there any Quarkus extensions that provide this sort of thing?

Emmanuel Bernard

unread,
Mar 26, 2025, 9:10:07 AM3/26/25
to quark...@googlegroups.com, Andrea Peruffo
Would you be interested in a model where this script / extension could run as WASM payload.
I’m adding Andrea here which explores WASM and Quarkus.

With WASM, you can then let your users write on any script language that can run as WASM. JavaScript chief amongst them.

--
You received this message because you are subscribed to the Google Groups "Quarkus Development mailing list" group.
To unsubscribe from this group and stop receiving emails from it, send an email to quarkus-dev...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/quarkus-dev/c04513d4-5b6b-44f7-a45c-3e79d324e127n%40googlegroups.com.

Georgios Andrianakis

unread,
Mar 26, 2025, 9:15:58 AM3/26/25
to quark...@googlegroups.com, Andrea Peruffo
You could use GraalVM's Truffle to run Python or JavaScript.



--

Georgios Andrianakis

Independent Contractor


Andrea Peruffo

unread,
Mar 26, 2025, 9:30:39 AM3/26/25
to Georgios Andrianakis, quark...@googlegroups.com
It's definitely possible to run Javascript, Python and other languages as wasm modules using either bare Chicory or Extism with the Java Chicory SDK.

I'm boarding to WASM IO right now but I'd be happy to learn more about the use case and help to come up with a solution!

bcl...@gmail.com

unread,
Mar 26, 2025, 9:33:05 AM3/26/25
to Quarkus Development mailing list
We do this using javassist to run Java code that can be changed at runtime. We are busy migrating from javassist to using runtime compilation. Here is a test case of ours that does this.
It uses some platform utils (UK.) but you should get the just of it:

```
    @Test
    @Order(9)
    @Transactional
    void dynamicCode() {
        try {

            String className = "Foo";
            String sourceCode = """
                    import org.slf4j.Logger;
                    import org.slf4j.LoggerFactory;
                    import com.ukheshe.arch.UK;
                    public class Foo {

                        private static final Logger log = LoggerFactory.getLogger(Foo.class);
                        private static final int x  = 10;

                        public int go(int a, int b) {
                            log.info("Hello");
                            return a + b + x;
                        }

                    }""";

            File tempDir = Files.createTempDirectory("dynamic_classes").toFile();
            tempDir.deleteOnExit();

            File sourceFile = new File(tempDir, className + ".java");
            Files.write(sourceFile.toPath(), sourceCode.getBytes());

            JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
            if (compiler == null) {
                throw new IllegalStateException("Cannot find Java compiler. Make sure you are using a JDK, not a JRE.");
            }

            boolean compilationResult;
            try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
                Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(sourceFile);
                compilationResult = compiler.getTask(null, fileManager, null, null, null, compilationUnits).call();
            }

            if (!compilationResult) {
                throw new RuntimeException("Compilation failed. Check the source code.");
            }

            URLClassLoader classLoader = URLClassLoader.newInstance(new URL[]{tempDir.toURI().toURL()}, Thread.currentThread().getContextClassLoader());
            Class<?> compiledClass = classLoader.loadClass(className);

            // Find the method and invoke it
            Method method = compiledClass.getDeclaredMethod("go", UK.class, int.class, int.class);
            
                try {
                    Object res = method.invoke(compiledClass.getDeclaredConstructor().newInstance(), 1, 2);
                    log.info("Result is [{}]", res);
                } catch (Throwable e) {
                    e.printStackTrace();
                }
            

            // Clean up
            sourceFile.delete();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
```


Eric Wittmann

unread,
Mar 26, 2025, 10:08:05 AM3/26/25
to Quarkus Development mailing list
Yeah Chicory was first on my list of options to explore.  +1

Eric Wittmann

unread,
Mar 26, 2025, 10:13:39 AM3/26/25
to Quarkus Development mailing list
Neat.  Looks interesting, thanks Georgios.

Eric Wittmann

unread,
Mar 26, 2025, 10:15:38 AM3/26/25
to Quarkus Development mailing list
Very cool - but I would worry about sandboxing issues with this approach.

Andrea Peruffo

unread,
Apr 23, 2025, 12:33:43 PM4/23/25
to Quarkus Development mailing list
For anyone following, I have been working with Eric and this effort is moving baby steps.

The decided direction is to use QuickJs in a secure sandbox.
Still completely experimental and immature, so any feedback is highly appreciated, but this the "generic part" that is shaping up:

https://github.com/andreaTP/quickjs4j

I know many projects that would benefit from this integration. This is a great opportunity to experiment and contribute early to its design!

Loïc MATHIEU

unread,
May 16, 2025, 6:06:29 AM5/16/25
to quark...@googlegroups.com
Hi,

First time I header about QuickJS.
I'm curious, why you didn't choose GraalVM Polyglott, it provides the same security mechanism (except for memory, you have to use isolate for that) and is well known and tested, and provides multiple language and not only JS.

Andrea Peruffo

unread,
May 16, 2025, 8:42:18 AM5/16/25
to Quarkus Development mailing list

Hi!
Regarding QuickJS, it’s used at scale by companies like Shopify (via Javy) to run untrusted user code securely within their infrastructure.

GraalJS doesn't offer the same level of security guarantees.
Since it's a Node.js replacement, it exposes the full Node API, allowing access to system resources like the file system and sockets.
In contrast, with a pure JavaScript engine like QuickJS, you explicitly expose only the functionality you want.
This gives the host environment (Java, in our case) full and fine-grained control over what JS code can do.

Additionally, to fully leverage the performance benefits of GraalJS, you typically need to run on GraalVM itself.
While it’s technically possible to use GraalJIT on other JVM distributions, it’s challenging.
In comparison, we compile QuickJS to pure, self-contained Java bytecode, which makes it extremely portable.

As always, it's about trade-offs and choosing the right tool for the job. :-)

Loïc MATHIEU

unread,
May 16, 2025, 11:35:37 AM5/16/25
to quark...@googlegroups.com
Interesting, thanks for your feedback

Reply all
Reply to author
Forward
0 new messages