Refactor response classes to use RequestContext instead of SessionId + request id #220

Merged
lars.winzer merged 5 commits from feat/34-make-response-use-requestcontext into main 2026-03-31 20:50:08 +02:00
5 changed files with 26 additions and 36 deletions
@@ -1,23 +1,20 @@
package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response; package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId;
/** Response representing an error outcome for a client's request. */ /** Response representing an error outcome for a client's request. */
public class ErrorResponse extends Response { public class ErrorResponse extends Response {
/** /**
* Construct an error response with a code and message. * Construct an error response with a code and message.
* *
* @param sessionId the target session id * @param context the RequestContext of the request
* @param requestId the originating request id
* @param errorCode a short error code identifying the failure * @param errorCode a short error code identifying the failure
* @param errorMessage a human readable error message * @param errorMessage a human readable error message
*/ */
public ErrorResponse( public ErrorResponse(RequestContext context, String errorCode, String errorMessage) {
SessionId sessionId, int requestId, String errorCode, String errorMessage) {
super( super(
sessionId, context,
requestId,
ResponseBody.builder().param("CODE", errorCode).param("MSG", errorMessage).build()); ResponseBody.builder().param("CODE", errorCode).param("MSG", errorMessage).build());
} }
@@ -1,7 +1,7 @@
package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response; package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId;
/** /**
* A simple success response with an empty body. * A simple success response with an empty body.
@@ -12,10 +12,9 @@ public class OkResponse extends SuccessResponse {
/** /**
* Create a minimal successful response (no body content). * Create a minimal successful response (no body content).
* *
* @param sessionId the target session id * @param context the RequestContext of the request
* @param requestId the originating request id
*/ */
public OkResponse(SessionId sessionId, int requestId) { public OkResponse(RequestContext context) {
super(sessionId, requestId, ResponseBody.builder().build()); super(context, ResponseBody.builder().build());
} }
} }
@@ -1,24 +1,22 @@
package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response; package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId; import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId;
/** Abstract base class for all server responses sent to clients. */ /** Abstract base class for all server responses sent to clients. */
public abstract class Response { public abstract class Response {
private final SessionId sessionId; private final RequestContext context;
private final int requestId;
private final ResponseBody body; private final ResponseBody body;
/** /**
* Create a new {@code Response}. * Create a new {@code Response}.
* *
* @param sessionId the id of the session this response targets * @param context the RequestContext of the request
* @param requestId the request identifier this response corresponds to
* @param body the structured response body * @param body the structured response body
*/ */
protected Response(SessionId sessionId, int requestId, ResponseBody body) { protected Response(RequestContext context, ResponseBody body) {
this.sessionId = sessionId; this.context = context;
this.requestId = requestId;
this.body = body; this.body = body;
} }
@@ -30,12 +28,12 @@ public abstract class Response {
public abstract String prefix(); public abstract String prefix();
/** /**
* Returns the session id that should receive this response. * Returns the session id of the session that should receive this response.
* *
* @return the target {@link SessionId} * @return the target {@link SessionId}
*/ */
public SessionId getSessionId() { public SessionId getSessionId() {
return sessionId; return context.sessionId();
} }
/** /**
@@ -44,7 +42,7 @@ public abstract class Response {
* @return the numeric request id * @return the numeric request id
*/ */
public int getRequestId() { public int getRequestId() {
return requestId; return context.requestId();
} }
/** /**
@@ -1,7 +1,7 @@
package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response; package ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.request.RequestContext;
import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody; import ch.unibas.dmi.dbis.cs108.casono.server.network.protocol.response.builder.ResponseBody;
import ch.unibas.dmi.dbis.cs108.casono.server.network.sessions.SessionId;
/** /**
* Abstract {@link Response} specialization indicating a successful outcome. * Abstract {@link Response} specialization indicating a successful outcome.
@@ -13,12 +13,11 @@ public abstract class SuccessResponse extends Response {
/** /**
* Create a successful response with the provided body. * Create a successful response with the provided body.
* *
* @param sessionId the session id this response targets * @param context the RequestContext of the request
* @param requestId the originating request id
* @param body the response body * @param body the response body
*/ */
protected SuccessResponse(SessionId sessionId, int requestId, ResponseBody body) { protected SuccessResponse(RequestContext context, ResponseBody body) {
super(sessionId, requestId, body); super(context, body);
} }
/** /**
@@ -46,11 +46,13 @@ public class SessionReader implements Runnable {
while (!Thread.currentThread().isInterrupted()) { while (!Thread.currentThread().isInterrupted()) {
RawPacket rawPacket = null; RawPacket rawPacket = null;
RawRequest rawRequest = null; RawRequest rawRequest = null;
RequestContext requestContext = null;
try { try {
// Step 1: Read from transport // Step 1: Read from transport
rawPacket = transport.read(); rawPacket = transport.read();
session.updateLastInboundActivity(); session.updateLastInboundActivity();
logger.debug("Recieved: {}", rawPacket); logger.debug("Recieved: {}", rawPacket);
requestContext = new RequestContext(session.getId(), rawPacket.requestId());
// Step 2: Syntax validation and conversion into transport object // Step 2: Syntax validation and conversion into transport object
rawRequest = ProtocolParser.parse(rawPacket.payload()); rawRequest = ProtocolParser.parse(rawPacket.payload());
@@ -58,9 +60,7 @@ public class SessionReader implements Runnable {
PrimitiveRequest primitiveRequest = PrimitiveRequest primitiveRequest =
new PrimitiveRequest( new PrimitiveRequest(
new RequestContext(session.getId(), rawPacket.requestId()), requestContext, rawRequest.command(), rawRequest.parameters());
rawRequest.command(),
rawRequest.parameters());
logger.debug("Converted to {}", primitiveRequest); logger.debug("Converted to {}", primitiveRequest);
// Step 3: Parse into Request and execute Request // Step 3: Parse into Request and execute Request
@@ -76,8 +76,7 @@ public class SessionReader implements Runnable {
sendErrorResponse( sendErrorResponse(
new ErrorResponse( new ErrorResponse(
session.getId(), requestContext,
rawPacket.requestId(),
"PARSING_ERROR", "PARSING_ERROR",
"Error occured during parsing. Likely due to malformed payload.")); "Error occured during parsing. Likely due to malformed payload."));
@@ -85,8 +84,7 @@ public class SessionReader implements Runnable {
logger.error("Recieved unknown command '{}' from client", rawRequest.command(), e); logger.error("Recieved unknown command '{}' from client", rawRequest.command(), e);
sendErrorResponse( sendErrorResponse(
new ErrorResponse( new ErrorResponse(
session.getId(), requestContext,
rawPacket.requestId(),
"UNKNOWN_COMMAND", "UNKNOWN_COMMAND",
"This command is unknown to the server.")); "This command is unknown to the server."));
@@ -97,8 +95,7 @@ public class SessionReader implements Runnable {
logger.error("Unexpected RuntimeException occured", e); logger.error("Unexpected RuntimeException occured", e);
sendErrorResponse( sendErrorResponse(
new ErrorResponse( new ErrorResponse(
session.getId(), requestContext,
rawPacket.requestId(),
"INTERNAL_ERROR", "INTERNAL_ERROR",
"Unexpected internal server error occured.")); "Unexpected internal server error occured."));
} }