CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-jpype1

A comprehensive Python-to-Java bridge enabling seamless integration between Python and Java virtual machines

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

exception-handling.mddocs/

Exception Handling

Handle Java exceptions within Python and bridge between Python and Java exception systems. This module provides seamless exception interoperability, allowing Python code to catch Java exceptions and Java code to handle Python exceptions.

Capabilities

Exception Base Classes

Base classes for Java exception handling in Python.

class JException(Exception):
    """Base class for all Java exceptions.
    
    Bridges Java exceptions to Python exception system.
    All Java exceptions are subclasses of JException.
    """
    
    def __init__(self, *args):
        """Initialize Java exception.
        
        Args:
            *args: Exception arguments
        """
    
    def getMessage(self) -> str:
        """Get the Java exception message.
        
        Returns:
            str: Exception message from Java
        """
    
    def getStackTrace(self):
        """Get Java stack trace.
        
        Returns:
            Java array of StackTraceElement objects
        """
    
    def printStackTrace(self):
        """Print Java stack trace to standard error."""
    
    def getCause(self):
        """Get the cause of this exception.
        
        Returns:
            JException or None: The underlying cause
        """

Usage Examples

Basic Exception Handling

import jpype

jpype.startJVM()

try:
    # This will cause a Java exception
    string_obj = jpype.java.lang.String("test")
    char = string_obj.charAt(10)  # StringIndexOutOfBoundsException
except jpype.JException as e:
    print(f"Caught Java exception: {e}")
    print(f"Exception type: {type(e)}")
    print(f"Message: {e.getMessage()}")

jpype.shutdownJVM()

Catching Specific Java Exceptions

import jpype

jpype.startJVM()

# Access Java exception classes
NumberFormatException = jpype.java.lang.NumberFormatException
IllegalArgumentException = jpype.java.lang.IllegalArgumentException

try:
    # Parse invalid number
    result = jpype.java.lang.Integer.parseInt("not_a_number")
except NumberFormatException as e:
    print(f"Number format error: {e.getMessage()}")
except IllegalArgumentException as e:
    print(f"Illegal argument: {e.getMessage()}")
except jpype.JException as e:
    print(f"Other Java exception: {e}")

jpype.shutdownJVM()

Exception Hierarchy

import jpype

jpype.startJVM()

# Java exception hierarchy maps to Python
RuntimeException = jpype.java.lang.RuntimeException
NullPointerException = jpype.java.lang.NullPointerException

try:
    # Create null pointer situation
    null_string = None
    # This would cause NullPointerException in Java context
    raise jpype.java.lang.NullPointerException("Test null pointer")
except NullPointerException as e:
    print("Caught NullPointerException")
except RuntimeException as e:
    print("Caught RuntimeException (parent class)")
except jpype.JException as e:
    print("Caught general Java exception")

jpype.shutdownJVM()

Stack Trace Information

import jpype

jpype.startJVM()

try:
    # Create a method that throws an exception
    Collections = jpype.java.util.Collections
    empty_list = Collections.emptyList()
    element = empty_list.get(0)  # IndexOutOfBoundsException
except jpype.JException as e:
    print(f"Exception message: {e.getMessage()}")
    print(f"Exception class: {e.getClass().getName()}")
    
    # Print Java stack trace
    print("\nJava stack trace:")
    e.printStackTrace()
    
    # Get stack trace elements
    stack_trace = e.getStackTrace()
    print(f"\nStack trace has {len(stack_trace)} elements")
    
    if len(stack_trace) > 0:
        top_element = stack_trace[0]
        print(f"Top frame: {top_element.getClassName()}.{top_element.getMethodName()}")
        print(f"Line number: {top_element.getLineNumber()}")

jpype.shutdownJVM()

Exception Chaining

import jpype

jpype.startJVM()

try:
    try:
        # Cause initial exception
        jpype.java.lang.Integer.parseInt("invalid")
    except jpype.JException as e:
        # Wrap in another exception
        RuntimeException = jpype.java.lang.RuntimeException
        wrapped = RuntimeException("Wrapped exception", e)
        raise wrapped
except jpype.JException as e:
    print(f"Outer exception: {e.getMessage()}")
    
    # Get the original cause
    cause = e.getCause()
    if cause:
        print(f"Original cause: {cause.getMessage()}")
        print(f"Cause type: {cause.getClass().getName()}")

jpype.shutdownJVM()

Throwing Java Exceptions from Python

import jpype
from jpype import JImplements, JOverride

jpype.startJVM()

# Throw Java exceptions from Python code
def risky_operation(value):
    if value < 0:
        raise jpype.java.lang.IllegalArgumentException("Value cannot be negative")
    if value == 0:
        raise jpype.java.lang.ArithmeticException("Division by zero")
    return 100 / value

