or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

advanced-features.mdclass-object-access.mdclasspath-management.mdexception-handling.mdindex.mdinterface-implementation.mdjvm-management.mdtype-system.md

exception-handling.mddocs/

0

# Exception Handling

1

2

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.

3

4

## Capabilities

5

6

### Exception Base Classes

7

8

Base classes for Java exception handling in Python.

9

10

```python { .api }

11

class JException(Exception):

12

"""Base class for all Java exceptions.

13

14

Bridges Java exceptions to Python exception system.

15

All Java exceptions are subclasses of JException.

16

"""

17

18

def __init__(self, *args):

19

"""Initialize Java exception.

20

21

Args:

22

*args: Exception arguments

23

"""

24

25

def getMessage(self) -> str:

26

"""Get the Java exception message.

27

28

Returns:

29

str: Exception message from Java

30

"""

31

32

def getStackTrace(self):

33

"""Get Java stack trace.

34

35

Returns:

36

Java array of StackTraceElement objects

37

"""

38

39

def printStackTrace(self):

40

"""Print Java stack trace to standard error."""

41

42

def getCause(self):

43

"""Get the cause of this exception.

44

45

Returns:

46

JException or None: The underlying cause

47

"""

48

```

49

50

## Usage Examples

51

52

### Basic Exception Handling

53

54

```python

55

import jpype

56

57

jpype.startJVM()

58

59

try:

60

# This will cause a Java exception

61

string_obj = jpype.java.lang.String("test")

62

char = string_obj.charAt(10) # StringIndexOutOfBoundsException

63

except jpype.JException as e:

64

print(f"Caught Java exception: {e}")

65

print(f"Exception type: {type(e)}")

66

print(f"Message: {e.getMessage()}")

67

68

jpype.shutdownJVM()

69

```

70

71

### Catching Specific Java Exceptions

72

73

```python

74

import jpype

75

76

jpype.startJVM()

77

78

# Access Java exception classes

79

NumberFormatException = jpype.java.lang.NumberFormatException

80

IllegalArgumentException = jpype.java.lang.IllegalArgumentException

81

82

try:

83

# Parse invalid number

84

result = jpype.java.lang.Integer.parseInt("not_a_number")

85

except NumberFormatException as e:

86

print(f"Number format error: {e.getMessage()}")

87

except IllegalArgumentException as e:

88

print(f"Illegal argument: {e.getMessage()}")

89

except jpype.JException as e:

90

print(f"Other Java exception: {e}")

91

92

jpype.shutdownJVM()

93

```

94

95

### Exception Hierarchy

96

97

```python

98

import jpype

99

100

jpype.startJVM()

101

102

# Java exception hierarchy maps to Python

103

RuntimeException = jpype.java.lang.RuntimeException

104

NullPointerException = jpype.java.lang.NullPointerException

105

106

try:

107

# Create null pointer situation

108

null_string = None

109

# This would cause NullPointerException in Java context

110

raise jpype.java.lang.NullPointerException("Test null pointer")

111

except NullPointerException as e:

112

print("Caught NullPointerException")

113

except RuntimeException as e:

114

print("Caught RuntimeException (parent class)")

115

except jpype.JException as e:

116

print("Caught general Java exception")

117

118

jpype.shutdownJVM()

119

```

120

121

### Stack Trace Information

122

123

```python

124

import jpype

125

126

jpype.startJVM()

127

128

try:

129

# Create a method that throws an exception

130

Collections = jpype.java.util.Collections

131

empty_list = Collections.emptyList()

132

element = empty_list.get(0) # IndexOutOfBoundsException

133

except jpype.JException as e:

134

print(f"Exception message: {e.getMessage()}")

135

print(f"Exception class: {e.getClass().getName()}")

136

137

# Print Java stack trace

138

print("\nJava stack trace:")

139

e.printStackTrace()

140

141

# Get stack trace elements

142

stack_trace = e.getStackTrace()

143

print(f"\nStack trace has {len(stack_trace)} elements")

144

145

if len(stack_trace) > 0:

146

top_element = stack_trace[0]

147

print(f"Top frame: {top_element.getClassName()}.{top_element.getMethodName()}")

148

print(f"Line number: {top_element.getLineNumber()}")

149

150

jpype.shutdownJVM()

151

```

152

153

### Exception Chaining

154

155

```python

156

import jpype

157

158

jpype.startJVM()

159

160

try:

161

try:

162

# Cause initial exception

163

jpype.java.lang.Integer.parseInt("invalid")

164

except jpype.JException as e:

165

# Wrap in another exception

166

RuntimeException = jpype.java.lang.RuntimeException

167

wrapped = RuntimeException("Wrapped exception", e)

168

raise wrapped

169

except jpype.JException as e:

170

print(f"Outer exception: {e.getMessage()}")

171

172

# Get the original cause

173

cause = e.getCause()

174

if cause:

175

print(f"Original cause: {cause.getMessage()}")

176

print(f"Cause type: {cause.getClass().getName()}")

177

178

jpype.shutdownJVM()

179

```

180

181

### Throwing Java Exceptions from Python

182

183

