[go: up one dir, main page]

DEV Community

Cover image for Code evaluation as a debugging tool
Anatolii Kozlov
Anatolii Kozlov

Posted on

Code evaluation as a debugging tool

In this article, "code evaluation" means - executing code expressions in runtime, like it happens when you pause the application in debug mode in IDEA and use the feature "Evaluate Expression". Let's consider how to implement "code evaluation" in a java application and then explore implemented solutions for using "code evaluation" in the java-spring application.

Use case example

For example, projects in your company use kubernetes. After implementing the new feature you must pass all pipelines to check how it works in the environment with all integrations with other services. And after deploying the service you see that some little things work not properly. And you want to make some little fixes for checking the hypothesis. However, to check it your must pass all pipelines including coding, review, building, deploying, etc.
If you have a tool like code evaluator in the project you can change any code or value of any variable (even the override code of the class method), check changes in runtime, and after checking changes start to fix the code and start pipeline things.
Notice, this tool must exist only in a non-production environment.

Implementation

As is known, groovy is fully compatible with java programming language. Groovy has a dynamic compilation feature, which we will use for "code evaluation" implementation. We will use groovy for "code evaluation", but it will work in any java application. How to add groovy to your java project you can find yourself easily. And now let's consider how to implement "code evaluation".

1) Let's create a groovy class and define a string variable that contains a class with a placeholder.

def EXPRESSION_CLASS_TEMPLATE = """
package dev.toliyansky.eval.service
class ExpressionClass implements java.util.function.Supplier<Object> {
    def get() {
        %s
    }
}
"""
Enter fullscreen mode Exit fullscreen mode

package must be with the same package where this code will call.

2) Let's compile and load a class from the first paragraph.
For instance, you can place the code below in the REST controller, it will allow getting a text for evaluation expression from the request body.

def finalClassCode = String.format(EXPRESSION_CLASS_TEMPLATE, code)
def supplier = groovyClassLoader.parseClass(finalClassCode)
                                .getDeclaredConstructor()
                                .newInstance() as Supplier<Object>
def result = supplier.get()
Enter fullscreen mode Exit fullscreen mode

On the first line, we replace %s with code that will be dynamically compiled and executed in runtime.

On the second line, we compile and instantiate the class from the first paragraph. Notice that instantiated class casted to the Supplier for the ability to call the method with text that you want to evaluate. Supplier<Object> is ideal for this purpose because it doesn't have parameters and has a return statement.

Implemented solution

If you don't want to mess around with implementing dynamic compilation and plugging up groovy into your project then you can use implemented spring boot starter with implemented "code evaluation" feature: evaluator-spring-boot-starter
After adding this starter dependency to your project you can evaluate code through http://host:port/eval with UI.
You can evaluate any text by sending HTTP requests. If you are interested in this project check readme on GitHub.

UI Screenshots

Example with dynamically overriding code of method in runtime. It can be any bean in your application, such us controllers or services.
dynamically overriding
Also as a bonus, this solution provides the possibility to execute Bash, Cmd, or PowerShell commands. It allows debug not only your application but even checking or changing some environments where your application started.
shell

Top comments (0)