Backend API. Server-side code: this runs in a Codename One backend, not in the app on the device.

public interface WebSocket

What an application implements to serve a websocket route.

One instance per ROUTE, not per connection – the same shape a @RestController has. Everything that belongs to one client lives on the WebSocketSession handed to each callback, so an endpoint can be stateless and a stateful one puts its state in WebSocketSession.setAttachment.

`@WebSocketMapping("/echo")`
public class Echo implements WebSocket {
public void onOpen(WebSocketSession session) { }
public void onText(WebSocketSession session, String message) throws Exception {
session.sendText(message);
}
public void onBinary(WebSocketSession session, byte\[\] message, int offset, int length)
throws Exception {
session.sendBinary(message, offset, length);
}
}

The build finds that and registers it. A server assembled by hand gets the same thing through a callback rather than a setter – see Backend.WebSocketEndpoints – because this runtime is asked for its configuration while it starts and never reconfigured once it is running.

Threading is the part worth reading twice. A callback runs on the thread that owns the connection – a virtual thread where the server has them, a pool worker otherwise – and the server reads nothing more from that connection until the callback returns. So an endpoint may block, and a slow endpoint slows down its own client and nobody else’s. What it must not do is assume it is alone: a session may be sent to from another thread entirely (that is what makes broadcast possible), and WebSocketSession is written to allow it.

The optional callbacks have empty defaults, so an endpoint overrides only what it cares about. PING is answered automatically before onPing is called; an endpoint never has to write the PONG itself.

Methods

public abstract void onOpen(WebSocketSession session) throws ExceptionThe handshake is done and the 101 is on the wire.
public abstract void onText(WebSocketSession session, String message) throws ExceptionA whole text message, reassembled from however many frames carried it, and already validated as UTF-8.
public abstract void onBinary(WebSocketSession session, byte[] message, int offset, int length) throws ExceptionA whole binary message.
public default void onPing(WebSocketSession session, byte[] payload, int offset, int length) throws ExceptionA PING arrived.
public default void onPong(WebSocketSession session, byte[] payload, int offset, int length) throws ExceptionA PONG arrived, answering a WebSocketSession.sendPing.
public default void onClose(WebSocketSession session, int code, String reason) throws ExceptionThe connection is finished, for any reason, exactly once per session.
public default void onError(WebSocketSession session, Exception error)Something went wrong: a protocol violation by the peer, an I/O failure, or an exception thrown by one of the callbacks above.
public default String[] getSubprotocols()The subprotocols this endpoint speaks, best first, or null for none.

Method details

onOpen

public abstract void onOpen(WebSocketSession session) throws Exception
The handshake is done and the 101 is on the wire. Sending here is allowed and reaches the client after the handshake, which is the earliest anything can.

Throws

Exception

onText

public abstract void onText(WebSocketSession session, String message) throws Exception
A whole text message, reassembled from however many frames carried it, and already validated as UTF-8.

Throws

Exception

onBinary

public abstract void onBinary(WebSocketSession session, byte[] message, int offset, int length) throws Exception

A whole binary message.

The array is the session’s own reassembly buffer and is valid only until this call returns – the same contract HttpServer.Request carries, and for the same reason: it is what lets a 10MB message arrive without a copy. An endpoint that needs to keep the bytes copies the range it wants.

Throws

Exception

onPing

public default void onPing(WebSocketSession session, byte[] payload, int offset, int length) throws Exception
A PING arrived. The PONG has already been sent. The payload is borrowed.

Throws

Exception

onPong

public default void onPong(WebSocketSession session, byte[] payload, int offset, int length) throws Exception
A PONG arrived, answering a WebSocketSession.sendPing. Borrowed.

Throws

Exception

onClose

public default void onClose(WebSocketSession session, int code, String reason) throws Exception

The connection is finished, for any reason, exactly once per session.

code is the close code, or 1006 when the connection dropped without one – which is normal, not exceptional: a process killed mid-suite, a network that went away, a browser tab closed. reason may be empty and is never null. Sending from here does nothing; the socket is already going.

Throws

Exception

onError

public default void onError(WebSocketSession session, Exception error)

Something went wrong: a protocol violation by the peer, an I/O failure, or an exception thrown by one of the callbacks above.

Reported rather than thrown, because by the time a websocket fails there is nobody left to throw to – the request that started it returned long ago. onClose still follows.

getSubprotocols

public default String[] getSubprotocols()

The subprotocols this endpoint speaks, best first, or null for none.

The SERVER’s order decides, not the client’s. RFC 6455 leaves the choice open, and honouring the client’s order would let a peer select a deprecated protocol over a current one simply by listing it first.