CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-python--jython-standalone

Jython is an implementation of Python 2.7 written in 100% Pure Java, providing seamless integration with the Java platform and ecosystem.

Pending
Overview
Eval results
Files

jsr223-scripting.mddocs/

JSR-223 Scripting

Jython provides full support for the Java Scripting API (JSR-223), allowing seamless integration with existing Java applications that use the standard scripting framework.

Script Engine Factory

The factory class for creating Jython script engines.

public class PyScriptEngineFactory implements ScriptEngineFactory {
    // Engine metadata
    public String getEngineName();          // Returns "jython"
    public String getEngineVersion();       // Returns Jython version
    public String getLanguageName();        // Returns "python"
    public String getLanguageVersion();     // Returns Python version "2.7"
    public List<String> getExtensions();    // Returns ["py"]
    public List<String> getMimeTypes();     // Returns Python MIME types
    public List<String> getNames();         // Returns ["python", "jython"]
    
    // Script engine creation
    public ScriptEngine getScriptEngine();
    
    // Utility methods
    public String getMethodCallSyntax(String obj, String m, String... args);
    public String getOutputStatement(String toDisplay);
    public String getProgram(String... statements);
    public Object getParameter(String key);
}

Script Engine

The main JSR-223 script engine implementation for Jython.

public class PyScriptEngine extends AbstractScriptEngine 
                           implements Compilable, Invocable, AutoCloseable {
    
    // Script execution
    public Object eval(String script) throws ScriptException;
    public Object eval(String script, ScriptContext context) throws ScriptException;
    public Object eval(Reader reader) throws ScriptException;
    public Object eval(Reader reader, ScriptContext context) throws ScriptException;
    
    // Compilation support (Compilable interface)
    public CompiledScript compile(String script) throws ScriptException;
    public CompiledScript compile(Reader reader) throws ScriptException;
    
    // Function invocation (Invocable interface)
    public Object invokeFunction(String name, Object... args) 
        throws ScriptException, NoSuchMethodException;
    public Object invokeMethod(Object thiz, String name, Object... args) 
        throws ScriptException, NoSuchMethodException;
    public <T> T getInterface(Class<T> clasz);
    public <T> T getInterface(Object thiz, Class<T> clasz);
    
    // Engine management
    public Bindings createBindings();
    public ScriptEngineFactory getFactory();
    public void close();
}

Script Engine Scope

Provides variable scoping and bindings for the JSR-223 engine.

public final class PyScriptEngineScope extends PyObject implements Bindings {
    // Bindings interface implementation
    public Object put(String key, Object value);
    public Object get(Object key);
    public Object remove(Object key);
    public boolean containsKey(Object key);
    public boolean containsValue(Object value);
    public Set<String> keySet();
    public Collection<Object> values();
    public Set<Entry<String, Object>> entrySet();
    public int size();
    public boolean isEmpty();
    public void clear();
    public void putAll(Map<? extends String, ? extends Object> toMerge);
}

Basic Usage Examples

Simple Script Execution

import javax.script.*;

public class JSR223Example {
    public static void main(String[] args) throws ScriptException {
        // Get script engine manager
        ScriptEngineManager manager = new ScriptEngineManager();
        
        // Get Jython engine by name
        ScriptEngine engine = manager.getEngineByName("python");
        
        // Execute simple script
        engine.eval("print('Hello from Jython!')");
        
        // Set variables
        engine.put("name", "World");
        engine.put("number", 42);
        
        // Use variables in script
        Object result = engine.eval("greeting = f'Hello, {name}! The answer is {number}'");
        Object greeting = engine.get("greeting");
        
        System.out.println("Result: " + greeting);
    }
}

Using Script Context

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");

// Create custom context
ScriptContext context = new SimpleScriptContext();
Bindings bindings = engine.createBindings();
bindings.put("x", 10);
bindings.put("y", 20);
context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);

// Execute with custom context
Object result = engine.eval("result = x + y", context);
Object sum = context.getAttribute("result");

System.out.println("Sum: " + sum); // Sum: 30

Compilation Support

Pre-compile scripts for better performance when executing multiple times.

Compiling Scripts

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");

// Check if engine supports compilation
if (engine instanceof Compilable) {
    Compilable compilable = (Compilable) engine;
    
    // Compile script
    CompiledScript compiled = compilable.compile("""
        def calculate(x, y):
            return x * y + (x - y)
        
        result = calculate(a, b)
        """);
    
    // Execute compiled script multiple times
    engine.put("a", 5);
    engine.put("b", 3);
    compiled.eval();
    System.out.println("Result 1: " + engine.get("result")); // 17
    
    engine.put("a", 10);
    engine.put("b", 4);
    compiled.eval();
    System.out.println("Result 2: " + engine.get("result")); // 46
}

