CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-dropwizard--dropwizard-jersey

Dropwizard Jersey Support - Jersey integration module for the Dropwizard Java framework

Pending
Overview
Eval results
Files

session-management.mddocs/

Session Management

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.

Capabilities

Session Annotation

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 Messages

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();
    }
}

Session Factories

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();
    }
}

Session Configuration

Basic Session Setup

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
    }
}

Session Lifecycle Management

@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();
    }
}

Flash Message Patterns

@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();
    }
}

Best Practices

Session Security

@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);
    }
}

Flash Message Types

// 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;

Session vs Flash Usage

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

docs

error-handling.md

framework-configuration.md

http-caching.md

index.md

jsr310-parameters.md

optional-handling.md

parameter-handling.md

session-management.md

validation.md

tile.json