-
Notifications
You must be signed in to change notification settings - Fork 0
Core Abstractions
The foundation of JSI rests on four fundamental abstractions: Server, Client, Request, and Response. These interfaces define the contract for all server-client communication, regardless of protocol or transport mechanism.
┌──────────┐ ┌──────────┐
│ Client │────── Request ────►│ Server │
│ │◄───── Response ────│ │
└──────────┘ └──────────┘
▲ ▲
│ │
ConnectionClient ConnectionServer
(TCP transport) (TCP transport)
│ │
DatabaseClient HttpServer
(database queries) (HTTP protocol)
These abstractions create a protocol-agnostic framework where the same patterns work for HTTP, databases, game servers, or any custom protocol.
File: Server.java
The Server class is the purest abstraction in JSI. It defines what any server must do, with zero assumptions about transport or protocol.
package jsi;
public abstract class Server {
/**
* Start the server.
*/
public abstract void start();
/**
* Hook method called before the server starts.
*/
protected void onBeforeStart() {}
/**
* Hook method called after the server has started.
*/
protected void onServerStarted() {}
/**
* Handle a request and generate a response.
*/
public abstract Response handleRequest(Request request);
}-
Lifecycle Management:
start()method defines when/how server begins operation -
Hook Points:
onBeforeStart()andonServerStarted()allow subclasses to inject custom behavior -
Request Handling:
handleRequest()is the core business logic entry point
The Server class deliberately avoids:
- Port specification (not all servers use ports - e.g., message queue consumers)
- Socket management (not all servers use sockets - e.g., in-process servers)
- Threading model (could be single-threaded, thread-per-request, async)
- Protocol details (HTTP, TCP, UDP, custom binary protocols)
This minimalism enables maximum flexibility in how servers are implemented.
// TCP-based server
public class ConnectionServer extends Server {
// Adds: port, ServerSocket, thread-per-client
}
// HTTP-specific server
public class HttpServer extends ConnectionServer {
// Adds: HTTP parsing, routing, response formatting
}
// Custom UDP server
public class UdpChatServer extends Server {
// Completely custom implementation
}The hook methods demonstrate the Template Method Pattern:
public void start() {
onBeforeStart(); // Hook: Initialize resources
// ... start server logic ...
onServerStarted(); // Hook: Log, register with discovery service, etc.
}Example usage:
public class LoggingHttpServer extends HttpServer {
@Override
protected void onBeforeStart() {
System.out.println("Initializing routes...");
// Load configuration, connect to databases, etc.
}
@Override
protected void onServerStarted() {
System.out.println("Server ready on port " + getPort());
// Send notification, update service registry, etc.
}
}File: Client.java
The Client class is the minimal abstraction for entities that communicate with servers.
package jsi;
public abstract class Client {
// Currently minimal - serves as marker for client implementations
}The current Client class is intentionally minimal because client behavior varies dramatically:
- Blocking vs. non-blocking communication
- Connection pooling strategies
- Request multiplexing (HTTP/2, database connection reuse)
Rather than forcing a specific pattern, JSI provides concrete implementations:
File: ConnectionClient.java
public abstract class ConnectionClient extends Client {
private String host;
private int port;
public ConnectionClient(String host, int port) {
this.host = host;
this.port = port;
}
public Response getResponse(Request request) {
// 1. Open TCP socket to host:port
// 2. Serialize and send request
// 3. Read and parse response
// 4. Close socket
return parseResponse(responseString);
}
protected String serializeRequest(Request request) {
return request.toString();
}
public abstract Response parseResponse(String input);
}Key characteristics:
- One request per connection: Simple but inefficient for high-volume scenarios
- Synchronous: Blocks until response received
- Protocol-agnostic: Works with any TCP-based protocol
File: DatabaseClient.java
public abstract class DatabaseClient extends ConnectionClient {
public DatabaseClient(String host, int port) {
super(host, port);
}
@Override
public abstract QueryResult getResponse(Request query);
public QueryResult executeQuery(Query query) {
return getResponse(query);
}
}Adds database-specific semantics (query execution) on top of TCP transport.
File: Request.java
Represents any message sent from client to server.
package jsi;
/**
* Abstract class representing a generic request.
*/
public interface Request {
/**
* Serialize the request into a string format.
*/
public abstract String serialize();
}The Request interface defines only what's universal: the ability to serialize into a transmittable format. Everything else (headers, parameters, body) is protocol-specific.
File: connection/http/HttpRequest.java
public class HttpRequest implements Request {
private String path;
private HttpRequestType requestType; // GET, POST, etc.
private HttpRequestParameter[] parameters;
private HttpRequestHeader[] headers;
public String getPath() { return path; }
public Object getParameter(String name) {
// Extract query parameter by name
}
@Override
public String serialize() {
// Convert to HTTP format:
// GET /path?key=value HTTP/1.1
// Header: value
// ...
}
}Parsing example:
String rawRequest = "GET /users?id=123 HTTP/1.1\r\nHost: localhost\r\n\r\n";
HttpRequest request = new HttpRequest(rawRequest);
String path = request.getPath(); // "/users"
String id = request.getParameter("id"); // "123"File: connection/database/query/Query.java
public abstract class Query implements Request {
private String rawQuery;
public abstract QueryType getQueryType(); // SELECT, INSERT, etc.
public abstract String getTargetCollection(); // Table name
public abstract List<Field> getAffectedFields(); // Columns
public abstract QueryCondition getCondition(); // WHERE clause
@Override
public String serialize() {
return rawQuery; // Original SQL string
}
}Usage example:
Query query = new MySqlQuery("SELECT * FROM users WHERE id = 123");
QueryType type = query.getQueryType(); // SELECT
String table = query.getTargetCollection(); // "users"
QueryCondition condition = query.getCondition(); // id = 123File: Response.java
Represents any message sent from server back to client.
package jsi;
/**
* Abstract class representing a generic response.
*/
public interface Response {
/**
* Serialize the response to a string format suitable for transmission.
*/
public String serialize();
}File: connection/http/HttpResponse.java
public class HttpResponse implements Response {
private ResponseType responseType; // 200 OK, 404 NOT FOUND, etc.
private ResponseHeader[] headers;
private ResponseBody body;
@Override
public String serialize() {
// Converts to HTTP format:
// HTTP/1.1 200 OK
// Content-Type: text/html
// Content-Length: 123
//
// <html>...</html>
}
}Response components:
// Status line
ResponseType responseType = HttpResponseType.OK; // "200 OK"
// Headers
ResponseHeader[] headers = {
new HttpResponseHeader("Content-Type", "application/json"),
new HttpResponseHeader("Cache-Control", "no-cache")
};
// Body
ResponseBody body = new HttpResponseBody("{\"status\": \"success\"}");
HttpResponse response = new HttpResponse(responseType, headers, body);File: connection/database/query/QueryResult.java
public class QueryResult implements Response {
private boolean success;
private String message;
private List<List<Field>> data; // Rows of data
@Override
public String serialize() {
// Serialize result set to string format
}
}Example usage:
QueryResult result = databaseEngine.execute(query);
if (result.isSuccess()) {
List<List<Field>> rows = result.getData();
for (List<Field> row : rows) {
String name = row.get(1).getValue(); // Get name column
}
}┌─────────────────────────────────────────────────────────────────┐
│ CLIENT SIDE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 1. Create Request │
│ HttpRequest req = new HttpRequest(GET, "/users", params) │
│ │
│ 2. Serialize Request │
│ String serialized = req.serialize() │
│ → "GET /users HTTP/1.1..." │
│ │
│ 3. Send over Network │
│ socket.send(serialized) │
│ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ SERVER SIDE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 4. Receive Raw Data │
│ String rawRequest = socket.receive() │
│ │
│ 5. Parse Request │
│ Request req = parseRequest(rawRequest) │
│ │
│ 6. Handle Request (Business Logic) │
│ Response resp = handleRequest(req) │
│ │
│ 7. Serialize Response │
│ String serialized = resp.serialize() │
│ → "HTTP/1.1 200 OK..." │
│ │
│ 8. Send Response │
│ socket.send(serialized) │
│ │
└─────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ CLIENT SIDE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ 9. Receive Response │
│ String rawResponse = socket.receive() │
│ │
│ 10. Parse Response │
│ Response resp = parseResponse(rawResponse) │
│ │
│ 11. Use Response Data │
│ String body = resp.getBody().getContent() │
│ │
└─────────────────────────────────────────────────────────────────┘
Client code:
// Create client
ConnectionClient client = new HttpClient("localhost", 8080);
// Create request
HttpRequest request = new HttpRequest(
HttpRequestType.GET,
new HttpRequestParameter[] {
new HttpRequestParameter("id", "123")
},
null // No custom headers
);
// Send and receive
HttpResponse response = client.getResponse(request);
// Use response
if (response.getResponseType() == HttpResponseType.OK) {
String content = response.getBody().getContent();
System.out.println("Response: " + content);
}Server code:
public class MyServer extends HttpServer {
@Override
public HttpResponse handleRequest(Request request) {
// Parse request (already done by HttpServer)
HttpRequest httpReq = (HttpRequest) request;
String id = httpReq.getParameter("id");
// Business logic
String userData = fetchUserFromDatabase(id);
// Create response
return new HttpResponse(
HttpResponseType.OK,
new ResponseHeader[] {
new HttpResponseHeader("Content-Type", "application/json")
},
new HttpResponseBody(userData)
);
}
}The same abstractions work for any protocol:
// HTTP
Request httpReq = new HttpRequest(GET, "/path", params);
Response httpResp = server.handleRequest(httpReq);
// Database
Request dbReq = new MySqlQuery("SELECT * FROM users");
Response dbResp = server.handleRequest(dbReq);
// Custom protocol
Request customReq = new GameCommandRequest("MOVE", x, y);
Response customResp = server.handleRequest(customReq);The serialize() method defines the wire format - how data travels over the network:
// HTTP serialization
GET /users?id=123 HTTP/1.1
Host: localhost
// Database query serialization
SELECT * FROM users WHERE id = 123
// Custom binary serialization
[0x01][0x00][0x7B][...] // Your custom formatAdd functionality by composing request/response objects:
// Request with authentication
public class AuthenticatedHttpRequest extends HttpRequest {
private String authToken;
@Override
public String serialize() {
return super.serialize() + "\nAuthorization: Bearer " + authToken;
}
}
// Response with caching
public class CachedHttpResponse extends HttpResponse {
@Override
public String serialize() {
String base = super.serialize();
return base.replace("\r\n\r\n",
"\r\nCache-Control: max-age=3600\r\n\r\n");
}
}- Architecture Overview - How these abstractions fit into the layered model
- ConnectionServer - TCP implementation of Server
- HTTP Server - HTTP implementation of Request/Response
- Database Server - Database implementation of Request/Response
Next: Dive into ConnectionServer to see how TCP transport is built on these abstractions, or explore HTTP Server for a complete protocol implementation.
JSI - Java Server Interface | Educational Server Framework | Zero Dependencies
Home • Getting Started • Architecture • Source Code
Made for learning | Report Issues • Discussions
Last updated: December 2025 | JSI v1.0
HTTP Development
Database Development
Custom Protocols