0
# Session Management
1
2
HTTP session integration with injection support and flash message capabilities for web applications requiring session state. Provides seamless access to HttpSession objects and flash messaging functionality in JAX-RS resource methods.
3
4
## Capabilities
5
6
### Session Annotation
7
8
Annotation for injecting HttpSession instances into JAX-RS resource method parameters and fields.
9
10
```java { .api }
11
/**
12
* Injects HttpSession into resource method parameters or fields
13
* Supports configuration for session creation behavior
14
*/
15
@Documented
16
@Retention(RetentionPolicy.RUNTIME)
17
@Target({ElementType.PARAMETER, ElementType.FIELD})
18
public @interface Session {
19
20
/**
21
* Whether to avoid creating a new session if one doesn't exist
22
* @return true to avoid creating new sessions, false to create if needed
23
*/
24
boolean doNotCreate() default false;
25
}
26
```
27
28
**Usage Examples:**
29
30
```java
31
import io.dropwizard.jersey.sessions.Session;
32
import jakarta.servlet.http.HttpSession;
33
import jakarta.ws.rs.*;
34
35
@Path("/users")
36
public class UserResource {
37
38
@POST
39
@Path("/login")
40
public Response login(@FormParam("username") String username,
41
@FormParam("password") String password,
42
@Session HttpSession session) {
43
if (authService.authenticate(username, password)) {
44
session.setAttribute("userId", username);
45
session.setAttribute("loginTime", System.currentTimeMillis());
46
return Response.ok().build();
47
}
48
return Response.status(401).build();
49
}
50
51
@GET
52
@Path("/profile")
53
public UserProfile getProfile(@Session HttpSession session) {
54
String userId = (String) session.getAttribute("userId");
55
if (userId == null) {
56
throw new WebApplicationException(401);
57
}
58
return userService.getProfile(userId);
59
}
60
61
@POST
62
@Path("/logout")
63
public Response logout(@Session HttpSession session) {
64
session.invalidate();
65
return Response.ok().build();
66
}
67
68
// Don't create session if it doesn't exist
69
@GET
70
@Path("/check")
71
public Response checkSession(@Session(doNotCreate = true) HttpSession session) {
72
if (session == null) {
73
return Response.status(401).entity("No active session").build();
74
}
75
return Response.ok().entity("Session active").build();
76
}
77
}
78
```
79
80
### Flash Messages
81
82
Flash message support for storing temporary messages in the session that are automatically removed after being accessed.
83
84
```java { .api }
85
/**
86
* Flash message container for session-based temporary messages
87
* Messages are automatically removed after being accessed
88
* @param <T> type of flash message content
89
*/
90
public class Flash<T> {
91
92
/**
93
* Gets the flash message content, removing it from session
94
* @return Optional containing the flash message, or empty if none exists
95
*/
96
public Optional<T> get();
97
98
/**
99
* Sets a flash message in the session
100
* @param value the message content to store
101
*/
102
public void set(T value);
103
}
104
```
105
106
**Usage Examples:**
107
108
```java
109
import io.dropwizard.jersey.sessions.Flash;
110
import io.dropwizard.jersey.sessions.Session;
111
import jakarta.servlet.http.HttpSession;
112
import jakarta.ws.rs.*;
113
import java.util.Optional;
114
115
@Path("/account")
116
public class AccountResource {
117
118
@POST
119
@Path("/update")
120
public Response updateAccount(@Valid UpdateAccountRequest request,
121
@Session HttpSession session,
122
@Session Flash<String> flash) {
123
try {
124
accountService.update(getCurrentUserId(session), request);
125
flash.set("Account updated successfully!");
126
return Response.seeOther(URI.create("/account")).build();
127
} catch (ValidationException e) {
128
flash.set("Error: " + e.getMessage());
129
return Response.seeOther(URI.create("/account/edit")).build();
130
}
131
}
132
133
@GET
134
@Path("/")
135
public AccountView getAccount(@Session HttpSession session,
136
@Session Flash<String> flash) {
137
String userId = getCurrentUserId(session);
138
Account account = accountService.getAccount(userId);
139
140
// Check for flash message
141
Optional<String> message = flash.get(); // Automatically removes from session
142
143
return new AccountView(account, message.orElse(null));
144
}
145
146
@GET
147
@Path("/notifications")
148
public Response getNotifications(@Session Flash<List<String>> notifications) {
149
Optional<List<String>> messages = notifications.get();
150
if (messages.isPresent()) {
151
return Response.ok(messages.get()).build();
152
}
153
return Response.ok(Collections.emptyList()).build();
154
}
155
}
156
```
157
158
### Session Factories
159
160
Factory classes that provide HttpSession and Flash instances for dependency injection.
161
162
```java { .api }
163
/**
164
* Factory for creating HttpSession instances
165
* Used by Jersey's dependency injection system
166
*/
167
public class HttpSessionFactory implements Factory<HttpSession> {
168
169
/** Provides the current HttpSession instance */
170
public HttpSession provide();
171
172
/** Disposes of the HttpSession (no-op) */
173
public void dispose(HttpSession instance);
174
}
175
176
/**
177
* Factory for creating Flash instances
178
* Used by Jersey's dependency injection system
179
*/
180
public class FlashFactory implements Factory<Flash<?>> {
181
182
/** Provides a Flash instance for the current session */
183
public Flash<?> provide();
184
185
/** Disposes of the Flash instance (no-op) */
186
public void dispose(Flash<?> instance);
187
}
188
189
/**
190
* Provider that registers session-related factories with Jersey
191
*/
192
public class SessionFactoryProvider {
193
194
/**
195
* Binder that registers HttpSessionFactory and FlashFactory
196
* Used internally by DropwizardResourceConfig
197
*/
198
public static class Binder extends AbstractBinder {
199
protected void configure();
200
}
201
}
202
```
203
204
## Session Configuration
205
206
### Basic Session Setup
207
208
Sessions are automatically configured when using DropwizardResourceConfig, but you can customize session behavior:
209
210
```java
211
import io.dropwizard.jersey.DropwizardResourceConfig;
212
import io.dropwizard.jersey.sessions.SessionFactoryProvider;
213
214
public class MyApplication extends Application<MyConfiguration> {
215
216
@Override
217
public void run(MyConfiguration config, Environment environment) {
218
// Sessions are automatically registered with DropwizardResourceConfig
219
JerseyEnvironment jersey = environment.jersey();
220
221
// Register resources that use sessions
222
jersey.register(UserSessionResource.class);
223
224
// Configure session timeout in Jetty (if needed)
225
environment.servlets()
226
.setSessionHandler(new SessionHandler())
227
.getSessionManager()
228
.setMaxInactiveInterval(3600); // 1 hour
229
}
230
}
231
```
232
233
### Session Lifecycle Management
234
235
```java
236
@Path("/session")
237
public class SessionResource {
238
239
@POST
240
@Path("/create")
241
public Response createSession(@Session HttpSession session) {
242
// Session is automatically created if it doesn't exist
243
session.setAttribute("created", Instant.now());
244
return Response.ok().build();
245
}
246
247
@GET
248
@Path("/info")
249
public SessionInfo getSessionInfo(@Session HttpSession session) {
250
return SessionInfo.builder()
251
.id(session.getId())
252
.creationTime(Instant.ofEpochMilli(session.getCreationTime()))
253
.lastAccessTime(Instant.ofEpochMilli(session.getLastAccessedTime()))
254
.maxInactiveInterval(session.getMaxInactiveInterval())
255
.isNew(session.isNew())
256
.build();
257
}
258
259
@DELETE
260
@Path("/")
261
public Response invalidateSession(@Session HttpSession session) {
262
session.invalidate();
263
return Response.noContent().build();
264
}
265
}
266
```
267
268
### Flash Message Patterns
269
270
```java
271
@Path("/wizard")
272
public class WizardResource {
273
274
@POST
275
@Path("/step1")
276
public Response processStep1(@Valid Step1Data data,
277
@Session HttpSession session,
278
@Session Flash<WizardState> wizardFlash) {
279
// Store intermediate data in flash
280
WizardState state = new WizardState();
281
state.setStep1Data(data);
282
wizardFlash.set(state);
283
284
return Response.seeOther(URI.create("/wizard/step2")).build();
285
}
286
287
@GET
288
@Path("/step2")
289
public Step2View showStep2(@Session Flash<WizardState> wizardFlash) {
290
Optional<WizardState> state = wizardFlash.get();
291
if (!state.isPresent()) {
292
// No flash data, redirect to start
293
throw new WebApplicationException(
294
Response.seeOther(URI.create("/wizard/step1")).build()
295
);
296
}
297
298
return new Step2View(state.get().getStep1Data());
299
}
300
301
@POST
302
@Path("/step2")
303
public Response processStep2(@Valid Step2Data data,
304
@Session Flash<WizardState> wizardFlash) {
305
Optional<WizardState> state = wizardFlash.get();
306
if (!state.isPresent()) {
307
return Response.seeOther(URI.create("/wizard/step1")).build();
308
}
309
310
// Complete wizard with both steps
311
WizardResult result = wizardService.complete(
312
state.get().getStep1Data(),
313
data
314
);
315
316
return Response.ok(result).build();
317
}
318
}
319
```
320
321
## Best Practices
322
323
### Session Security
324
325
```java
326
@Path("/secure")
327
public class SecureResource {
328
329
@GET
330
@Path("/data")
331
public SecureData getData(@Session HttpSession session) {
332
// Always validate session state
333
String userId = (String) session.getAttribute("userId");
334
if (userId == null) {
335
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
336
}
337
338
// Check session timeout
339
long lastAccess = session.getLastAccessedTime();
340
long now = System.currentTimeMillis();
341
if (now - lastAccess > TimeUnit.HOURS.toMillis(1)) {
342
session.invalidate();
343
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
344
}
345
346
return secureService.getData(userId);
347
}
348
}
349
```
350
351
### Flash Message Types
352
353
```java
354
// Typed flash messages for type safety
355
@Session Flash<String> stringMessage;
356
@Session Flash<List<ValidationError>> validationErrors;
357
@Session Flash<UserNotification> notification;
358
@Session Flash<Map<String, Object>> formData;
359
360
// Generic flash for flexible content
361
@Session Flash<Object> genericFlash;
362
```
363
364
### Session vs Flash Usage
365
366
```java
367
public class SessionUsageExample {
368
369
// Use session attributes for persistent user state
370
public void storeUserPreferences(@Session HttpSession session, UserPreferences prefs) {
371
session.setAttribute("preferences", prefs);
372
session.setAttribute("theme", prefs.getTheme());
373
}
374
375
// Use flash messages for temporary notifications
376
public void showSuccessMessage(@Session Flash<String> flash) {
377
flash.set("Operation completed successfully!");
378
}
379
380
// Use flash for form data preservation on validation errors
381
public void preserveFormData(@Session Flash<FormData> flash, FormData data) {
382
flash.set(data); // Available for next request only
383
}
384
}
385
```