CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-glassfish-jersey-core--jersey-server

Jersey core server implementation for building RESTful Web Services with JAX-RS.

Pending
Overview
Eval results
Files

async-processing.mddocs/

Asynchronous Processing

Server-side asynchronous request processing including async contexts, chunked output, broadcasting, and managed async execution. Enables scalable handling of long-running operations, streaming responses, and real-time communication patterns.

Capabilities

AsyncContext

Server-side asynchronous request processing context providing access to both request and response for asynchronous operations.

/**
 * Server-side asynchronous processing context extending AsyncResponse.
 * Provides access to request and response contexts for asynchronous operations.
 */
public interface AsyncContext extends AsyncResponse {
    
    /**
     * Get the container request associated with this async context.
     * @return ContainerRequest for the asynchronous operation
     */
    ContainerRequest getContainerRequest();
    
    /**
     * Get the container response associated with this async context.
     * @return ContainerResponse for the asynchronous operation
     */
    ContainerResponse getContainerResponse();
    
    /**
     * Suspend the request processing.
     * @return true if successfully suspended, false if already suspended
     */
    boolean suspend();
    
    /**
     * Suspend request processing with timeout.
     * @param time Timeout value
     * @param unit Time unit for timeout
     * @return true if successfully suspended
     */
    boolean suspend(long time, TimeUnit unit);
    
    /**
     * Resume processing with a response.
     * @param response Response to resume with
     * @return true if successfully resumed
     */
    boolean resume(Object response);
    
    /**
     * Resume processing with an exception.
     * @param throwable Exception to resume with
     * @return true if successfully resumed
     */
    boolean resume(Throwable throwable);
    
    /**
     * Cancel the asynchronous processing.
     * @return true if successfully cancelled
     */
    boolean cancel();
    
    /**
     * Check if the async processing is suspended.
     * @return true if currently suspended
     */
    boolean isSuspended();
    
    /**
     * Check if the async processing is cancelled.
     * @return true if cancelled
     */
    boolean isCancelled();
}

Usage Examples:

import org.glassfish.jersey.server.AsyncContext;
import org.glassfish.jersey.server.ContainerRequest;
import jakarta.ws.rs.container.AsyncResponse;
import jakarta.ws.rs.container.Suspended;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.TimeUnit;

@Path("/async")
public class AsyncResource {
    
    @GET
    @Path("/data")
    public void getDataAsync(@Suspended AsyncResponse asyncResponse) {
        // Cast to AsyncContext for additional functionality
        AsyncContext asyncContext = (AsyncContext) asyncResponse;
        
        // Access request information
        ContainerRequest request = asyncContext.getContainerRequest();
        String userAgent = request.getHeaderString("User-Agent");
        
        // Suspend with timeout
        asyncContext.suspend(30, TimeUnit.SECONDS);
        
        // Perform async operation
        CompletableFuture.supplyAsync(() -> {
            return performLongRunningOperation();
        }).thenAccept(result -> {
            // Resume with result
            asyncContext.resume(result);
        }).exceptionally(throwable -> {
            // Resume with exception
            asyncContext.resume(throwable);
            return null;
        });
    }
    
    @POST
    @Path("/cancel")
    public String cancelAsync(@QueryParam("id") String operationId) {
        AsyncContext context = findAsyncContext(operationId);
        if (context != null && context.isSuspended()) {
            boolean cancelled = context.cancel();
            return cancelled ? "Cancelled" : "Could not cancel";
        }
        return "Operation not found or not suspended";
    }
}

ChunkedOutput

Support for chunked transfer encoding responses enabling streaming of data to clients in chunks.

/**
 * Chunked output for streaming responses to clients.
 * Extends GenericType and implements Closeable for resource management.
 */
public class ChunkedOutput<T> extends GenericType<T> implements Closeable {
    
    /**
     * Create chunked output for specified chunk type.
     * @param chunkType Type of chunks to be written
     */
    public ChunkedOutput(Type chunkType);
    
    /**
     * Create chunked output for specified chunk type with separator.
     * @param chunkType Type of chunks to be written
     * @param separator Separator between chunks
     */
    public ChunkedOutput(Type chunkType, String separator);
    
    /**
     * Check if the chunked output is closed.
     * @return true if closed, false otherwise
     */
    public boolean isClosed();
    
    /**
     * Write a chunk to the output.
     * @param chunk Chunk data to write
     * @throws IOException if writing fails or output is closed
     */
    public void write(T chunk) throws IOException;
    
    /**
     * Close the chunked output stream.
     * @throws IOException if closing fails
     */
    public void close() throws IOException;
    
    /**
     * Set exception callback for error handling.
     * @param callback Callback to handle exceptions
     */
    public void setExceptionCallback(ChunkedOutput.ExceptionCallback callback);
    
    /**
     * Exception callback interface for handling write errors.
     */
    public interface ExceptionCallback {
        void onException(ChunkedOutput chunkedOutput, Exception exception);
    }
}

