org.atmosphere.cpr.AtmosphereHandler Maven / Gradle / Ivy
/*
* Copyright 2008-2024 Async-IO.org
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.atmosphere.cpr;
import java.io.IOException;
/**
* Implementation of {@link AtmosphereHandler} allows creation of event-driven web applications which are hosted in
* the browser. An {@link AtmosphereHandler} allows a web application to suspend and resume an HTTP response. An HTTP
* response can be suspended {@link AtmosphereResource#suspend()} and later resume via {@link AtmosphereResource#resume()}.
* Messages can also be shared between suspended responses and their associated {@link AtmosphereHandler} using a
* {@link Broadcaster}. Any invocation of {@link Broadcaster#broadcast(java.lang.Object)} will allow a suspended
* response to write the content of the message {@link AtmosphereHandler#onStateChange(org.atmosphere.cpr.AtmosphereResourceEvent)}.
*
* A class implementing {@link AtmosphereHandler} must be thread safe.
*
* For example, a simple pubsub based AtmosphereHandler will take the form of
*
public class AtmosphereHandlerPubSub extends AbstractReflectorAtmosphereHandler {
public void onRequest(AtmosphereResource r) throws IOException {
AtmosphereRequest req = r.getRequest();
AtmosphereResponse res = r.getResponse();
String method = req.getMethod();
// Suspend the response.
if ("GET".equalsIgnoreCase(method)) {
// Log all events on the console, including WebSocket events.
r.addEventListener(new WebSocketEventListenerAdapter());
res.setContentType("text/html;charset=ISO-8859-1");
Broadcaster b = lookupBroadcaster(req.getPathInfo());
r.setBroadcaster(b).suspend();
} else if ("POST".equalsIgnoreCase(method)) {
Broadcaster b = lookupBroadcaster(req.getPathInfo());
String message = req.getReader().readLine();
if (message != null && message.indexOf("message") != -1) {
b.broadcast(message.substring("message=".length()));
}
}
}
public void destroy() {
}
Broadcaster lookupBroadcaster(String pathInfo) {
String[] decodedPath = pathInfo.split("/");
Broadcaster b = BroadcasterFactory.getDefault().lookup(decodedPath[decodedPath.length - 1], true);
return b;
}
}
*
* It is recommended to use the {@link org.atmosphere.config.service.AtmosphereHandlerService}
* or {@link org.atmosphere.config.service.ManagedService} annotation to reduce the number
* of lines of code and take advantage of {@link AtmosphereInterceptor} such as
* {@link org.atmosphere.interceptor.AtmosphereResourceStateRecovery} and
* {@link org.atmosphere.interceptor.AtmosphereResourceLifecycleInterceptor}.
*
* @author Jeanfrancois Arcand
*/
public interface AtmosphereHandler {
/**
* When a client sends a request to its associated {@link AtmosphereHandler}, it can decide if the underlying
* connection can be suspended (creating a Continuation) or handle the connection synchronously.
*
* It is recommended to only suspend requests for which HTTP method is a GET and use the POST method to send data
* to the server, without marking the connection as asynchronous.
*
* @param resource an {@link AtmosphereResource}
*/
void onRequest(AtmosphereResource resource) throws IOException;
/**
* This method is invoked when the {@link Broadcaster} executes a broadcast operation. When this method is invoked
* its associated {@link Broadcaster}, any suspended connection will be allowed to write the data back to its
* associated clients.
*
* This method will also be invoked when a response get resumed, e.g. when {@link AtmosphereResource#resume} gets
* invoked. In that case, {@link AtmosphereResourceEvent#isResuming} will return true.
*
* This method will also be invoked when the {@link AtmosphereResource#suspend(long)} expires. In that case,
* {@link AtmosphereResourceEvent#isResumedOnTimeout} will return true.
*
* @param event an {@link AtmosphereResourceEvent}
*/
void onStateChange(AtmosphereResourceEvent event) throws IOException;
/**
* Destroy this handler
*/
void destroy();
}