Skip to content

Package: RemoteEndpoint$Basic

RemoteEndpoint$Basic

Coverage

1: /*
2: * Copyright (c) 2018, 2021 Oracle and/or its affiliates and others.
3: * All rights reserved.
4: *
5: * This program and the accompanying materials are made available under the
6: * terms of the Eclipse Public License v. 2.0, which is available at
7: * http://www.eclipse.org/legal/epl-2.0.
8: *
9: * This Source Code may also be made available under the following Secondary
10: * Licenses when the conditions for such availability set forth in the
11: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
12: * version 2 with the GNU Classpath Exception, which is available at
13: * https://www.gnu.org/software/classpath/license.html.
14: *
15: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
16: */
17:
18: package jakarta.websocket;
19:
20: import java.io.IOException;
21: import java.io.OutputStream;
22: import java.io.Writer;
23: import java.nio.ByteBuffer;
24: import java.util.concurrent.Future;
25:
26: /**
27: * The RemoteEndpoint object is supplied by the container and represents the 'other end' or peer of the Web Socket
28: * conversation. Instances of the RemoteEndpoint are obtained from the Session using {@link Session#getBasicRemote()} or
29: * {@link Session#getAsyncRemote()}. Objects of this kind include numerous ways to send web socket messages. There are
30: * two kinds of RemoteEndpoint objects: RemoteEndpoint.Basic for synchronous sending of websocket messages, and
31: * RemoteEndpoint.Async for sending messages asynchronously.
32: *
33: * <p>
34: * There is no guarantee of the successful delivery of a web socket message to the peer, but if the action of sending a
35: * message causes an error known to the container, the API throws it. RemoteEndpoints include a variety of ways to send
36: * messages: by whole message, in parts, and in various data formats including websocket pings and pongs.
37: *
38: * <p>
39: * Implementations may or may not support batching of messages. More detail of the expected semantics of implementations
40: * that do support batching are laid out in {@link RemoteEndpoint#setBatchingAllowed(boolean)}.
41: *
42: * <p>
43: * Note: Implementations may choose their own schemes for sending large messages in smaller parts. These schemes may or
44: * may not bear a relationship to the underlying websocket dataframes in which the message is ultimately sent on the
45: * wire.
46: *
47: * <p>
48: * If the underlying connection is closed and methods on the RemoteEndpoint are attempted to be called, they will result
49: * in an error being generated. For the methods that send messages, this will be an IOException, for the methods that
50: * alter configuration of the endpoint, this will be runtime IllegalArgumentExceptions.
51: *
52: * @author dannycoward
53: */
54: public interface RemoteEndpoint {
55:
56: /**
57: * Indicate to the implementation that it is allowed to batch outgoing messages before sending. Not all
58: * implementations support batching of outgoing messages. The default mode for RemoteEndpoints is false. If the
59: * developer has indicated that batching of outgoing messages is permitted, then the developer must call
60: * flushBatch() in order to be sure that all the messages passed into the send methods of this RemoteEndpoint are
61: * sent. When batching is allowed, the implementations send operations are considered to have completed if the
62: * message has been written to the local batch, in the case when there is still room in the batch for the message,
63: * and are considered to have completed if the batch has been send to the peer and the remainder written to the new
64: * batch, in the case when writing the message causes the batch to need to be sent. The blocking and asynchronous
65: * send methods use this notion of completion in order to complete blocking calls, notify SendHandlers and complete
66: * Futures respectively. When batching is allowed, if the developer has called send methods on this RemoteEndpoint
67: * without calling flushBatch(), then the implementation may not have sent all the messages the developer has asked
68: * to be sent. If the parameter value is false and the implementation has a batch of unsent messages, then the
69: * implementation must immediately send the batch of unsent messages.
70: *
71: * @param allowed whether the implementation is allowed to batch messages.
72: * @throws IOException if batching is being disabled and there are unsent messages this error may be thrown as the
73: * implementation sends the batch of unsent messages if there is a problem.
74: */
75: void setBatchingAllowed(boolean allowed) throws IOException;
76:
77: /**
78: * Return whether the implementation is allowed to batch outgoing messages before sending. The default mode for
79: * RemoteEndpoints is false. The value may be changed by calling {@link #setBatchingAllowed(boolean)
80: * setBatchingAllowed}.
81: *
82: * @return {@code true} if the implementation is allowed to batch outgoing messages before sending, otherwise
83: * {@code false}
84: */
85: boolean getBatchingAllowed();
86:
87: /**
88: * This method is only used when batching is allowed for this RemoteEndpint. Calling this method forces the
89: * implementation to send any unsent messages it has been batching.
90: *
91: * @throws IOException if the sending of any unsent messages failed
92: */
93: void flushBatch() throws IOException;
94:
95: /**
96: * Send a Ping message containing the given application data to the remote endpoint. The corresponding Pong message
97: * may be picked up using the MessageHandler.Pong handler.
98: * <p>
99: * It is not safe for other threads to use the ByteBuffer until the sending of this message is complete. If the
100: * sending of the message completes successfully, the buffer's limit will be unchanged and the buffer's position
101: * will be equal to the limit. If the sending of the message does not complete successfully, the state of the buffer
102: * is undefined.
103: *
104: * @param applicationData the data to be carried in the ping request.
105: * @throws IOException if the ping failed to be sent
106: * @throws IllegalArgumentException if the applicationData exceeds the maximum allowed payload of 125 bytes
107: */
108: void sendPing(ByteBuffer applicationData) throws IOException, IllegalArgumentException;
109:
110: /**
111: * Allows the developer to send an unsolicited Pong message containing the given application data in order to serve
112: * as a unidirectional heartbeat for the session.
113: * <p>
114: * It is not safe for other threads to use the ByteBuffer until the sending of this message is complete. If the
115: * sending of the message completes successfully, the buffer's limit will be unchanged and the buffer's position
116: * will be equal to the limit. If the sending of the message does not complete successfully, the state of the buffer
117: * is undefined.
118: *
119: * @param applicationData the application data to be carried in the pong response.
120: * @throws IOException if the pong failed to be sent
121: * @throws IllegalArgumentException if the applicationData exceeds the maximum allowed payload of 125 bytes
122: */
123: void sendPong(ByteBuffer applicationData) throws IOException, IllegalArgumentException;
124:
125: /**
126: * This representation of the peer of a web socket conversation has the ability to send messages asynchronously. The
127: * point of completion of the send is defined when all the supplied data has been written to the underlying
128: * connection. The completion handlers for the asynchronous methods may be called with a different thread from that
129: * which initiated the send.
130: */
131: interface Async extends RemoteEndpoint {
132:
133: /**
134: * Return the number of milliseconds the implementation will timeout attempting to send a websocket message. A
135: * zero or negative value indicates the implementation will not timeout attempting to send a websocket message
136: * asynchronously. This value overrides the default value assigned in the WebSocketContainer.
137: *
138: * @return the timeout time in milliseconds.
139: */
140: long getSendTimeout();
141:
142: /**
143: * Sets the number of milliseconds the implementation will timeout attempting to send a websocket message. A
144: * zero or negative value indicates the implementation will not timeout attempting to send a websocket message
145: * asynchronously. This value overrides the default value assigned in the WebSocketContainer.
146: *
147: * @param timeoutmillis The number of milliseconds this RemoteEndpoint will wait before timing out an incomplete
148: * asynchronous message send.
149: */
150: void setSendTimeout(long timeoutmillis);
151:
152: /**
153: * Initiates the asynchronous transmission of a text message. This method returns before the message is
154: * transmitted. Developers provide a callback to be notified when the message has been transmitted. Errors in
155: * transmission are given to the developer in the SendResult object.
156: *
157: * @param text the text being sent.
158: * @param handler the handler which will be notified of progress.
159: * @throws IllegalArgumentException if the text or the handler is {@code null}.
160: */
161: void sendText(String text, SendHandler handler);
162:
163: /**
164: * Initiates the asynchronous transmission of a text message. This method returns before the message is
165: * transmitted. Developers use the returned Future object to track progress of the transmission. The Future's
166: * get() method returns {@code null} upon successful completion. Errors in transmission are wrapped in the
167: * {@link java.util.concurrent.ExecutionException} thrown when querying the Future object.
168: *
169: * @param text the text being sent.
170: * @return the Future object representing the send operation.
171: * @throws IllegalArgumentException if the text is {@code null}.
172: */
173: Future<Void> sendText(String text);
174:
175: /**
176: * Initiates the asynchronous transmission of a binary message. This method returns before the message is
177: * transmitted. Developers use the returned Future object to track progress of the transmission. The Future's
178: * get() method returns {@code null} upon successful completion. Errors in transmission are wrapped in the
179: * {@link java.util.concurrent.ExecutionException} thrown when querying the Future object.
180: * <p>
181: * It is not safe for other threads to use the ByteBuffer until the sending of this message is complete. If the
182: * sending of the message completes successfully, the buffer's limit will be unchanged and the buffer's position
183: * will be equal to the limit. If the sending of the message does not complete successfully, the state of the
184: * buffer is undefined.
185: *
186: * @param data the data being sent.
187: * @return the Future object representing the send operation.
188: * @throws IllegalArgumentException if the data is {@code null}.
189: */
190: Future<Void> sendBinary(ByteBuffer data);
191:
192: /**
193: * Initiates the asynchronous transmission of a binary message. This method returns before the message is
194: * transmitted. Developers provide a callback to be notified when the message has been transmitted. Errors in
195: * transmission are given to the developer in the SendResult object.
196: * <p>
197: * It is not safe for other threads to use the ByteBuffer until the sending of this message is complete. If the
198: * sending of the message completes successfully, the buffer's limit will be unchanged and the buffer's position
199: * will be equal to the limit. If the sending of the message does not complete successfully, the state of the
200: * buffer is undefined.
201: *
202: * @param data the data being sent, must not be {@code null}.
203: * @param handler the handler that will be notified of progress, must not be {@code null}.
204: * @throws IllegalArgumentException if either the data or the handler are {@code null}.
205: */
206: void sendBinary(ByteBuffer data, SendHandler handler);
207:
208: /**
209: * Initiates the asynchronous transmission of a custom developer object. The developer will have provided an
210: * encoder for this object type in the endpoint configuration. Containers will by default be able to encode java
211: * primitive types and their object equivalents, otherwise the developer must have provided an encoder for the
212: * object type in the endpoint configuration. A developer-provided encoder for a Java primitive type and its
213: * object equivalent overrides the container default encoder. Progress may be tracked using the Future object.
214: * The Future's get() methods return {@code null} upon successful completion. Errors in transmission are wrapped
215: * in the {@link java.util.concurrent.ExecutionException} thrown when querying the Future object.
216: *
217: * @param data the object being sent.
218: * @return the Future object representing the send operation.
219: * @throws IllegalArgumentException if the data is {@code null}.
220: *
221: */
222: Future<Void> sendObject(Object data);
223:
224: /**
225: * Initiates the asynchronous transmission of a custom developer object. Containers will by default be able to
226: * encode java primitive types and their object equivalents, otherwise the developer must have provided an
227: * encoder for the object type in the endpoint configuration. A developer-provided encoder for a Java primitive
228: * type and its object equivalent overrides the container default encoder. Developers are notified when
229: * transmission is complete through the supplied callback object.
230: *
231: * @param data the object being sent.
232: * @param handler the handler that will be notified of progress, must not be {@code null}.
233: * @throws IllegalArgumentException if either the data or the handler are {@code null}.
234: */
235: void sendObject(Object data, SendHandler handler);
236:
237: }
238:
239: /**
240: * This representation of the peer of a web socket conversation has the ability to send messages synchronously. The
241: * point of completion of the send is defined when all the supplied data has been written to the underlying
242: * connection. The methods for sending messages on the RemoteEndpoint.Basic block until this point of completion is
243: * reached, except for {@link RemoteEndpoint.Basic#getSendStream() getSendStream} and
244: * {@link RemoteEndpoint.Basic#getSendWriter() getSendWriter} which present traditional blocking I/O streams to
245: * write messages.
246: *
247: * <p>
248: * If the websocket connection underlying this RemoteEndpoint is busy sending a message when a call is made to send
249: * another one, for example if two threads attempt to call a send method concurrently, or if a developer attempts to
250: * send a new message while in the middle of sending an existing one, the send method called while the connection is
251: * already busy may throw an {@link java.lang.IllegalStateException}.
252: */
253: interface Basic extends RemoteEndpoint {
254:
255: /**
256: * Send a text message, blocking until all of the message has been transmitted.
257: *
258: * @param text the message to be sent.
259: * @throws IOException if there is a problem delivering the message.
260: * @throws IllegalArgumentException if the text is {@code null}.
261: */
262: void sendText(String text) throws IOException;
263:
264: /**
265: * Send a binary message, returning when all of the message has been transmitted.
266: * <p>
267: * It is not safe for other threads to use the ByteBuffer until the sending of this message is complete. If the
268: * sending of the message completes successfully, the buffer's limit will be unchanged and the buffer's position
269: * will be equal to the limit. If the sending of the message does not complete successfully, the state of the
270: * buffer is undefined.
271: *
272: * @param data the message to be sent.
273: * @throws IOException if there is a problem delivering the message.
274: * @throws IllegalArgumentException if the data is {@code null}.
275: *
276: */
277: void sendBinary(ByteBuffer data) throws IOException;
278:
279: /**
280: * Send a text message in parts, blocking until all of the message has been transmitted. The runtime reads the
281: * message in order. Non-final parts of the message are sent with isLast set to false. The final part must be
282: * sent with isLast set to true.
283: *
284: * @param partialMessage the parts of the message being sent.
285: * @param isLast Whether the partial message being sent is the last part of the message.
286: * @throws IOException if there is a problem delivering the message fragment.
287: * @throws IllegalArgumentException if the partialMessage is {@code null}.
288: */
289: void sendText(String partialMessage, boolean isLast) throws IOException;
290:
291: /**
292: * Send a binary message in parts, blocking until all of the message has been transmitted. The runtime reads the
293: * message in order. Non-final parts are sent with isLast set to false. The final piece must be sent with isLast
294: * set to true.
295: * <p>
296: * It is not safe for other threads to use the ByteBuffer until the sending of this partial message is complete.
297: * If the sending of the partial message completes successfully, the buffer's limit will be unchanged and the
298: * buffer's position will be equal to the limit. If the sending of the partial message does not complete
299: * successfully, the state of the buffer is undefined.
300: *
301: * @param partialByte the part of the message being sent.
302: * @param isLast Whether the partial message being sent is the last part of the message.
303: * @throws IOException if there is a problem delivering the partial message.
304: * @throws IllegalArgumentException if the partialByte is {@code null}.
305: */
306: void sendBinary(ByteBuffer partialByte, boolean isLast) throws IOException; // or Iterable<byte[]>
307:
308: /**
309: * Opens an output stream on which a binary message may be sent. The developer must close the output stream in
310: * order to indicate that the complete message has been placed into the output stream. If no calls are made to
311: * one of the {@code write()} methods before the output stream is closed then no WebSocket binary messages will
312: * be sent. If at least one call is made to one of the {@code write()} methods before the output stream is
313: * closed then at least one WebSocket binary message will be sent even if that message is of zero length.
314: *
315: * @return the output stream to which the message will be written.
316: * @throws IOException if there is a problem obtaining the OutputStream to write the binary message.
317: */
318: OutputStream getSendStream() throws IOException;
319:
320: /**
321: * Opens a character stream on which a text message may be sent. The developer must close the writer in order to
322: * indicate that the complete message has been placed into the character stream. If no calls are made to one of
323: * the {@code write()} or {@code append()} methods before the writer is closed then no WebSocket text messages
324: * will be sent. If at least one call is made to one of the {@code write()} or {@code append()} methods before
325: * the writer is closed then at least one WebSocket text message will be sent even if that message is of zero
326: * length.
327: *
328: * @return the writer to which the message will be written.
329: * @throws IOException if there is a problem obtaining the Writer to write the text message.
330: */
331: Writer getSendWriter() throws IOException;
332:
333: /**
334: * Sends a custom developer object, blocking until it has been transmitted. Containers will by default be able
335: * to encode java primitive types and their object equivalents, otherwise the developer must have provided an
336: * encoder for the object type in the endpoint configuration. A developer-provided encoder for a Java primitive
337: * type and its object equivalent overrides the container default encoder.
338: *
339: * @param data the object to be sent.
340: * @throws IOException if there is a communication error sending the message object.
341: * @throws EncodeException if there was a problem encoding the message object into the form of a native
342: * websocket message.
343: * @throws IllegalArgumentException if the data parameter is {@code null}
344: */
345: void sendObject(Object data) throws IOException, EncodeException;
346: }
347:
348: }