Usage Examples:

import org.glassfish.jersey.server.ChunkedOutput;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;
import java.io.IOException;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@Path("/stream")
public class StreamingResource {
    
    private final ScheduledExecutorService executor = Executors.newScheduledThreadPool(5);
    
    @GET
    @Path("/data")
    @Produces(MediaType.APPLICATION_JSON)
    public ChunkedOutput<String> streamData() {
        ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
        
        // Set exception callback
        output.setExceptionCallback((chunkedOutput, exception) -> {
            System.err.println("Streaming error: " + exception.getMessage());
        });
        
        // Stream data every second for 10 seconds
        executor.scheduleAtFixedRate(() -> {
            try {
                if (!output.isClosed()) {
                    String data = generateData();
                    output.write(data);
                }
            } catch (IOException e) {
                try {
                    output.close();
                } catch (IOException closeEx) {
                    // Log close exception
                }
            }
        }, 0, 1, TimeUnit.SECONDS);
        
        // Auto-close after 10 seconds
        executor.schedule(() -> {
            try {
                output.close();
            } catch (IOException e) {
                // Log exception
            }
        }, 10, TimeUnit.SECONDS);
        
        return output;
    }
    
    @GET
    @Path("/logs")
    @Produces(MediaType.TEXT_PLAIN)
    public ChunkedOutput<String> streamLogs() {
        ChunkedOutput<String> output = new ChunkedOutput<>(String.class, "\n");
        
        // Stream log entries
        streamLogEntries(output);
        
        return output;
    }
    
    private String generateData() {
        return "{\"timestamp\":" + System.currentTimeMillis() + ",\"data\":\"example\"}";
    }
}

Broadcaster

Broadcasting utility for sending messages to multiple clients simultaneously, useful for real-time notifications and pub-sub patterns.

/**
 * Broadcaster for sending messages to multiple ChunkedOutput instances.
 * Implements BroadcasterListener for lifecycle management.
 */
public final class Broadcaster<T> implements BroadcasterListener<T> {
    
    /**
     * Create a broadcaster for specific chunk type without automatic closing.
     * @param chunkType Type of chunks to broadcast
     * @return Broadcaster instance
     */
    public static <T> Broadcaster<T> createOnly(Class<T> chunkType);
    
    /**
     * Create a broadcaster for specific chunk type with automatic closing.
     * @param chunkType Type of chunks to broadcast
     * @return Broadcaster instance that auto-closes when empty
     */
    public static <T> Broadcaster<T> create(Class<T> chunkType);
    
    /**
     * Add a chunked output to the broadcaster.
     * @param chunkedOutput ChunkedOutput to add
     * @return true if successfully added
     */
    public boolean add(ChunkedOutput<T> chunkedOutput);
    
    /**
     * Remove a chunked output from the broadcaster.
     * @param chunkedOutput ChunkedOutput to remove
     * @return true if successfully removed
     */
    public boolean remove(ChunkedOutput<T> chunkedOutput);
    
    /**
     * Broadcast a chunk to all registered outputs.
     * @param chunk Chunk to broadcast
     */
    public void broadcast(T chunk);
    
    /**
     * Close all registered outputs and clear the broadcaster.
     */
    public void closeAll();
    
    /**
     * Get the number of registered outputs.
     * @return Number of active chunked outputs
     */
    public int size();
    
    /**
     * Check if the broadcaster is empty.
     * @return true if no outputs are registered
     */
    public boolean isEmpty();
    
    /**
     * Add a broadcaster listener.
     * @param listener Listener to add
     */
    public void addListener(BroadcasterListener<T> listener);
    
    /**
     * Remove a broadcaster listener.
     * @param listener Listener to remove
     */
    public void removeListener(BroadcasterListener<T> listener);
}

Usage Examples:

import org.glassfish.jersey.server.Broadcaster;
import org.glassfish.jersey.server.ChunkedOutput;
import org.glassfish.jersey.server.BroadcasterListener;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.POST;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.core.MediaType;

@Path("/notifications")
public class NotificationResource {
    
    // Static broadcaster for notifications
    private static final Broadcaster<String> broadcaster = Broadcaster.create(String.class);
    
    static {
        // Add listener for broadcaster events
        broadcaster.addListener(new BroadcasterListener<String>() {
            @Override
            public void onClose(ChunkedOutput<String> chunkedOutput) {
                System.out.println("Client disconnected from notifications");
            }
            
            @Override
            public void onException(ChunkedOutput<String> chunkedOutput, Exception exception) {
                System.err.println("Broadcast error: " + exception.getMessage());
            }
        });
    }
    
    @GET
    @Path("/subscribe")
    @Produces(MediaType.TEXT_PLAIN)
    public ChunkedOutput<String> subscribe() {
        ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
        
        // Add to broadcaster
        broadcaster.add(output);
        
        // Send welcome message
        try {
            output.write("Connected to notifications");
        } catch (IOException e) {
            broadcaster.remove(output);
        }
        
        return output;
    }
    