CompiledScript Usage

CompiledScript compiled = compilable.compile("x ** 2 + y ** 2");

// Execute with different contexts
ScriptContext ctx1 = new SimpleScriptContext();
ctx1.setAttribute("x", 3, ScriptContext.ENGINE_SCOPE);
ctx1.setAttribute("y", 4, ScriptContext.ENGINE_SCOPE);
Object result1 = compiled.eval(ctx1);
System.out.println("3² + 4² = " + result1); // 25

ScriptContext ctx2 = new SimpleScriptContext();
ctx2.setAttribute("x", 5, ScriptContext.ENGINE_SCOPE);
ctx2.setAttribute("y", 12, ScriptContext.ENGINE_SCOPE);
Object result2 = compiled.eval(ctx2);
System.out.println("5² + 12² = " + result2); // 169

Function Invocation

Call Python functions directly from Java using the Invocable interface.

Basic Function Invocation

ScriptEngineManager manager = new ScriptEngineManager();
ScriptEngine engine = manager.getEngineByName("python");

// Define Python functions
engine.eval("""
    def add(x, y):
        return x + y
    
    def greet(name, title=""):
        if title:
            return f"Hello, {title} {name}!"
        else:
            return f"Hello, {name}!"
    
    class Calculator:
        def __init__(self, factor=1):
            self.factor = factor
        
        def multiply(self, x):
            return x * self.factor
    
    calc = Calculator(10)
    """);

// Invoke functions
if (engine instanceof Invocable) {
    Invocable invocable = (Invocable) engine;
    
    // Call simple function
    Object sum = invocable.invokeFunction("add", 5, 3);
    System.out.println("Sum: " + sum); // 8
    
    // Call function with keyword-like behavior (positional only in JSR-223)
    Object greeting1 = invocable.invokeFunction("greet", "Alice");
    Object greeting2 = invocable.invokeFunction("greet", "Bob", "Dr.");
    System.out.println(greeting1); // Hello, Alice!
    System.out.println(greeting2); // Hello, Dr. Bob!
    
    // Call method on object
    Object calcInstance = engine.get("calc");
    Object product = invocable.invokeMethod(calcInstance, "multiply", 7);
    System.out.println("Product: " + product); // 70
}

Interface Implementation

Create Java interfaces implemented by Python objects.

// Define Java interface
interface MathOperations {
    double calculate(double x, double y);
    String getOperationName();
}

// Define Python implementation
engine.eval("""
    class Adder:
        def calculate(self, x, y):
            return x + y
        
        def getOperationName(self):
            return "Addition"
    
    adder = Adder()
    """);

// Get interface implementation
MathOperations mathOps = invocable.getInterface(
    engine.get("adder"), 
    MathOperations.class
);

// Use as Java interface
double result = mathOps.calculate(10.5, 5.3);
String opName = mathOps.getOperationName();

System.out.println(opName + ": " + result); // Addition: 15.8

Advanced Usage Patterns

Custom Bindings

ScriptEngine engine = manager.getEngineByName("python");

// Create custom bindings with initial values
Bindings customBindings = new SimpleBindings();
customBindings.put("PI", Math.PI);
customBindings.put("E", Math.E);
customBindings.put("logger", LoggerFactory.getLogger("jython"));

// Set as engine scope
engine.setBindings(customBindings, ScriptContext.ENGINE_SCOPE);

engine.eval("""
    import math
    
    # Use Java objects in Python
    logger.info("Calculating circle area")
    
    radius = 5
    area = PI * radius * radius
    
    logger.info(f"Area of circle with radius {radius} is {area}")
    """);

Multi-Engine Coordination

ScriptEngineManager manager = new ScriptEngineManager();

// Create multiple engines
ScriptEngine engine1 = manager.getEngineByName("python");
ScriptEngine engine2 = manager.getEngineByName("python");

// Shared data object
Map<String, Object> sharedData = new ConcurrentHashMap<>();

// Setup engines with shared data
engine1.put("shared", sharedData);
engine2.put("shared", sharedData);

// Engine 1 sets data
engine1.eval("shared['message'] = 'Hello from Engine 1'");

// Engine 2 reads data
engine2.eval("print('Engine 2 received:', shared.get('message'))");

Error Handling

ScriptEngine engine = manager.getEngineByName("python");

