Dropwizard Jersey Support - Jersey integration module for the Dropwizard Java framework
—
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.
Annotation for injecting HttpSession instances into JAX-RS resource method parameters and fields.
/**
* Injects HttpSession into resource method parameters or fields
* Supports configuration for session creation behavior
*/
@Documented
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER, ElementType.FIELD})
public @interface Session {
/**
* Whether to avoid creating a new session if one doesn't exist
* @return true to avoid creating new sessions, false to create if needed
*/
boolean doNotCreate() default false;
}Usage Examples:
import io.dropwizard.jersey.sessions.Session;
import jakarta.servlet.http.HttpSession;
import jakarta.ws.rs.*;
@Path("/users")
public class UserResource {
@POST
@Path("/login")
public Response login(@FormParam("username") String username,
@FormParam("password") String password,
@Session HttpSession session) {
if (authService.authenticate(username, password)) {
session.setAttribute("userId", username);
session.setAttribute("loginTime", System.currentTimeMillis());
return Response.ok().build();
}
return Response.status(401).build();
}
@GET
@Path("/profile")
public UserProfile getProfile(@Session HttpSession session) {
String userId = (String) session.getAttribute("userId");
if (userId == null) {
throw new WebApplicationException(401);
}
return userService.getProfile(userId);
}
@POST
@Path("/logout")
public Response logout(@Session HttpSession session) {
session.invalidate();
return Response.ok().build();
}
// Don't create session if it doesn't exist
@GET
@Path("/check")
public Response checkSession(@Session(doNotCreate = true) HttpSession session) {
if (session == null) {
return Response.status(401).entity("No active session").build();
}
return Response.ok().entity("Session active").build();
}
}Flash message support for storing temporary messages in the session that are automatically removed after being accessed.
/**
* Flash message container for session-based temporary messages
* Messages are automatically removed after being accessed
* @param <T> type of flash message content
*/
public class Flash<T> {
/**
* Gets the flash message content, removing it from session
* @return Optional containing the flash message, or empty if none exists
*/
public Optional<T> get();
/**
* Sets a flash message in the session
* @param value the message content to store
*/
public void set(T value);
}Usage Examples:
import io.dropwizard.jersey.sessions.Flash;
import io.dropwizard.jersey.sessions.Session;
import jakarta.servlet.http.HttpSession;
import jakarta.ws.rs.*;
import java.util.Optional;
@Path("/account")
public class AccountResource {
@POST
@Path("/update")
public Response updateAccount(@Valid UpdateAccountRequest request,
@Session HttpSession session,
@Session Flash<String> flash) {
try {
accountService.update(getCurrentUserId(session), request);
flash.set("Account updated successfully!");
return Response.seeOther(URI.create("/account")).build();
} catch (ValidationException e) {
flash.set("Error: " + e.getMessage());
return Response.seeOther(URI.create("/account/edit")).build();
}
}
@GET
@Path("/")
public AccountView getAccount(@Session HttpSession session,
@Session Flash<String> flash) {
String userId = getCurrentUserId(session);
Account account = accountService.getAccount(userId);
// Check for flash message
Optional<String> message = flash.get(); // Automatically removes from session
return new AccountView(account, message.orElse(null));
}
@GET
@Path("/notifications")
public Response getNotifications(@Session Flash<List<String>> notifications) {
Optional<List<String>> messages = notifications.get();
if (messages.isPresent()) {
return Response.ok(messages.get()).build();
}
return Response.ok(Collections.emptyList()).build();
}
}Factory classes that provide HttpSession and Flash instances for dependency injection.
/**
* Factory for creating HttpSession instances
* Used by Jersey's dependency injection system
*/
public class HttpSessionFactory implements Factory<HttpSession> {
/** Provides the current HttpSession instance */
public HttpSession provide();
/** Disposes of the HttpSession (no-op) */
public void dispose(HttpSession instance);
}
/**
* Factory for creating Flash instances
* Used by Jersey's dependency injection system
*/
public class FlashFactory implements Factory<Flash<?>> {
/** Provides a Flash instance for the current session */
public Flash<?> provide();
/** Disposes of the Flash instance (no-op) */
public void dispose(Flash<?> instance);
}
/**
* Provider that registers session-related factories with Jersey
*/
public class SessionFactoryProvider {
/**
* Binder that registers HttpSessionFactory and FlashFactory
* Used internally by DropwizardResourceConfig
*/
public static class Binder extends AbstractBinder {
protected void configure();
}
}Sessions are automatically configured when using DropwizardResourceConfig, but you can customize session behavior:
import io.dropwizard.jersey.DropwizardResourceConfig;
import io.dropwizard.jersey.sessions.SessionFactoryProvider;
public class MyApplication extends Application<MyConfiguration> {
@Override
public void run(MyConfiguration config, Environment environment) {
// Sessions are automatically registered with DropwizardResourceConfig
JerseyEnvironment jersey = environment.jersey();
// Register resources that use sessions
jersey.register(UserSessionResource.class);
// Configure session timeout in Jetty (if needed)
environment.servlets()
.setSessionHandler(new SessionHandler())
.getSessionManager()
.setMaxInactiveInterval(3600); // 1 hour
}
}@Path("/session")
public class SessionResource {
@POST
@Path("/create")
public Response createSession(@Session HttpSession session) {
// Session is automatically created if it doesn't exist
session.setAttribute("created", Instant.now());
return Response.ok().build();
}
@GET
@Path("/info")
public SessionInfo getSessionInfo(@Session HttpSession session) {
return SessionInfo.builder()
.id(session.getId())
.creationTime(Instant.ofEpochMilli(session.getCreationTime()))
.lastAccessTime(Instant.ofEpochMilli(session.getLastAccessedTime()))
.maxInactiveInterval(session.getMaxInactiveInterval())
.isNew(session.isNew())
.build();
}
@DELETE
@Path("/")
public Response invalidateSession(@Session HttpSession session) {
session.invalidate();
return Response.noContent().build();
}
}@Path("/wizard")
public class WizardResource {
@POST
@Path("/step1")
public Response processStep1(@Valid Step1Data data,
@Session HttpSession session,
@Session Flash<WizardState> wizardFlash) {
// Store intermediate data in flash
WizardState state = new WizardState();
state.setStep1Data(data);
wizardFlash.set(state);
return Response.seeOther(URI.create("/wizard/step2")).build();
}
@GET
@Path("/step2")
public Step2View showStep2(@Session Flash<WizardState> wizardFlash) {
Optional<WizardState> state = wizardFlash.get();
if (!state.isPresent()) {
// No flash data, redirect to start
throw new WebApplicationException(
Response.seeOther(URI.create("/wizard/step1")).build()
);
}
return new Step2View(state.get().getStep1Data());
}
@POST
@Path("/step2")
public Response processStep2(@Valid Step2Data data,
@Session Flash<WizardState> wizardFlash) {
Optional<WizardState> state = wizardFlash.get();
if (!state.isPresent()) {
return Response.seeOther(URI.create("/wizard/step1")).build();
}
// Complete wizard with both steps
WizardResult result = wizardService.complete(
state.get().getStep1Data(),
data
);
return Response.ok(result).build();
}
}@Path("/secure")
public class SecureResource {
@GET
@Path("/data")
public SecureData getData(@Session HttpSession session) {
// Always validate session state
String userId = (String) session.getAttribute("userId");
if (userId == null) {
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
// Check session timeout
long lastAccess = session.getLastAccessedTime();
long now = System.currentTimeMillis();
if (now - lastAccess > TimeUnit.HOURS.toMillis(1)) {
session.invalidate();
throw new WebApplicationException(Response.Status.UNAUTHORIZED);
}
return secureService.getData(userId);
}
}// Typed flash messages for type safety
@Session Flash<String> stringMessage;
@Session Flash<List<ValidationError>> validationErrors;
@Session Flash<UserNotification> notification;
@Session Flash<Map<String, Object>> formData;
// Generic flash for flexible content
@Session Flash<Object> genericFlash;public class SessionUsageExample {
// Use session attributes for persistent user state
public void storeUserPreferences(@Session HttpSession session, UserPreferences prefs) {
session.setAttribute("preferences", prefs);
session.setAttribute("theme", prefs.getTheme());
}
// Use flash messages for temporary notifications
public void showSuccessMessage(@Session Flash<String> flash) {
flash.set("Operation completed successfully!");
}
// Use flash for form data preservation on validation errors
public void preserveFormData(@Session Flash<FormData> flash, FormData data) {
flash.set(data); // Available for next request only
}
}Install with Tessl CLI
npx tessl i tessl/maven-io-dropwizard--dropwizard-jersey