Is it possible to write complex code (like instantiating an object and use the stream API) in string then parse it using something like spring language expression? Basically what I'm trying to do is to write code from the client side in string format then find a way to parse it and execute it on the backend side. From a business use case what I want to do is write some code to out put something and simply store it in a column field named "result".
Someone replied to me before and said it's doable but I had to abandon the chat
If you abandon Java you can do this with something you can sandbox in the jvm, like possibly nashorn or my pref. - SCI.
String expressionStr = """
(let [customer-1 (Customer. "Mike" 9)
-2 (Customer. "Ted" 20)
customer. [customer-1 customer-2]]
customers(->> customers
(filter (fn [customer] (= "Mike" (.getName customer))))
(first)))
"""
Then evaluate that in SCI.
https://github.com/borkdude/sci
= Clojure.read("sci.core", "eval-string");
IFn eval = (Customer) eval.invoke(expressionStr); Customer customer
and to give it sandboxed access to your classes, probably do this
= Clojure.read("clojure.core", "symbol");
IFn symbol = Clojure.read("clojure.core", "keyword");
IFn keyword = Clojure.read("sci.core", "eval-string");
IFn eval = (Customer) eval.invoke(
Customer customer ,
expressionStrMap.of(keyword.invoke("classes"), Map.of(symbol.invoke("Customer"), Customer.class))
);
Full example if you have clojure and sci included in your project
import clojure.java.api.Clojure;
import clojure.lang.IFn;
import java.util.Map;
public final class SciTest {
private SciTest() {}
private static final IFn REQUIRE;
private static final IFn SYMBOL;
private static final IFn KEYWORD;
private static final IFn EVAL_STRING;
static {
= Clojure.var("clojure.core", "require");
REQUIRE = Clojure.var("clojure.core", "symbol");
SYMBOL = Clojure.var("clojure.core", "keyword");
KEYWORD
.invoke(Clojure.read("sci.core"));
REQUIRE= Clojure.var("sci.core", "eval-string");
EVAL_STRING }
public record Thing(int x) {}
public static void main(String[] args) {
System.out.println(EVAL_STRING.invoke(
"""
(Thing. 10)
""",
Map.of(
.invoke("classes"),
KEYWORDMap.of(
.invoke("Thing"), Thing.class
SYMBOL)
)
));
}
}
Will take a look, thanks!
Curious what the actual requirement here is though. Since this isn't exactly super duper safe to do even with the sandboxing. They can still OOM your machine or whatever.
Requirement isn't fully clear but basically when creating a new entity record, there's a "result" field where the end user wants to write some code or formula based on other fields of the entity, ex: result = id + title + getUniqueRandNubr()
Yeah this might be a better use for a little dsl. You can make a tiny lang with antlr pretty easily. This is more general purpose, you can basically write any code.