### Complete Echo Server Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioserver.md A full example demonstrating the setup and execution of an echo server using NioTcpServer. It includes session configuration, filter setup, handler implementation, and binding to a port. ```java import org.apache.mina.api.*; import java.net.InetSocketAddress; public class EchoServer { public static void main(String[] args) throws Exception { // Create server IoServer server = new NioTcpServer(); // Configure session defaults IoSessionConfig config = server.getSessionConfig(); config.setReadBufferSize(1024); config.setIdleTimeInMillis(IdleStatus.BOTH_IDLE, 60000); // Set up filters (optional codec) server.setFilters( new LoggingFilter(), new ProtocolCodecFilter(encoder, decoder) ); // Set handler server.setIoHandler(new AbstractIoHandler() { @Override public void sessionOpened(IoSession session) { System.out.println("Client connected: " + session.getRemoteAddress()); } @Override public void messageReceived(IoSession session, Object message) { System.out.println("Received: " + message); session.write("Echo: " + message); } @Override public void sessionClosed(IoSession session) { System.out.println("Client disconnected: " + session.getRemoteAddress()); } @Override public void exceptionCaught(IoSession session, Exception cause) { cause.printStackTrace(); session.close(true); } }); // Bind and start listening server.bind(9090); System.out.println("Server listening on port 9090"); } } ``` -------------------------------- ### Complete Session Configuration Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iosessionconfig.md Demonstrates a comprehensive configuration of an IoSession, including buffer sizes, idle timeouts, socket options, and handler setup. This example shows how to configure a server with specific settings for high-throughput or low-latency scenarios. ```java import org.apache.mina.api.*; public class ConfiguredSession { public static void main(String[] args) throws Exception { IoServer server = new NioTcpServer(); // Get default session configuration IoSessionConfig config = server.getSessionConfig(); // === Buffer Configuration === // Larger buffers for high-throughput scenarios config.setReadBufferSize(65536); // 64KB read buffer config.setSendBufferSize(65536); // 64KB send buffer // === Idle Timeout Configuration === // Detect idle after 5 minutes of inactivity config.setIdleTimeInMillis(IdleStatus.READ_IDLE, 300000); config.setIdleTimeInMillis(IdleStatus.WRITE_IDLE, 300000); // Separate timeout for both-idle config.setIdleTimeInMillis(IdleStatus.BOTH_IDLE, 600000); // 10 min // === Socket Options === // Allow quick restart on same port config.setReuseAddress(true); // Optimize for low latency (interactive) config.setTrafficClass(TrafficClassEnum.IPTOS_LOWDELAY); // 30 second socket timeout config.setTimeout(30000); // === Handler for Idle Sessions === server.setIoHandler(new AbstractIoHandler() { @Override public void sessionIdle(IoSession session, IdleStatus status) { System.out.println("Session " + session.getId() + " idle: " + status); // Close both-idle sessions if (status == IdleStatus.BOTH_IDLE) { session.close(false); } } }); // Bind and start server.bind(9090); System.out.println("Server configured and listening"); } } ``` -------------------------------- ### Basic HTTP Client Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/README.md Demonstrates how to create a basic NioTcpClient, set a handler, connect to a server, send an HTTP GET request, and close the session. ```java public class SimpleClient { public static void main(String[] args) throws Exception { // Create client IoClient client = new NioTcpClient(); // Set handler client.setIoHandler(new AbstractIoHandler() { @Override public void messageReceived(IoSession session, Object message) { if (message instanceof HttpResponse) { HttpResponse response = (HttpResponse) message; System.out.println("Response: " + response.getStatus()); } } }); // Connect SocketAddress serverAddr = new InetSocketAddress("localhost", 8080); IoFuture connectFuture = client.connect(serverAddr); // Wait for connection try { IoSession session = connectFuture.get(5, TimeUnit.SECONDS); // Send HTTP request HttpRequest request = new DefaultHttpRequest(); request.setMethod(HttpMethod.GET); request.setTargetURI("/"); session.write(request); // Wait for response Thread.sleep(1000); // Close session.close(false); } catch (Exception e) { e.printStackTrace(); } } } ``` -------------------------------- ### Example: Get with Timeout for Connection Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuture.md Shows how to use get() with a timeout to attempt a connection. Handles timeouts and connection failures gracefully. ```java IoFuture future = client.connect(address); try { IoSession session = future.get(5, TimeUnit.SECONDS); System.out.println("Connected"); } catch (TimeoutException e) { System.err.println("Connection timed out"); } catch (ExecutionException e) { System.err.println("Connection failed: " + e.getCause()); } ``` -------------------------------- ### Complete HTTP Request Handler Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/httprequest.md This example demonstrates a full implementation of an HTTP request handler, including message reception, request parsing, routing based on method and URI, and response generation. It covers handling GET and POST requests, accessing headers and parameters, and sending appropriate responses like OK or Not Found. ```java public class HttpRequestHandler extends AbstractIoHandler { @Override public void messageReceived(IoSession session, Object message) { if (message instanceof HttpRequest) { handleRequest(session, (HttpRequest) message); } else if (message instanceof HttpContentChunk) { handleContent(session, (HttpContentChunk) message); } } private void handleRequest(IoSession session, HttpRequest request) { String method = request.getMethod().toString(); String uri = request.getTargetURI(); String version = request.getProtocolVersion().toString(); System.out.println(method + " " + uri + " " + version); // Log headers Map headers = request.getHeaders(); for (Map.Entry header : headers.entrySet()) { System.out.println(header.getKey() + ": " + header.getValue()); } // Log parameters Map> params = request.getParameters(); System.out.println("Parameters: " + params); // Route to handler if (request.getMethod() == HttpMethod.GET) { handleGetRequest(session, request); } else if (request.getMethod() == HttpMethod.POST) { handlePostRequest(session, request); } } private void handleGetRequest(IoSession session, HttpRequest request) { String uri = request.getTargetURI(); if (uri.startsWith("/api/users")) { handleUsersRequest(session, request); } else if (uri.startsWith("/api/items")) { handleItemsRequest(session, request); } else { sendNotFound(session, uri); } } private void handlePostRequest(IoSession session, HttpRequest request) { // Handle POST data (received separately in HttpContentChunk) } private void handleUsersRequest(IoSession session, HttpRequest request) { String page = request.getParameter("page"); int pageNum = page != null ? Integer.parseInt(page) : 1; HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); String body = "{\"users\": [], \"page\": " + pageNum + "}"; response.setContent(body.getBytes(StandardCharsets.UTF_8)); session.write(response); } private void handleItemsRequest(IoSession session, HttpRequest request) { List colors = request.getParameters().get("color"); HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); String body = colors != null ? "{\"items\": " + colors + "}" : "{\"items\": []}"; response.setContent(body.getBytes(StandardCharsets.UTF_8)); session.write(response); } private void sendNotFound(IoSession session, String uri) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.NOT_FOUND_404); response.setContent("Not Found: " + uri); session.write(response); } } ``` -------------------------------- ### Example: Blocking Get for Connection Result Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuture.md Demonstrates using the get() method to block until a connection is established and then write data. Handles potential connection failures. ```java IoFuture connectFuture = client.connect(serverAddress); try { IoSession session = connectFuture.get(); // Blocks until connected session.write("Hello"); } catch (ExecutionException e) { System.err.println("Connection failed: " + e.getCause()); } ``` -------------------------------- ### Complete Echo Client Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioclient.md A full example of an EchoClient using NioTcpClient. It configures session defaults, sets up filters, defines an IoHandler, connects to a server, sends a message, and closes the connection. ```java import org.apache.mina.api.*; import java.net.InetSocketAddress; public class EchoClient { public static void main(String[] args) throws Exception { // Create client IoClient client = new NioTcpClient(); // Configure session defaults IoSessionConfig config = client.getSessionConfig(); config.setReadBufferSize(1024); // Set up filters (optional codec) client.setFilters( new LoggingFilter(), new ProtocolCodecFilter(encoder, decoder) ); // Set handler client.setIoHandler(new AbstractIoHandler() { @Override public void sessionOpened(IoSession session) { System.out.println("Connected to server at: " + session.getRemoteAddress()); } @Override public void messageReceived(IoSession session, Object message) { System.out.println("Received from server: " + message); } @Override public void sessionClosed(IoSession session) { System.out.println("Disconnected from server"); } @Override public void exceptionCaught(IoSession session, Exception cause) { cause.printStackTrace(); } }); // Connect to server SocketAddress serverAddress = new InetSocketAddress("localhost", 9090); IoFuture connectFuture = client.connect(serverAddress); // Wait for connection try { IoSession session = connectFuture.get(); System.out.println("Connected successfully"); // Send message session.write("Hello from client"); // Wait for response Thread.sleep(1000); // Close connection session.close(false); } catch (Exception e) { System.err.println("Connection failed: " + e.getMessage()); } } } ``` -------------------------------- ### Example ProtocolDecoder Implementation with State Creation Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md An example implementation of ProtocolDecoder demonstrating the creation of a custom decoder state. ```java public class MyDecoder implements ProtocolDecoder { @Override public MyDecoderState createDecoderState() { return new MyDecoderState(); } } class MyDecoderState { private ByteBuffer buffer = ByteBuffer.allocate(1024); private int lineCount = 0; } ``` -------------------------------- ### Set Byte Order Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iobuffer.md Example demonstrating how to set the byte order to LITTLE_ENDIAN and write an integer. ```java buffer.order(ByteOrder.LITTLE_ENDIAN); buffer.putInt(0x12345678); // Little-endian order ``` -------------------------------- ### finishEncode Implementation Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md An example implementation of the finishEncode method for releasing resources. ```java @Override public void finishEncode() { // Release any held resources } ``` -------------------------------- ### Example: Handling Operation Completion Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuturelistener.md Demonstrates how to check for success or failure and retrieve results or exceptions. ```java @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { IoSession session = future.get(); System.out.println("Connected successfully"); } else { System.err.println("Connection failed: " + future.getException().getMessage()); } } ``` -------------------------------- ### Complete HTTP Response Handler Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/httpresponse.md This example demonstrates a complete HTTP response handler that processes incoming requests and builds appropriate responses based on the URI. ```java public class HttpResponseHandler extends AbstractIoHandler { @Override public void messageReceived(IoSession session, Object message) { if (message instanceof HttpRequest) { HttpRequest request = (HttpRequest) message; HttpResponse response = buildResponse(request); session.write(response); } } private HttpResponse buildResponse(HttpRequest request) { String uri = request.getTargetURI(); if (uri.equals("/health")) { return healthCheckResponse(); } else if (uri.startsWith("/api/")) { return apiResponse(uri); } else { return notFoundResponse(uri); } } private HttpResponse healthCheckResponse() { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); response.setContent("{\"status\": \"healthy\"}"); return response; } private HttpResponse apiResponse(String uri) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); response.setHeader("Cache-Control", "no-cache"); String body = "{\"path\": \"" + uri + "\"}"; response.setContent(body); return response; } private HttpResponse notFoundResponse(String uri) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.NOT_FOUND_404); response.setHeader("Content-Type", "text/html"); response.setContent("