try {
    engine.eval("undefined_variable + 1");
} catch (ScriptException e) {
    System.out.println("Script error: " + e.getMessage());
    System.out.println("Line number: " + e.getLineNumber());
    System.out.println("Column number: " + e.getColumnNumber());
    System.out.println("File name: " + e.getFileName());
    
    // Get the underlying Python exception
    Throwable cause = e.getCause();
    if (cause instanceof PyException) {
        PyException pyEx = (PyException) cause;
        System.out.println("Python exception type: " + pyEx.type);
        System.out.println("Python exception value: " + pyEx.value);
    }
}

Configuration and Properties

Engine Parameters

ScriptEngineFactory factory = new PyScriptEngineFactory();

// Get engine information
System.out.println("Engine Name: " + factory.getEngineName());
System.out.println("Engine Version: " + factory.getEngineVersion());
System.out.println("Language Name: " + factory.getLanguageName());
System.out.println("Language Version: " + factory.getLanguageVersion());
System.out.println("Extensions: " + factory.getExtensions());
System.out.println("MIME Types: " + factory.getMimeTypes());
System.out.println("Names: " + factory.getNames());

// Check specific parameters
Object threadingType = factory.getParameter(ScriptEngine.THREADING);
System.out.println("Threading: " + threadingType);

Script Context Management

ScriptEngine engine = manager.getEngineByName("python");

// Get default context
ScriptContext defaultContext = engine.getContext();

// Create isolated context for sensitive operations
ScriptContext isolatedContext = new SimpleScriptContext();
Bindings isolatedBindings = engine.createBindings();
isolatedBindings.put("secure_data", "sensitive information");
isolatedContext.setBindings(isolatedBindings, ScriptContext.ENGINE_SCOPE);

// Execute in isolated context
engine.eval("result = len(secure_data)", isolatedContext);
Object result = isolatedContext.getAttribute("result");

// Original context remains unaffected
Object originalData = defaultContext.getAttribute("secure_data");
System.out.println("Original context has secure_data: " + (originalData != null));

Performance Optimization

Script Compilation Best Practices

// Cache compiled scripts for reuse
Map<String, CompiledScript> scriptCache = new ConcurrentHashMap<>();

public Object executeScript(String script, Map<String, Object> variables) 
    throws ScriptException {
    
    // Get or compile script
    CompiledScript compiled = scriptCache.computeIfAbsent(script, s -> {
        try {
            return ((Compilable) engine).compile(s);
        } catch (ScriptException e) {
            throw new RuntimeException(e);
        }
    });
    
    // Create context with variables
    ScriptContext context = new SimpleScriptContext();
    Bindings bindings = engine.createBindings();
    bindings.putAll(variables);
    context.setBindings(bindings, ScriptContext.ENGINE_SCOPE);
    
    // Execute compiled script
    return compiled.eval(context);
}

Resource Management

// Use try-with-resources for automatic cleanup
try (AutoCloseable engine = (AutoCloseable) manager.getEngineByName("python")) {
    engine.eval("print('Script executed')");
    // Engine automatically closed
}

// Manual resource management
ScriptEngine engine = manager.getEngineByName("python");
try {
    engine.eval("print('Script executed')");
} finally {
    if (engine instanceof AutoCloseable) {
        ((AutoCloseable) engine).close();
    }
}

Integration with Java Frameworks

Spring Framework Integration

@Component
public class JythonScriptService {
    private final ScriptEngine engine;
    
    public JythonScriptService() {
        ScriptEngineManager manager = new ScriptEngineManager();
        this.engine = manager.getEngineByName("python");
    }
    
    @PostConstruct
    public void initialize() throws ScriptException {
        // Load common Python modules
        engine.eval("""
            import json
            import datetime
            import re
            
            def format_data(data):
                return json.dumps(data, indent=2)
            """);
    }
    
    public String processData(Map<String, Object> data) throws ScriptException {
        engine.put("input_data", data);
        return (String) engine.eval("format_data(input_data)");
    }
}

Servlet Integration

@WebServlet("/python-script")
public class PythonScriptServlet extends HttpServlet {
    private ScriptEngine engine;
    
    @Override
    public void init() throws ServletException {
        ScriptEngineManager manager = new ScriptEngineManager();
        engine = manager.getEngineByName("python");
    }
    
    @Override
    protected void doPost(HttpServletRequest request, HttpServletResponse response) 
        throws ServletException, IOException {
        
        String script = request.getParameter("script");
        
        try {
            engine.put("request_params", request.getParameterMap());
            Object result = engine.eval(script);
            
            response.setContentType("application/json");
            response.getWriter().write(result.toString());
        } catch (ScriptException e) {
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            response.getWriter().write("Script error: " + e.getMessage());
        }
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-python--jython-standalone

docs

configuration.md

exception-handling.md

index.md

java-integration.md

jsr223-scripting.md

python-execution.md

python-objects.md

tile.json