try:
    result1 = risky_operation(-5)
except jpype.java.lang.IllegalArgumentException as e:
    print(f"Illegal argument: {e.getMessage()}")

try:
    result2 = risky_operation(0)
except jpype.java.lang.ArithmeticException as e:
    print(f"Arithmetic error: {e.getMessage()}")

# Normal case
result3 = risky_operation(10)
print(f"Normal result: {result3}")

jpype.shutdownJVM()

Exception Handling in Interface Implementations

import jpype
from jpype import JImplements, JOverride

jpype.startJVM()

Callable = jpype.java.util.concurrent.Callable

@JImplements(Callable)
class ExceptionThrowingTask:
    def __init__(self, should_fail, error_type="runtime"):
        self.should_fail = should_fail
        self.error_type = error_type
    
    @JOverride
    def call(self):
        if not self.should_fail:
            return "Success"
        
        # Throw different types of Java exceptions
        if self.error_type == "runtime":
            raise jpype.java.lang.RuntimeException("Task failed with runtime error")
        elif self.error_type == "illegal_state":
            raise jpype.java.lang.IllegalStateException("Invalid task state")
        elif self.error_type == "io":
            raise jpype.java.io.IOException("I/O operation failed")
        else:
            raise jpype.java.lang.Exception("Generic task failure")

# Use with ExecutorService
executor = jpype.java.util.concurrent.Executors.newSingleThreadExecutor()

# Test different exception types
test_cases = [
    ("runtime", jpype.java.lang.RuntimeException),
    ("illegal_state", jpype.java.lang.IllegalStateException),
    ("io", jpype.java.io.IOException),
    ("generic", jpype.java.lang.Exception)
]

for error_type, expected_exception in test_cases:
    task = ExceptionThrowingTask(True, error_type)
    future = executor.submit(task)
    
    try:
        result = future.get()
    except jpype.java.util.concurrent.ExecutionException as e:
        cause = e.getCause()
        print(f"Task with {error_type} error failed: {cause.getMessage()}")
        print(f"Exception type: {cause.getClass().getName()}")

executor.shutdown()
jpype.shutdownJVM()

Exception Translation

import jpype

jpype.startJVM()

def python_to_java_exception(python_func):
    """Decorator to translate Python exceptions to Java exceptions."""
    def wrapper(*args, **kwargs):
        try:
            return python_func(*args, **kwargs)
        except ValueError as e:
            raise jpype.java.lang.IllegalArgumentException(str(e))
        except FileNotFoundError as e:
            raise jpype.java.io.FileNotFoundException(str(e))
        except Exception as e:
            raise jpype.java.lang.RuntimeException(f"Python error: {str(e)}")
    return wrapper

@python_to_java_exception
def parse_positive_int(value_str):
    """Parse string to positive integer, raising appropriate exceptions."""
    if not isinstance(value_str, str):
        raise ValueError("Input must be a string")
    
    try:
        value = int(value_str)
    except ValueError:
        raise ValueError(f"'{value_str}' is not a valid integer")
    
    if value <= 0:
        raise ValueError("Value must be positive")
    
    return value

# Test exception translation
test_values = ["123", "abc", "-5", 42]

for test_val in test_values:
    try:
        result = parse_positive_int(test_val)
        print(f"Parsed {test_val} -> {result}")
    except jpype.JException as e:
        print(f"Java exception for {test_val}: {e.getClass().getSimpleName()} - {e.getMessage()}")

jpype.shutdownJVM()

Custom Exception Classes

import jpype
from jpype import JImplements

jpype.startJVM()

# Create custom Java exception by extending existing ones
@JImplements("java.lang.RuntimeException", deferred=True)
class CustomBusinessException:
    def __init__(self, message, error_code=None):
        super().__init__(message)
        self.error_code = error_code
    
    def getErrorCode(self):
        return self.error_code

# Use custom exception
def business_operation(account_id):
    if account_id < 0:
        raise CustomBusinessException("Invalid account ID", "INVALID_ACCOUNT")
    if account_id == 999:
        raise CustomBusinessException("Account suspended", "ACCOUNT_SUSPENDED")
    return f"Operation successful for account {account_id}"

# Test custom exception
try:
    result = business_operation(-1)
except CustomBusinessException as e:
    print(f"Business error: {e.getMessage()}")
    print(f"Error code: {e.getErrorCode()}")

jpype.shutdownJVM()

Install with Tessl CLI

npx tessl i tessl/pypi-jpype1

docs

advanced-features.md

class-object-access.md

classpath-management.md

exception-handling.md

index.md

interface-implementation.md

jvm-management.md

type-system.md

tile.json