diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java index 573a0c3661..4398f72389 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/controller/AdminController.java @@ -28,14 +28,30 @@ import lombok.extern.slf4j.Slf4j; +/** + * This class is responsible for managing the admin module. + *

+ * It provides a method to run the admin module with the specified {@link HttpServer} + * and handles requests related to topics management. + */ + @Slf4j public class AdminController { public AdminController() { } + /** + * Invoke this method to run the admin module. + * + * @param server A HttpServer is bound to an IP address and port number + * and listens for incoming TCP connections from clients on this address. + * @throws IOException + * @see HttpServer + */ public void run(HttpServer server) throws IOException { + // Creates a mapping from API URI path to the exchange handler on this HttpServer. server.createContext(TOPIC_MANAGE_PATH, new TopicsHandler()); log.info("EventMesh-Admin Controller server context created successfully"); diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java index 836f293ef4..4a7914186b 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/handler/TopicsHandler.java @@ -39,33 +39,65 @@ import lombok.extern.slf4j.Slf4j; +/** + * This class is responsible for handling HTTP requests related to topics. + *

+ * It implements the {@link HttpHandler} interface to process incoming requests, + * which is used by the {@linkplain com.sun.net.httpserver.HttpServer HttpServer}. + *

+ * It uses the {@link RequestMapping} class to match the request URL and the HTTP method. + *

+ * It uses the {@link TopicCreateRequest} class to parse the request body + * and the {@link TopicResponse} class to create the response. + * + * @see HttpHandler + */ + @Slf4j public class TopicsHandler implements HttpHandler { + /** + * Handles the HTTP request for creating topics. + * + * @param httpExchange the exchange containing the request from the client and used to send the response + * @throws IOException if an I/O error occurs + * @see HttpHandler#handle(HttpExchange) + */ @Override public void handle(HttpExchange httpExchange) throws IOException { - // create a new topic + // If the request matches, then create a new topic. if (RequestMapping.postMapping(TOPIC_MANAGE_PATH, httpExchange)) { createTopicHandler(httpExchange); return; } + // Otherwise, it prepares an error response and sends it back to the client. OutputStream out = httpExchange.getResponseBody(); httpExchange.sendResponseHeaders(500, 0); String result = String.format("Please check your request url: %s", httpExchange.getRequestURI()); log.error(result); + // Write the response data. out.write(result.getBytes(Constants.DEFAULT_CHARSET)); } + /** + * Handles the creation of a new topic. + * + * @param httpExchange the exchange containing the request from the client and used to send the response + * @throws IOException if an I/O error occurs + */ public void createTopicHandler(HttpExchange httpExchange) throws IOException { String result; try (OutputStream out = httpExchange.getResponseBody()) { + // Parses the request body into a TopicCreateRequest object. String params = NetUtils.parsePostBody(httpExchange); TopicCreateRequest topicCreateRequest = JsonUtils.parseObject(params, TopicCreateRequest.class); + // Gets the topic name from the request body. String topic = topicCreateRequest.getTopic(); + // If the topic name is empty, then returns an error message. if (StringUtils.isBlank(topic)) { result = "Create topic failed. Parameter topic not found."; log.error(result); @@ -74,7 +106,7 @@ public void createTopicHandler(HttpExchange httpExchange) throws IOException { } //TBD: A new rocketmq service will be implemented for creating topics - TopicResponse topicResponse = null; + TopicResponse topicResponse = null; // Temporary variable for topic response if (topicResponse != null) { log.info("create a new topic: {}", topic); httpExchange.getResponseHeaders().add(CONTENT_TYPE, APPLICATION_JSON); @@ -83,12 +115,14 @@ public void createTopicHandler(HttpExchange httpExchange) throws IOException { log.info(result); out.write(result.getBytes(Constants.DEFAULT_CHARSET)); } else { + // If the topic creation fails, then returns an error message. httpExchange.sendResponseHeaders(500, 0); result = TOPIC_ERROR; log.error(result); out.write(result.getBytes(Constants.DEFAULT_CHARSET)); } } catch (Exception e) { + // If an exception occurs, then returns an error message. httpExchange.getResponseHeaders().add(CONTENT_TYPE, APPLICATION_JSON); httpExchange.sendResponseHeaders(500, 0); result = TOPIC_ERROR; diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java index 81a99b1cb3..925b43889a 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/request/TopicCreateRequest.java @@ -22,12 +22,35 @@ import com.fasterxml.jackson.annotation.JsonInclude; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * A data transfer object (DTO) that represents a request to create a new topic. + *

+ * This class provides a convenient way to encapsulate the topic information when creating a new topic. + *

+ * Empty or null values will not be included in the serialized JSON. + *

+ * Any unknown properties will be ignored when deserializing JSON into this class. + *

+ * Example usage: + *

+ * String params = NetUtils.parsePostBody(httpExchange);
+ * TopicCreateRequest topicCreateRequest = JsonUtils.parseObject(params, TopicCreateRequest.class);
+ * String topic = topicCreateRequest.getTopic();
+ * topicCreateRequest.setTopic("UpdatedTopic");
+ * 
+ */ + @JsonInclude(JsonInclude.Include.NON_EMPTY) @JsonIgnoreProperties(ignoreUnknown = true) public class TopicCreateRequest { private String topic; + /** + * Constructs a new instance of {@link TopicCreateRequest}. + * + * @param topic the topic for the request + */ @JsonCreator public TopicCreateRequest(@JsonProperty("topic") String topic) { this.topic = topic; diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java index 9ccdc2bb85..c9b1590a77 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/response/TopicResponse.java @@ -20,6 +20,15 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; +/** + * A data transfer object (DTO) that represents a response containing a topic and its creation time. + *

+ * It includes the values returned upon the creation of a new topic, an update to an existing topic, + * or the retrieval of a topic's details. + *

+ * It is used to encapsulate the topic information being sent to the client from the server. + */ + public class TopicResponse { private String topic; diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java index 2158cb2b1c..914e00c836 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/RequestMapping.java @@ -23,25 +23,65 @@ import lombok.experimental.UtilityClass; +/** + * This class provides utility methods for handling HTTP request mappings. + */ + @UtilityClass public class RequestMapping { + /** + * Performs a POST mapping for a specific URL. + * + * @param value the URL pattern to match + * @param httpExchange the exchange containing the request from the client and used to send the response + * @return {@code true} if the URL pattern matches and the HTTP method is POST, {@code false} otherwise + */ public boolean postMapping(String value, HttpExchange httpExchange) { return isUrlMatch(value, httpExchange, HttpMethod.POST.name()); } + /** + * Performs a GET mapping for a specific URL. + * + * @param value the URL pattern to match + * @param httpExchange the exchange containing the request from the client and used to send the response + * @return {@code true} if the URL pattern matches and the HTTP method is GET, {@code false} otherwise + */ public boolean getMapping(String value, HttpExchange httpExchange) { return isUrlMatch(value, httpExchange, HttpMethod.GET.name()); } + /** + * Performs a PUT mapping for a specific URL. + * + * @param value the URL pattern to match + * @param httpExchange the exchange containing the request from the client and used to send the response + * @return {@code true} if the URL pattern matches and the HTTP method is PUT, {@code false} otherwise + */ public boolean putMapping(String value, HttpExchange httpExchange) { return isUrlMatch(value, httpExchange, HttpMethod.PUT.name()); } + /** + * Performs a DELETE mapping for a specific URL. + * + * @param value the URL pattern to match + * @param httpExchange the exchange containing the request from the client and used to send the response + * @return {@code true} if the URL pattern matches and the HTTP method is DELETE, {@code false} otherwise + */ public boolean deleteMapping(String value, HttpExchange httpExchange) { return isUrlMatch(value, httpExchange, HttpMethod.DELETE.name()); } + /** + * Checks if the URL pattern matches the request URI and the HTTP method is the specified method type. + * + * @param value the URL pattern to match + * @param httpExchange the exchange containing the request from the client and used to send the response + * @param methodType the HTTP method type to check against + * @return {@code true} if the URL pattern matches and the HTTP method is the specified method type, {@code false} otherwise + */ private boolean isUrlMatch(String value, HttpExchange httpExchange, String methodType) { if (methodType.equalsIgnoreCase(httpExchange.getRequestMethod())) { String requestUri = httpExchange.getRequestURI().getPath(); diff --git a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java index 994f471c86..254a3c8ca3 100644 --- a/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java +++ b/eventmesh-admin/eventmesh-admin-rocketmq/src/main/java/org/apache/eventmesh/admin/rocketmq/util/UrlMappingPattern.java @@ -25,6 +25,11 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; +/** + * Represents a URL mapping pattern for routing purposes. + * The pattern can include variable path parameters or query strings. + */ + public class UrlMappingPattern { private static final String URL_PARAMETER_REGEX = "\\{(\\w*?)\\}"; @@ -55,6 +60,13 @@ public String getMappingPattern() { return urlMappingPattern.replaceFirst(URL_FORMAT_REGEX, ""); } + /** + * Extracts path parameters from the given URL and returns a {@link Map} of parameter names to values. + * + * @param url the URL from which to extract path parameters + * @return a {@link Map} containing path parameter names and their corresponding values, + * or null if the URL does not match the defined URL mapping pattern + */ public Map extractPathParameterValues(String url) { Matcher matcher = compiledUrlMappingPattern.matcher(url); if (matcher.matches()) { @@ -81,6 +93,12 @@ private void acquireParamNames() { } } + /** + * Extracts parameters from the provided {@link Matcher} object and returns a {@link Map} of parameter names to values. + * + * @param matcher the Matcher object used to match and capture parameter values + * @return a {@link Map} containing parameter names and their corresponding values + */ private Map extractParameters(Matcher matcher) { Map values = new HashMap<>((int) (matcher.groupCount() / 0.75f + 1)); for (int i = 0; i < matcher.groupCount(); i++) { diff --git a/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java index 1614fddfa8..0cc9971a5a 100644 --- a/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java +++ b/eventmesh-runtime/src/main/java/org/apache/eventmesh/runtime/admin/controller/ClientManageController.java @@ -85,16 +85,26 @@ public ClientManageController(EventMeshTCPServer eventMeshTCPServer, } + /** + * Method to start the server and perform initialization. + * + * @throws IOException if an I/O error occurs + */ public void start() throws IOException { + // Get the server's admin port. int port = eventMeshTCPServer.getEventMeshTCPConfiguration().getEventMeshServerAdminPort(); + // Create an HTTP server and bind it to the specified port. HttpServer server = HttpServer.create(new InetSocketAddress(port), 0); HttpHandlerManager httpHandlerManager = new HttpHandlerManager(); - //todo Optimized for automatic injection + //TODO: Optimized for automatic injection + + // Initialize the client handler and register it with the HTTP handler manager. initClientHandler(eventMeshTCPServer, eventMeshHTTPServer, eventMeshGrpcServer, eventMeshRegistry, httpHandlerManager); + // Register the handlers from the HTTP handler manager with the HTTP server. httpHandlerManager.registerHttpHandler(server); AdminController adminController = new AdminController(); adminController.run(server);