0
# Exception Handling
1
2
Custom exception types and error handling patterns for JDBC session map operations.
3
4
## Capabilities
5
6
### JDBC Exception
7
8
Custom exception class for JDBC session map related errors.
9
10
```java { .api }
11
/**
12
* Exception thrown for JDBC session map operations
13
* Extends WebDriverException to integrate with Selenium's exception hierarchy
14
*/
15
public class JdbcException extends WebDriverException {
16
/**
17
* Creates a JDBC exception with no message
18
*/
19
public JdbcException();
20
21
/**
22
* Creates a JDBC exception with a message
23
* @param message The error message
24
*/
25
public JdbcException(String message);
26
27
/**
28
* Creates a JDBC exception wrapping another exception
29
* @param cause The underlying cause
30
*/
31
public JdbcException(Throwable cause);
32
33
/**
34
* Creates a JDBC exception with message and cause
35
* @param message The error message
36
* @param cause The underlying cause
37
*/
38
public JdbcException(String message, Throwable cause);
39
}
40
```
41
42
## Exception Scenarios
43
44
### Database Connection Errors
45
46
Thrown when database connections fail during session map operations.
47
48
**Usage Example:**
49
50
```java
51
import org.openqa.selenium.grid.sessionmap.jdbc.JdbcException;
52
53
try {
54
SessionMap sessionMap = JdbcBackedSessionMap.create(config);
55
sessionMap.add(session);
56
} catch (JdbcException e) {
57
System.err.println("Database operation failed: " + e.getMessage());
58
59
// Check if it's a connection issue
60
if (e.getCause() instanceof SQLException) {
61
SQLException sqlException = (SQLException) e.getCause();
62
System.err.println("SQL Error Code: " + sqlException.getErrorCode());
63
System.err.println("SQL State: " + sqlException.getSQLState());
64
}
65
}
66
```
67
68
### Configuration Errors
69
70
Thrown when required configuration is missing or invalid.
71
72
**Usage Example:**
73
74
```java
75
import org.openqa.selenium.grid.config.ConfigException;
76
77
try {
78
// Missing JDBC URL will trigger configuration error
79
Config config = new MapConfig(Map.of());
80
SessionMap sessionMap = JdbcBackedSessionMap.create(config);
81
} catch (ConfigException e) {
82
System.err.println("Configuration error: " + e.getMessage());
83
// Expected message: "Missing JDBC Url value. Add sessions option value --jdbc-url <url-value>"
84
} catch (JdbcException e) {
85
System.err.println("JDBC configuration error: " + e.getMessage());
86
}
87
```
88
89
### Session Not Found Errors
90
91
Standard Selenium exception for missing sessions.
92
93
**Usage Example:**
94
95
```java
96
import org.openqa.selenium.NoSuchSessionException;
97
98
try {
99
SessionId unknownId = new SessionId("non-existent-session");
100
Session session = sessionMap.get(unknownId);
101
} catch (NoSuchSessionException e) {
102
System.err.println("Session not found: " + e.getMessage());
103
// Handle missing session appropriately
104
// This is the standard Selenium exception, not JdbcException
105
}
106
```
107
108
## Error Handling Patterns
109
110
### Robust Session Operations
111
112
```java
113
public class RobustSessionManager {
114
private final SessionMap sessionMap;
115
private final Logger logger;
116
117
public boolean safeAddSession(Session session) {
118
try {
119
return sessionMap.add(session);
120
} catch (JdbcException e) {
121
logger.error("Failed to add session " + session.getId() + " to database", e);
122
return false;
123
}
124
}
125
126
public Optional<Session> safeGetSession(SessionId id) {
127
try {
128
return Optional.of(sessionMap.get(id));
129
} catch (NoSuchSessionException e) {
130
logger.debug("Session " + id + " not found in database");
131
return Optional.empty();
132
} catch (JdbcException e) {
133
logger.error("Database error retrieving session " + id, e);
134
return Optional.empty();
135
}
136
}
137
138
public void safeRemoveSession(SessionId id) {
139
try {
140
sessionMap.remove(id);
141
logger.debug("Session " + id + " removed from database");
142
} catch (JdbcException e) {
143
logger.error("Failed to remove session " + id + " from database", e);
144
// Continue - removal failures shouldn't break the flow
145
}
146
}
147
}
148
```
149
150
### Connection Health Monitoring
151
152
```java
153
public class SessionMapHealthChecker {
154
private final JdbcBackedSessionMap sessionMap;
155
156
public boolean isHealthy() {
157
try {
158
return sessionMap.isReady();
159
} catch (Exception e) {
160
logger.warn("Session map health check failed", e);
161
return false;
162
}
163
}
164
165
public void performHealthCheck() {
166
if (!isHealthy()) {
167
logger.error("Session map is not healthy - database connection issues");
168
// Trigger alerts, attempt reconnection, etc.
169
}
170
}
171
}
172
```
173
174
### Graceful Degradation
175
176
```java
177
public class FallbackSessionManager {
178
private final SessionMap primarySessionMap;
179
private final SessionMap fallbackSessionMap; // e.g., in-memory session map
180
181
public boolean add(Session session) {
182
try {
183
return primarySessionMap.add(session);
184
} catch (JdbcException e) {
185
logger.warn("Primary session map failed, using fallback", e);
186
return fallbackSessionMap.add(session);
187
}
188
}
189
190
public Session get(SessionId id) throws NoSuchSessionException {
191
try {
192
return primarySessionMap.get(id);
193
} catch (JdbcException e) {
194
logger.warn("Primary session map failed, trying fallback", e);
195
return fallbackSessionMap.get(id);
196
}
197
}
198
}
199
```
200
201
## Common Error Causes and Solutions
202
203
### Database Connection Issues
204
205
**Error**: `SQLException: Connection refused`
206
**Cause**: Database server is not running or not accessible
207
**Solution**: Verify database server status and network connectivity
208
209
```java
210
try {
211
Connection connection = options.getJdbcConnection();
212
} catch (SQLException e) {
213
if (e.getMessage().contains("Connection refused")) {
214
logger.error("Database server appears to be down: " + options.getJdbcUrl());
215
// Implement retry logic or fallback
216
}
217
}
218
```
219
220
### Missing Database Table
221
222
**Error**: `JdbcException` wrapping `SQLException: Table 'sessions_map' doesn't exist`
223
**Cause**: Database schema not initialized
224
**Solution**: Create the required table structure
225
226
```sql
227
CREATE TABLE sessions_map (
228
session_ids VARCHAR(50),
229
session_uri VARCHAR(30),
230
session_stereotype VARCHAR(300),
231
session_caps VARCHAR(300),
232
session_start VARCHAR(128)
233
);
234
```
235
236
### Authentication Failures
237
238
**Error**: `SQLException: Access denied for user`
239
**Cause**: Invalid database credentials
240
**Solution**: Verify JDBC username and password configuration
241
242
```java
243
// Check configuration
244
String user = options.getJdbcUser();
245
if (user == null || user.isEmpty()) {
246
logger.warn("JDBC user not configured - using default");
247
}
248
```
249
250
### Connection Pool Exhaustion
251
252
**Error**: `SQLException: Connection pool exhausted`
253
**Cause**: Too many concurrent connections
254
**Solution**: Configure connection pooling or implement connection reuse
255
256
```java
257
// Properly close connections
258
try (Connection connection = options.getJdbcConnection()) {
259
// Use connection
260
} // Automatically closed here
261
```
262
263
## Exception Integration with Grid Events
264
265
The JDBC session map integrates exceptions with Selenium Grid's event system and distributed tracing:
266
267
- **Trace Span Errors**: Database exceptions are recorded in distributed traces
268
- **Event Attributes**: Error details are added to Grid events
269
- **Monitoring Integration**: Exceptions can trigger monitoring alerts
270
- **Graceful Degradation**: Grid continues operating even with session map failures
271
272
This integration ensures that JDBC session map errors are properly observed and handled within the broader Grid infrastructure.