    @POST
    @Path("/send")
    public String sendNotification(String message) {
        // Broadcast to all subscribers
        broadcaster.broadcast("NOTIFICATION: " + message);
        
        return "Notification sent to " + broadcaster.size() + " subscribers";
    }
    
    @GET
    @Path("/stats")
    @Produces(MediaType.APPLICATION_JSON)
    public String getStats() {
        return "{\"subscribers\":" + broadcaster.size() + ",\"isEmpty\":" + broadcaster.isEmpty() + "}";
    }
    
    @POST
    @Path("/shutdown")
    public String shutdown() {
        broadcaster.closeAll();
        return "All notification subscribers disconnected";
    }
}

BroadcasterListener

Event listener interface for broadcaster lifecycle events and error handling.

/**
 * Listener interface for broadcaster events.
 * Provides callbacks for output lifecycle and error handling.
 */
public interface BroadcasterListener<T> {
    
    /**
     * Called when a chunked output is closed.
     * @param chunkedOutput ChunkedOutput that was closed
     */
    default void onClose(ChunkedOutput<T> chunkedOutput) {
        // Default implementation does nothing
    }
    
    /**
     * Called when an exception occurs during broadcasting.
     * @param chunkedOutput ChunkedOutput where exception occurred
     * @param exception Exception that occurred
     */
    default void onException(ChunkedOutput<T> chunkedOutput, Exception exception) {
        // Default implementation does nothing
    }
}

Managed Async Annotations

Annotations for controlling managed asynchronous execution in Jersey resources.

/**
 * Annotation marking methods for managed asynchronous execution.
 * Methods annotated with this will be executed on a managed thread pool.
 */
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManagedAsync {
    // Marker annotation - no parameters
}

/**
 * Qualifier annotation for injecting managed async executor.
 * Used with @Inject to get the managed executor service.
 */
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface ManagedAsyncExecutor {
    // Qualifier annotation - no parameters
}

/**
 * Qualifier annotation for injecting background scheduler.
 * Used with @Inject to get the background scheduled executor service.
 */
@Qualifier
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface BackgroundScheduler {
    // Qualifier annotation - no parameters
}

Usage Examples:

import org.glassfish.jersey.server.ManagedAsync;
import org.glassfish.jersey.server.ManagedAsyncExecutor;
import org.glassfish.jersey.server.BackgroundScheduler;
import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.container.AsyncResponse;
import jakarta.ws.rs.container.Suspended;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Path("/managed")
public class ManagedAsyncResource {
    
    @Inject
    @ManagedAsyncExecutor
    private ExecutorService asyncExecutor;
    
    @Inject
    @BackgroundScheduler
    private ScheduledExecutorService scheduler;
    
    @GET
    @Path("/simple")
    @ManagedAsync
    public String getManagedAsync() {
        // This method will be executed on managed thread pool
        return performLongOperation();
    }
    
    @GET
    @Path("/custom")
    public void getCustomAsync(@Suspended AsyncResponse asyncResponse) {
        // Use injected managed executor
        asyncExecutor.submit(() -> {
            try {
                String result = performLongOperation();
                asyncResponse.resume(result);
            } catch (Exception e) {
                asyncResponse.resume(e);
            }
        });
    }
    
    @GET
    @Path("/scheduled")
    public void getScheduledAsync(@Suspended AsyncResponse asyncResponse) {
        // Use injected background scheduler
        scheduler.schedule(() -> {
            try {
                String result = performDelayedOperation();
                asyncResponse.resume(result);
            } catch (Exception e) {
                asyncResponse.resume(e);
            }
        }, 5, TimeUnit.SECONDS);
    }
    
    @ManagedAsync
    @GET
    @Path("/streaming")
    public ChunkedOutput<String> getManagedStreaming() {
        // Managed async with streaming
        ChunkedOutput<String> output = new ChunkedOutput<>(String.class);
        
        scheduler.scheduleAtFixedRate(() -> {
            try {
                if (!output.isClosed()) {
                    output.write("Managed stream data: " + System.currentTimeMillis());
                }
            } catch (IOException e) {
                try {
                    output.close();
                } catch (IOException closeEx) {
                    // Log close exception
                }
            }
        }, 0, 2, TimeUnit.SECONDS);
        
        return output;
    }
    
    private String performLongOperation() {
        // Simulate long-running operation
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        }
        return "Long operation completed";
    }
    
    private String performDelayedOperation() {
        return "Delayed operation completed at " + System.currentTimeMillis();
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-org-glassfish-jersey-core--jersey-server

docs

async-processing.md

configuration-properties.md

index.md

monitoring.md

request-processing.md

resource-configuration.md

resource-model.md

spi.md

wadl.md

tile.json