```python

184

import jpype

185

from jpype import JImplements, JOverride

186

187

jpype.startJVM()

188

189

# Throw Java exceptions from Python code

190

def risky_operation(value):

191

if value < 0:

192

raise jpype.java.lang.IllegalArgumentException("Value cannot be negative")

193

if value == 0:

194

raise jpype.java.lang.ArithmeticException("Division by zero")

195

return 100 / value

196

197

try:

198

result1 = risky_operation(-5)

199

except jpype.java.lang.IllegalArgumentException as e:

200

print(f"Illegal argument: {e.getMessage()}")

201

202

try:

203

result2 = risky_operation(0)

204

except jpype.java.lang.ArithmeticException as e:

205

print(f"Arithmetic error: {e.getMessage()}")

206

207

# Normal case

208

result3 = risky_operation(10)

209

print(f"Normal result: {result3}")

210

211

jpype.shutdownJVM()

212

```

213

214

### Exception Handling in Interface Implementations

215

216

```python

217

import jpype

218

from jpype import JImplements, JOverride

219

220

jpype.startJVM()

221

222

Callable = jpype.java.util.concurrent.Callable

223

224

@JImplements(Callable)

225

class ExceptionThrowingTask:

226

def __init__(self, should_fail, error_type="runtime"):

227

self.should_fail = should_fail

228

self.error_type = error_type

229

230

@JOverride

231

def call(self):

232

if not self.should_fail:

233

return "Success"

234

235

# Throw different types of Java exceptions

236

if self.error_type == "runtime":

237

raise jpype.java.lang.RuntimeException("Task failed with runtime error")

238

elif self.error_type == "illegal_state":

239

raise jpype.java.lang.IllegalStateException("Invalid task state")

240

elif self.error_type == "io":

241

raise jpype.java.io.IOException("I/O operation failed")

242

else:

243

raise jpype.java.lang.Exception("Generic task failure")

244

245

# Use with ExecutorService

246

executor = jpype.java.util.concurrent.Executors.newSingleThreadExecutor()

247

248

# Test different exception types

249

test_cases = [

250

("runtime", jpype.java.lang.RuntimeException),

251

("illegal_state", jpype.java.lang.IllegalStateException),

252

("io", jpype.java.io.IOException),

253

("generic", jpype.java.lang.Exception)

254

]

255

256

for error_type, expected_exception in test_cases:

257

task = ExceptionThrowingTask(True, error_type)

258

future = executor.submit(task)

259

260

try:

261

result = future.get()

262

except jpype.java.util.concurrent.ExecutionException as e:

263

cause = e.getCause()

264

print(f"Task with {error_type} error failed: {cause.getMessage()}")

265

print(f"Exception type: {cause.getClass().getName()}")

266

267

executor.shutdown()

268

jpype.shutdownJVM()

269

```

270

271

### Exception Translation

272

273

```python

274

import jpype

275

276

jpype.startJVM()

277

278

def python_to_java_exception(python_func):

279

"""Decorator to translate Python exceptions to Java exceptions."""

280

def wrapper(*args, **kwargs):

281

try:

282

return python_func(*args, **kwargs)

283

except ValueError as e:

284

raise jpype.java.lang.IllegalArgumentException(str(e))

285

except FileNotFoundError as e:

286

raise jpype.java.io.FileNotFoundException(str(e))

287

except Exception as e:

288

raise jpype.java.lang.RuntimeException(f"Python error: {str(e)}")

289

return wrapper

290

291

@python_to_java_exception

292

def parse_positive_int(value_str):

293

"""Parse string to positive integer, raising appropriate exceptions."""

294

if not isinstance(value_str, str):

295

raise ValueError("Input must be a string")

296

297

try:

298

value = int(value_str)

299

except ValueError:

300

raise ValueError(f"'{value_str}' is not a valid integer")

301

302

if value <= 0:

303

raise ValueError("Value must be positive")

304

305

return value

306

307

# Test exception translation

308

test_values = ["123", "abc", "-5", 42]

309

310

for test_val in test_values:

311

try:

312

result = parse_positive_int(test_val)

313

print(f"Parsed {test_val} -> {result}")

314

except jpype.JException as e:

315

print(f"Java exception for {test_val}: {e.getClass().getSimpleName()} - {e.getMessage()}")

316

317

jpype.shutdownJVM()

318

```

319

320

### Custom Exception Classes

321

322

```python

323

import jpype

324

from jpype import JImplements

325

326

jpype.startJVM()

327

328

# Create custom Java exception by extending existing ones

329

@JImplements("java.lang.RuntimeException", deferred=True)

330

class CustomBusinessException:

331

def __init__(self, message, error_code=None):

332

super().__init__(message)

333

self.error_code = error_code

334

335

def getErrorCode(self):

336

return self.error_code

337

338

# Use custom exception

339

def business_operation(account_id):

340

if account_id < 0:

341

raise CustomBusinessException("Invalid account ID", "INVALID_ACCOUNT")

342

if account_id == 999:

343

raise CustomBusinessException("Account suspended", "ACCOUNT_SUSPENDED")

344

return f"Operation successful for account {account_id}"

345

346

# Test custom exception

347

try:

348

result = business_operation(-1)

349

except CustomBusinessException as e:

350

print(f"Business error: {e.getMessage()}")

351

print(f"Error code: {e.getErrorCode()}")

352

353

jpype.shutdownJVM()

354

```