404 Not Found

" + "

Path: " + uri + "

"); return response; } private HttpResponse errorResponse(String errorMsg) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR_500); response.setHeader("Content-Type", "text/plain"); response.setContent("Error: " + errorMsg); return response; } private HttpResponse jsonResponse(String json) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); response.setContent(json); return response; } private HttpResponse redirectResponse(String location) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.FOUND_302); response.setHeader("Location", location); return response; } } ``` -------------------------------- ### StatelessProtocolEncoder Pattern Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md An example of extending StatelessProtocolEncoder for simple message encoding scenarios. ```java public class SimpleEncoder extends StatelessProtocolEncoder { @Override public ByteBuffer encode(MyMessage message) throws ProtocolEncoderException { ByteBuffer buffer = ByteBuffer.allocate(256); buffer.putInt(message.getType()); buffer.put(message.getData()); buffer.flip(); return buffer; } } ``` -------------------------------- ### Complete Server Configuration Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/configuration.md Demonstrates how to configure a MINA TCP server with buffer sizes, idle timeouts, socket options, and a basic handler. ```java import org.apache.mina.api.*; import org.apache.mina.transport.nio.NioTcpServer; public class ConfiguredServer { public static void main(String[] args) throws Exception { // Create server IoServer server = new NioTcpServer(); // Get default session config IoSessionConfig config = server.getSessionConfig(); // Configure buffers config.setReadBufferSize(16384); // 16KB read buffer config.setSendBufferSize(32768); // 32KB send buffer // Configure idle timeouts config.setIdleTimeInMillis(IdleStatus.READ_IDLE, 120000); // 2 minutes config.setIdleTimeInMillis(IdleStatus.WRITE_IDLE, 120000); // 2 minutes config.setIdleTimeInMillis(IdleStatus.BOTH_IDLE, 300000); // 5 minutes // Configure socket options config.setTimeout(10000); // 10 second socket timeout config.setReuseAddress(true); // Reuse address on restart config.setTrafficClass(TrafficClassEnum.IPTOS_LOWDELAY); // Low latency // Set handler server.setIoHandler(new AbstractIoHandler() { @Override public void sessionIdle(IoSession session, IdleStatus status) { System.out.println("Session idle: " + status); if (status == IdleStatus.BOTH_IDLE) { session.close(false); } } }); // Bind server server.bind(9090); System.out.println("Server configured and listening on port 9090"); } } ``` -------------------------------- ### Stateless Protocol Decoder Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md Extend StatelessProtocolDecoder for simple decoders that do not require state management. This example decodes a message from a ByteBuffer. ```java public class SimpleDecoder extends StatelessProtocolDecoder { @Override public MyMessage decode(ByteBuffer input) { if (input.remaining() < HEADER_SIZE) { return null; // Incomplete } int length = input.getInt(); if (input.remaining() < length) { return null; // Incomplete } byte[] payload = new byte[length]; input.get(payload); return new MyMessage(payload); } } ``` -------------------------------- ### Async Connection with Listener Setup Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioclient.md Demonstrates setting up an asynchronous connection and registering a listener to handle the connection outcome. This is useful for non-blocking client operations. ```java IoClient client = new NioTcpClient(); client.setIoHandler(handler); SocketAddress serverAddr = new InetSocketAddress("example.com", 8080); IoFuture future = client.connect(serverAddr); // Register listener for asynchronous notification future.register(new IoFutureListener() { @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { IoSession session = future.get(); // Use the session to send/receive data session.write(someData); } else { Throwable cause = future.getException(); // Handle connection failure System.err.println("Failed to connect: " + cause); } } }); ``` -------------------------------- ### Writing Data Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iobuffer.md Demonstrates allocating an IoBuffer and writing an integer, bytes, and a long. Includes flipping the buffer for reading. ```java IoBuffer buffer = IoBuffer.allocate(1024); buffer.putInt(42); // Write integer buffer.put("Hello".getBytes()); // Write bytes buffer.putLong(System.currentTimeMillis()); // Flip for reading buffer.flip(); // Set limit to position, reset position to 0 ``` -------------------------------- ### Example ProtocolDecoder finishDecode() Implementation Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md An example implementation of finishDecode that checks for incomplete messages and clears the buffer if necessary. ```java @Override public void finishDecode(MyDecoderState context) { // Check for incomplete message if (context.buffer.position() > 0) { System.err.println("Incomplete message at session close"); context.buffer.clear(); } } ``` -------------------------------- ### Example ProtocolDecoder decode() Implementation Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md An example implementation of the decode method that appends input to an accumulated buffer and extracts complete lines based on newline characters. ```java @Override public String decode(ByteBuffer input, MyDecoderState context) { // Append to accumulated buffer context.buffer.put(input); // Try to find a complete line int newlinePos = findNewline(context.buffer); if (newlinePos == -1) { return null; // Incomplete, wait for more data } // Extract complete line byte[] line = new byte[newlinePos]; context.buffer.get(line); context.lineCount++; return new String(line, StandardCharsets.UTF_8); } ``` -------------------------------- ### Get Installed Filters Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioservice.md Retrieves an array of all IoFilters currently applied to the service. Useful for inspection or debugging. ```java IoFilter[] filters = service.getFilters(); for (IoFilter filter : filters) { System.out.println("Filter: " + filter.getClass().getName()); } ``` -------------------------------- ### Example: Listener for Connection Completion Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuture.md Demonstrates registering a listener to handle connection completion asynchronously. The listener checks for success or failure and performs actions accordingly. ```java IoFuture future = client.connect(serverAddress); future.register(new IoFutureListener() { @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { IoSession session = future.get(); System.out.println("Connected!"); session.write("Hello"); } else { System.err.println("Connection failed: " + future.getException().getMessage()); } } }); ``` -------------------------------- ### Reading Data Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iobuffer.md Shows how to read an integer, bytes, and a long from an IoBuffer after it has been flipped or received data. ```java // After flip() or after receiving data int value = buffer.getInt(); byte[] text = new byte[5]; buffer.get(text); long timestamp = buffer.getLong(); ``` -------------------------------- ### StringEncoder Implementation Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md An example implementation of ProtocolEncoder for encoding String messages into a ByteBuffer with a length prefix. ```java public class StringEncoder implements ProtocolEncoder { @Override public ByteBuffer encode(String message) { byte[] bytes = message.getBytes(StandardCharsets.UTF_8); ByteBuffer buffer = ByteBuffer.allocate(4 + bytes.length); buffer.putInt(bytes.length); buffer.put(bytes); buffer.flip(); return buffer; } } ``` -------------------------------- ### Filter Chain Control Examples Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofilter.md Demonstrates how to pass messages down the filter chain using ReadFilterChainController and WriteFilterChainController. ```java // In messageReceived controller.callNextFilter(session, transformedMessage); // In messageWriting controller.callNextFilter(session, transformedRequest); ``` -------------------------------- ### MyMessageEncoder Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md An example ProtocolEncoder for a custom MyMessage type, encoding its version, ID, and payload. ```java public class MyMessageEncoder implements ProtocolEncoder { @Override public ByteBuffer encode(MyMessage message) throws ProtocolEncoderException { if (message == null) { throw new ProtocolEncoderException("Message cannot be null"); } ByteBuffer buffer = ByteBuffer.allocate(64); // Encode header buffer.put(message.getVersion()); buffer.putInt(message.getId()); // Encode payload byte[] payload = message.getPayload(); buffer.putInt(payload.length); buffer.put(payload); buffer.flip(); return buffer; } @Override public void finishEncode() { } } ``` -------------------------------- ### Codec Filter Example for messageReceived Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofilter.md Example of a codec filter decoding a ByteBuffer into a custom message before passing it down the chain. ```java @Override public void messageReceived(IoSession session, Object message, ReadFilterChainController controller) { ByteBuffer buffer = (ByteBuffer) message; // Decode buffer to application message MyMessage decoded = decoder.decode(buffer); if (decoded != null) { controller.callNextFilter(session, decoded); } } ``` -------------------------------- ### LengthPrefixedStringEncoder Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md A complete example of a ProtocolEncoder for String messages, including charset configuration and error handling. ```java public class LengthPrefixedStringEncoder implements ProtocolEncoder { private final Charset charset; public LengthPrefixedStringEncoder() { this(StandardCharsets.UTF_8); } public LengthPrefixedStringEncoder(Charset charset) { this.charset = charset; } @Override public ByteBuffer encode(String message) throws ProtocolEncoderException { if (message == null) { throw new ProtocolEncoderException("Message cannot be null"); } try { byte[] bytes = message.getBytes(charset); // Create buffer with 4-byte length prefix + data ByteBuffer buffer = ByteBuffer.allocate(4 + bytes.length); buffer.putInt(bytes.length); buffer.put(bytes); buffer.flip(); return buffer; } catch (Exception e) { throw new ProtocolEncoderException("Failed to encode: " + e, e); } } @Override public void finishEncode() { // No resources to clean up } } ``` -------------------------------- ### Handle Connection Events Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioclient.md Example of handling connection events and sending data using an IoFuture and IoFutureListener. This demonstrates how to react to a successful connection or a failure. ```java IoClient client = /* create client */; SocketAddress serverAddress = new InetSocketAddress("localhost", 9090); IoFuture connectFuture = client.connect(serverAddress); connectFuture.register(new IoFutureListener() { @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { IoSession session = future.get(); System.out.println("Connected to server"); session.write("Hello Server"); } else { System.err.println("Connection failed: " + future.getException().getMessage()); } } }); ``` -------------------------------- ### Write Completion Handler Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuturelistener.md A listener to handle the completion of a write operation, checking for success or failure. ```java IoSession session = /* active session */; IoFuture writeFuture = session.writeWithFuture("Hello"); writeFuture.register(new IoFutureListener() { @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { System.out.println("Message sent successfully"); } else { System.err.println("Send failed: " + future.getException().getMessage()); session.close(true); } } }); ``` -------------------------------- ### Integrate Decoder with ProtocolCodecFilter Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md Example of integrating a custom encoder and decoder with the ProtocolCodecFilter and setting it on the server. ```java ProtocolEncoder encoder = /* ... */; ProtocolDecoder decoder = /* ... */; IoFilter codecFilter = new ProtocolCodecFilter(encoder, decoder); server.setFilters(codecFilter); ``` -------------------------------- ### Codec Filter Example for messageWriting Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofilter.md Example of a codec filter encoding a custom message into a ByteBuffer before passing the encoded request down the chain. ```java @Override public void messageWriting(IoSession session, WriteRequest message, WriteFilterChainController controller) { Object obj = message.getMessage(); // Encode application message to ByteBuffer ByteBuffer encoded = encoder.encode(obj); WriteRequest encodedRequest = new WriteRequest(encoded); controller.callNextFilter(session, encodedRequest); } ``` -------------------------------- ### Handle Idle Session Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iosessionconfig.md An example handler implementation to close a session when it becomes idle for a specified duration. ```java @Override public void sessionIdle(IoSession session, IdleStatus status) { if (status == IdleStatus.BOTH_IDLE) { System.out.println("Session idle for 2 minutes, closing"); session.close(false); } } ``` -------------------------------- ### Create Empty IoBuffer Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iobuffer.md Creates a new, empty IoBuffer instance. Use when starting with an empty buffer and adding data later. ```java IoBuffer buffer = IoBuffer.newInstance(); ``` -------------------------------- ### Buffer Accumulation Decoder Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md Implement ProtocolDecoder to accumulate partial messages in a BufferState. This FixedLengthDecoder handles messages of a predefined size. ```java public class FixedLengthDecoder implements ProtocolDecoder { private final int messageSize; public FixedLengthDecoder(int messageSize) { this.messageSize = messageSize; } @Override public BufferState createDecoderState() { return new BufferState(messageSize); } @Override public byte[] decode(ByteBuffer input, BufferState state) { state.accumulator.put(input); if (state.accumulator.position() >= messageSize) { byte[] message = new byte[messageSize]; state.accumulator.flip(); state.accumulator.get(message); state.accumulator.clear(); return message; } return null; } @Override public void finishDecode(BufferState state) { // Clear any partial data state.accumulator.clear(); } } class BufferState { ByteBuffer accumulator; BufferState(int capacity) { this.accumulator = ByteBuffer.allocate(capacity); } } ``` -------------------------------- ### Complete Line-Delimited Decoder Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocoldecoder.md A full implementation of a ProtocolDecoder that handles line-delimited messages, including state management and error handling for incomplete lines. ```java public class LineDecoder implements ProtocolDecoder { private static final byte NEWLINE = '\n'; @Override public LineDecoderState createDecoderState() { return new LineDecoderState(); } @Override public String decode(ByteBuffer input, LineDecoderState state) { // Add new data to accumulated buffer state.buffer.put(input); // Look for newline byte[] data = state.buffer.array(); int limit = state.buffer.position(); for (int i = 0; i < limit; i++) { if (data[i] == NEWLINE) { // Found complete line String line = new String(data, 0, i); // Reset for next message state.buffer.clear(); state.buffer.put(data, i + 1, limit - i - 1); return line; } } // Incomplete message return null; } @Override public void finishDecode(LineDecoderState state) { if (state.buffer.position() > 0) { throw new IllegalStateException("Incomplete line received"); } } } class LineDecoderState { ByteBuffer buffer = ByteBuffer.allocate(8192); } ``` -------------------------------- ### Basic HTTP Request Routing in Java Source: https://github.com/apache/mina/blob/trunk/_autodocs/endpoints.md Implement path and method-based routing for incoming HTTP requests. Handles GET, POST, PUT, DELETE, and dynamic path parameters. Remove query strings before matching paths. ```java public class HttpRequestRouter extends AbstractIoHandler { @Override public void messageReceived(IoSession session, Object message) { if (message instanceof HttpRequest) { HttpRequest request = (HttpRequest) message; routeRequest(session, request); } else if (message instanceof HttpContentChunk) { handleContent(session, (HttpContentChunk) message); } } private void routeRequest(IoSession session, HttpRequest request) { String uri = request.getTargetURI(); HttpMethod method = request.getMethod(); // Remove query string for path matching String path = uri.split("\\?")[0]; if (path.equals("/health") && method == HttpMethod.GET) { handleHealthCheck(session, request); } else if (path.equals("/api/users") && method == HttpMethod.GET) { handleGetUsers(session, request); } else if (path.equals("/api/users") && method == HttpMethod.POST) { handleCreateUser(session, request); } else if (path.matches("^/api/users/\\d+$") && method == HttpMethod.GET) { handleGetUser(session, request); } else if (path.matches("^/api/users/\\d+$") && method == HttpMethod.PUT) { handleUpdateUser(session, request); } else if (path.matches("^/api/users/\\d+$") && method == HttpMethod.DELETE) { handleDeleteUser(session, request); } else { handleNotFound(session, request); } } private void handleHealthCheck(IoSession session, HttpRequest request) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); response.setContent("{\"status\": \"healthy\"}"); session.write(response); } private void handleGetUsers(IoSession session, HttpRequest request) { String page = request.getParameter("page"); int pageNum = page != null ? Integer.parseInt(page) : 1; HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); String json = String.format( "{\"users\": [], \"page\": %d, \"total\": 0}", pageNum ); response.setContent(json); session.write(response); } private void handleCreateUser(IoSession session, HttpRequest request) { // POST request - content will arrive in separate HttpContentChunk // Store request in session attribute for later processing AttributeKey KEY = new AttributeKey<>( HttpRequest.class, "pending_request"); session.setAttribute(KEY, request); } private void handleGetUser(IoSession session, HttpRequest request) { String userId = extractPathParam(request.getTargetURI(), "^/api/users/(\\d+)$ ", 1); HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.OK_200); response.setHeader("Content-Type", "application/json"); String json = "{\"id\": " + userId + ", \"name\": \"User\"}"; response.setContent(json); session.write(response); } private void handleUpdateUser(IoSession session, HttpRequest request) { // Update user - content in HttpContentChunk AttributeKey KEY = new AttributeKey<>( HttpRequest.class, "pending_request"); session.setAttribute(KEY, request); } private void handleDeleteUser(IoSession session, HttpRequest request) { String userId = extractPathParam(request.getTargetURI(), "^/api/users/(\\d+)$ ", 1); HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.NO_CONTENT_204); // 204 has no content session.write(response); } private void handleNotFound(IoSession session, HttpRequest request) { HttpResponse response = new DefaultHttpResponse(); response.setStatus(HttpStatus.NOT_FOUND_404); response.setHeader("Content-Type", "text/html"); String html = "

404 Not Found

" + "

Path: " + request.getTargetURI() + "

" + ""; response.setContent(html); session.write(response); } private String extractPathParam(String uri, String pattern, int group) { Pattern p = Pattern.compile(pattern); Matcher m = p.matcher(uri.split("\\?")[0]); return m.matches() ? m.group(group) : null; } ``` -------------------------------- ### Using Valid Ports for Binding Source: https://github.com/apache/mina/blob/trunk/_autodocs/errors.md Shows correct and incorrect examples of port numbers when binding a server. Ports must be within the valid range of 1 to 65535. ```java // WRONG server.bind(-1); // Negative port server.bind(100000); // Port > 65535 // CORRECT server.bind(9090); // Valid port in range 1-65535 ``` -------------------------------- ### Session Close Handler Example Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iofuturelistener.md A listener to handle the completion of a session close operation, reporting success or errors. ```java IoFuture closeFuture = session.close(false); // Graceful close closeFuture.register(new IoFutureListener() { @Override public void operationComplete(IoFuture future) { if (future.isSuccess()) { System.out.println("Session closed"); } else { System.err.println("Error during close: " + future.getException().getMessage()); } } }); ``` -------------------------------- ### Handle Session Handshake Start Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iohandler.md This method is invoked when a secured session's handshake begins. It can be called multiple times for rehandshakes. ```java void handshakeStarted(IoSession session) ``` ```java @Override public void handshakeStarted(IoSession session) { System.out.println("SSL/TLS handshake started"); } ``` -------------------------------- ### Set common and security headers for HTTP response Source: https://github.com/apache/mina/blob/trunk/_autodocs/endpoints.md This example demonstrates how to set various headers on an HTTP response, including status, content type, length, caching, CORS, and security-related headers. ```java HttpResponse response = new DefaultHttpResponse(); // Set response status response.setStatus(HttpStatus.OK_200); // Set common headers response.setHeader("Content-Type", "application/json; charset=utf-8"); response.setHeader("Content-Length", String.valueOf(content.length)); response.setHeader("Cache-Control", "no-cache"); response.setHeader("Access-Control-Allow-Origin", "*"); // Set security headers response.setHeader("X-Content-Type-Options", "nosniff"); response.setHeader("X-Frame-Options", "DENY"); response.setHeader("Strict-Transport-Security", "max-age=31536000"); session.write(response); ``` -------------------------------- ### Get All Parameters Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/httprequest.md Retrieves a read-only map of all query parameters. Keys are parameter names, and values are lists of strings to support multi-valued parameters. ```java Map> params = request.getParameters(); // Get single-valued parameter List pageValues = params.get("page"); String page = pageValues != null ? pageValues.get(0) : "1"; // Get multi-valued parameter List colors = params.get("color"); for (String color : colors) { System.out.println("Color: " + color); } ``` -------------------------------- ### Set up an HTTP Server Source: https://github.com/apache/mina/blob/trunk/_autodocs/endpoints.md This snippet demonstrates how to initialize and configure an NioTcpServer, set session properties, and bind it to a specific port. ```java import org.apache.mina.api.*; import org.apache.mina.filter.codec.ProtocolCodecFilter; import org.apache.mina.http.HttpServerDecoder; import org.apache.mina.http.HttpServerEncoder; public class HttpServer { public static void main(String[] args) throws Exception { // Create server IoServer server = new NioTcpServer(); // Configure session IoSessionConfig config = server.getSessionConfig(); config.setReadBufferSize(8192); config.setIdleTimeInMillis(IdleStatus.BOTH_IDLE, 60000); // Set up HTTP codec HttpServerDecoder httpDecoder = new HttpServerDecoder(); HttpServerEncoder httpEncoder = new HttpServerEncoder(); IoFilter codecFilter = new ProtocolCodecFilter(httpEncoder, httpDecoder); // Optional: add logging filter LoggingFilter loggingFilter = new LoggingFilter(LogLevel.DEBUG); // Set filters server.setFilters(codecFilter, loggingFilter); // Set handler server.setIoHandler(new HttpRequestRouter()); // Start server server.bind(8080); System.out.println("HTTP Server listening on port 8080"); } } ``` -------------------------------- ### Catch ConfigurationException Source: https://github.com/apache/mina/blob/trunk/_autodocs/errors.md Catch this exception to handle specific errors related to invalid service configuration in MINA. This is useful for debugging setup issues. ```java try { server.setFilters(/* invalid filter */); server.bind(9090); } catch (ConfigurationException e) { System.err.println("Configuration error: " + e.getMessage()); } ``` -------------------------------- ### Route requests by HTTP method Source: https://github.com/apache/mina/blob/trunk/_autodocs/endpoints.md This pattern allows for different actions based on the HTTP method (GET, POST, PUT, DELETE) used in the request. ```java HttpMethod method = request.getMethod(); if (method == HttpMethod.GET) { // Retrieve } else if (method == HttpMethod.POST) { // Create } else if (method == HttpMethod.PUT) { // Update } else if (method == HttpMethod.DELETE) { // Delete } ``` -------------------------------- ### Implement Custom Protocol Decoder and Encoder Source: https://github.com/apache/mina/blob/trunk/_autodocs/README.md Provides Java examples for creating a custom message decoder and encoder using MINA's protocol interfaces. The decoder handles incoming byte buffers, while the encoder transforms messages into byte buffers. ```java public class MyDecoder implements ProtocolDecoder { @Override public MyDecoderState createDecoderState() { return new MyDecoderState(); } @Override public MyMessage decode(ByteBuffer input, MyDecoderState state) { // Decode logic return null; // null if incomplete } @Override public void finishDecode(MyDecoderState state) { // Cleanup } } public class MyEncoder implements ProtocolEncoder { @Override public ByteBuffer encode(MyMessage message) throws ProtocolEncoderException { // Encode logic return ByteBuffer.wrap(data); } @Override public void finishEncode() { // Cleanup } } ``` -------------------------------- ### Write Message with Future Tracking Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/iosession.md Use writeWithFuture to send a message and get an IoFuture to track the completion of the write operation. Register a listener to handle the operation's outcome. ```java IoFuture writeWithFuture(Object message) ``` ```java String msg = "Hello"; IoFuture writeFuture = session.writeWithFuture(msg); writeFuture.register(new IoFutureListener() { public void operationComplete(IoFuture future) { System.out.println("Write complete"); } }); ``` -------------------------------- ### Route requests by path prefix Source: https://github.com/apache/mina/blob/trunk/_autodocs/endpoints.md Use this pattern to handle all requests that start with a specific URL segment, useful for API versioning or grouping related endpoints. ```java if (uri.startsWith("/api/")) { // Handle API request } ``` -------------------------------- ### Setting IoHandler Before Binding Source: https://github.com/apache/mina/blob/trunk/_autodocs/errors.md Illustrates the correct way to initialize an IoServer by setting the IoHandler before binding to a port. Failure to do so can result in exceptions. ```java // WRONG IoServer server = new NioTcpServer(); server.bind(9090); // No handler set! // CORRECT IoServer server = new NioTcpServer(); server.setIoHandler(myHandler); // Set handler first server.bind(9090); ``` -------------------------------- ### Recommended Production Settings: Memory-Constrained Source: https://github.com/apache/mina/blob/trunk/_autodocs/configuration.md Offers `IoSessionConfig` recommendations for environments with limited memory resources. ```java // For memory-constrained environments config.setReadBufferSize(4096); // 4KB config.setSendBufferSize(4096); // 4KB config.setIdleTimeInMillis(IdleStatus.BOTH_IDLE, 60000); // 1 min ``` -------------------------------- ### CompressedEncoder Implementation Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/protocolencoder.md An example implementation of ProtocolEncoder that compresses string messages before encoding. It includes a magic byte, original size, compressed size, and the compressed data. ```java public class CompressedEncoder implements ProtocolEncoder { private static final byte MAGIC = 0x42; @Override public ByteBuffer encode(String message) throws ProtocolEncoderException { try { byte[] original = message.getBytes(StandardCharsets.UTF_8); byte[] compressed = compress(original); ByteBuffer buffer = ByteBuffer.allocate(1 + 4 + 4 + compressed.length); buffer.put(MAGIC); // Magic byte buffer.putInt(original.length); // Original size buffer.putInt(compressed.length); // Compressed size buffer.put(compressed); // Compressed data buffer.flip(); return buffer; } catch (Exception e) { throw new ProtocolEncoderException("Compression failed", e); } } private byte[] compress(byte[] data) throws IOException { // Use Java compression, gzip, etc. return data; // Simplified } @Override public void finishEncode() { } } ``` -------------------------------- ### Configuration Timing: Correct vs. Incorrect Source: https://github.com/apache/mina/blob/trunk/_autodocs/configuration.md Illustrates the correct timing for applying session configurations. Settings must be applied before binding the server to take effect on new connections. ```java // CORRECT IoServer server = new NioTcpServer(); server.getSessionConfig().setReadBufferSize(1024); server.bind(9090); // WRONG - Configuration after bind has no effect on existing connections server.bind(9090); server.getSessionConfig().setReadBufferSize(1024); // Too late! ``` -------------------------------- ### Safe Decoding with Exception Handling Source: https://github.com/apache/mina/blob/trunk/_autodocs/errors.md Implement a ProtocolDecoder that safely handles potential exceptions during the decoding process, such as BufferUnderflowException or RuntimeExceptions. This example ensures that decoding errors are wrapped in ProtocolDecoderException. ```java public class SafeDecoder implements ProtocolDecoder { @Override public Message decode(ByteBuffer input, DecoderState state) throws ProtocolDecoderException { try { if (input.remaining() < MIN_SIZE) { return null; // Incomplete message } // Validate data validateHeader(input); // Decode return decodeMessage(input, state); } catch (BufferUnderflowException e) { // This shouldn't happen with proper checks, but be safe throw new ProtocolDecoderException("Buffer underflow", e); } catch (RuntimeException e) { throw new ProtocolDecoderException("Decoding error: " + e, e); } } private void validateHeader(ByteBuffer input) throws ProtocolDecoderException { int magic = input.getInt(input.position()); if (magic != MAGIC_NUMBER) { throw new ProtocolDecoderException( "Invalid magic: expected 0x" + Integer.toHexString(MAGIC_NUMBER) + ", got 0x" + Integer.toHexString(magic)); } } } ``` -------------------------------- ### Recommended Production Settings: Bulk Data Transfer Source: https://github.com/apache/mina/blob/trunk/_autodocs/configuration.md Suggests `IoSessionConfig` settings optimized for transferring large amounts of data efficiently. ```java // For bulk data transfer config.setReadBufferSize(262144); // 256KB config.setSendBufferSize(262144); // 256KB config.setTrafficClass(TrafficClassEnum.IPTOS_THROUGHPUT); ``` -------------------------------- ### Configuring Filters Before Binding Source: https://github.com/apache/mina/blob/trunk/_autodocs/errors.md Demonstrates the correct order for setting filters and binding the server. Filters must be set before the server is bound to take effect. ```java // WRONG server.bind(9090); server.setFilters(newFilters); // Too late! // CORRECT server.setFilters(newFilters); server.bind(9090); ``` -------------------------------- ### Blocking Connect to Server Source: https://github.com/apache/mina/blob/trunk/_autodocs/api-reference/ioclient.md Demonstrates how to establish a blocking connection to a server using NioTcpClient. It includes setting up the client, initiating the connection, waiting for it to complete with a timeout, sending data, and closing the session. Proper error handling for timeouts and connection failures is shown. ```java IoClient client = new NioTcpClient(); client.setIoHandler(handler); SocketAddress serverAddr = new InetSocketAddress("example.com", 8080); IoFuture future = client.connect(serverAddr); try { // Wait up to 5 seconds for connection IoSession session = future.get(5, TimeUnit.SECONDS); // Send data session.write("Hello"); // Close session session.close(false).await(); } catch (TimeoutException e) { System.err.println("Connection timed out"); } catch (ExecutionException e) { System.err.println("Connection failed: " + e.getCause()); } ```