diff --git a/plugin/src/main/groovy/org/rmq4j/common/Rmq4j.java b/plugin/src/main/groovy/org/rmq4j/common/Rmq4j.java index 1a11e34..c7876b5 100644 --- a/plugin/src/main/groovy/org/rmq4j/common/Rmq4j.java +++ b/plugin/src/main/groovy/org/rmq4j/common/Rmq4j.java @@ -1,4 +1,57 @@ package org.rmq4j.common; +import org.springframework.web.context.request.RequestContextHolder; +import org.springframework.web.context.request.ServletRequestAttributes; +import org.unify4j.common.UniqueId4j; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpSession; + public class Rmq4j { + + /** + * @return the HTTP servlet request, class {@link HttpServletRequest} + */ + public static HttpServletRequest getRequest() { + ServletRequestAttributes s = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); + return s.getRequest(); + } + + /** + * Retrieves the current session ID from the request context. + *

+ * This method accesses the current request attributes from the RequestContextHolder + * and extracts the session ID associated with the current request. This is useful + * for tracking the session of the user making the request, especially in web + * applications where session management is crucial for user authentication and + * maintaining user state across multiple requests. + * + * @return the session ID of the current request, or null if no session is associated with the current request context + */ + public static String getCurrentSessionId() { + try { + ServletRequestAttributes s = (ServletRequestAttributes) RequestContextHolder.currentRequestAttributes(); + return s.getSessionId(); + } catch (IllegalStateException e) { + return String.valueOf(UniqueId4j.getUniqueId19()); + } + } + + /** + * Retrieves the session ID from the given HttpServletRequest. + *

+ * This method gets the current HttpSession associated with the request, + * and then extracts the session ID from it. If there is no current session + * and create is false, it returns null. + * + * @param request the HttpServletRequest from which to retrieve the session ID + * @return the session ID, or null if there is no current session + */ + public static String getSessionId(HttpServletRequest request) { + if (request == null) { + return String.valueOf(UniqueId4j.getUniqueId19()); + } + HttpSession session = request.getSession(false); // Pass false to prevent creating a new session if one does not exist + return (session != null) ? session.getId() : null; + } } diff --git a/plugin/src/main/groovy/org/rmq4j/service/Rmq4jCallback.java b/plugin/src/main/groovy/org/rmq4j/service/Rmq4jCallback.java deleted file mode 100644 index 4b1a234..0000000 --- a/plugin/src/main/groovy/org/rmq4j/service/Rmq4jCallback.java +++ /dev/null @@ -1,8 +0,0 @@ -package org.rmq4j.service; - -public interface Rmq4jCallback { - - void onSuccess(); - - void onError(); -} diff --git a/plugin/src/main/groovy/org/rmq4j/service/Rmq4jService.java b/plugin/src/main/groovy/org/rmq4j/service/Rmq4jService.java index 282dfc2..6b5ecb8 100644 --- a/plugin/src/main/groovy/org/rmq4j/service/Rmq4jService.java +++ b/plugin/src/main/groovy/org/rmq4j/service/Rmq4jService.java @@ -24,13 +24,23 @@ public interface Rmq4jService { Optional createFactory(Rmq4jProperties.Connection connection); + Optional createFactory(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback); + Optional createCacheConnFactory(Rmq4jProperties.Connection connection); + Optional createCacheConnFactory(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback); + Optional dispatch(Rmq4jProperties.Connection connection); + Optional dispatch(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback); + Optional dispatch(CachingConnectionFactory factory); + Optional dispatch(CachingConnectionFactory factory, Rmq4jWrapCallback callback); + Optional createAdm(Rmq4jProperties.Connection connection); + Optional createAdm(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback); + String getURLConnSchema(Rmq4jProperties.Connection connection); } diff --git a/plugin/src/main/groovy/org/rmq4j/service/Rmq4jWrapCallback.java b/plugin/src/main/groovy/org/rmq4j/service/Rmq4jWrapCallback.java new file mode 100644 index 0000000..9912008 --- /dev/null +++ b/plugin/src/main/groovy/org/rmq4j/service/Rmq4jWrapCallback.java @@ -0,0 +1,20 @@ +package org.rmq4j.service; + +import org.unify4j.model.response.WrapResponse; + +/** + * This interface defines a callback mechanism for handling RabbitMQ-related operations. + * Implementations of this interface should provide logic for handling exceptions + * that may occur during these operations and return a wrapped response. + */ +public interface Rmq4jWrapCallback { + + /** + * This method is called when an exception occurs during a RabbitMQ operation. + * Implementations should handle the exception and return an appropriate + * WrapResponse object. + * + * @param response a WrapResponse object containing the result or error information, class {@link WrapResponse} + */ + void onCallback(WrapResponse response); +} diff --git a/plugin/src/main/groovy/org/rmq4j/service/impl/Rmq4jServiceImpl.java b/plugin/src/main/groovy/org/rmq4j/service/impl/Rmq4jServiceImpl.java index df59efe..606d92b 100644 --- a/plugin/src/main/groovy/org/rmq4j/service/impl/Rmq4jServiceImpl.java +++ b/plugin/src/main/groovy/org/rmq4j/service/impl/Rmq4jServiceImpl.java @@ -1,8 +1,10 @@ package org.rmq4j.service.impl; import com.rabbitmq.client.ConnectionFactory; +import org.rmq4j.common.Rmq4j; import org.rmq4j.config.props.Rmq4jProperties; import org.rmq4j.service.Rmq4jService; +import org.rmq4j.service.Rmq4jWrapCallback; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.amqp.rabbit.connection.CachingConnectionFactory; @@ -12,7 +14,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.unify4j.common.Collection4j; +import org.unify4j.common.Json4j; import org.unify4j.common.String4j; +import org.unify4j.model.builder.HttpStatusBuilder; +import org.unify4j.model.builder.HttpWrapBuilder; import org.unify4j.model.enums.IconType; import java.util.Map; @@ -136,6 +141,40 @@ public Optional createFactory(Rmq4jProperties.Connection conn } } + /** + * Creates a {@link ConnectionFactory} for RabbitMQ based on the provided cluster configuration. + *

+ * This method initializes a {@link ConnectionFactory} using the details from the given {@link Rmq4jProperties.Connection}. + * It sets the host, port, virtual host, username, and password on the factory. If SSL is enabled in the configuration, + * it applies SSL settings to the factory. + *

+ * If the configuration is null or the cluster is not enabled, it returns an empty {@link Optional}. + * If an exception occurs while applying SSL settings, it logs the error and throws a {@link RuntimeException}. + * + * @param connection The cluster configuration used to create the {@link ConnectionFactory}. + * @return An {@link Optional} containing the configured {@link ConnectionFactory} if the configuration is valid and SSL settings are applied successfully; + * otherwise, an empty {@link Optional}. + */ + @Override + public Optional createFactory(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback) { + HttpWrapBuilder response = new HttpWrapBuilder<>().ok(null).requestId(Rmq4j.getCurrentSessionId()); + Optional factory = Optional.empty(); + try { + factory = this.createFactory(connection); + } catch (Exception e) { + response + .statusCode(HttpStatusBuilder.INTERNAL_SERVER_ERROR) + .message("creating connection factory failed") + .debug("cause", e.getMessage()) + .errors(e) + .customFields("conn_string", Json4j.toJson(connection)); + } + if (callback != null) { + callback.onCallback(response.build()); + } + return factory; + } + /** * Creates a {@link CachingConnectionFactory} for RabbitMQ based on the provided cluster configuration. *

@@ -160,6 +199,40 @@ public Optional createCacheConnFactory(Rmq4jProperties return Optional.of(new CachingConnectionFactory(factory.get())); } + /** + * Creates a {@link CachingConnectionFactory} for RabbitMQ based on the provided cluster configuration. + *

+ * This method first uses {@link #createFactory(Rmq4jProperties.Connection)} to create a {@link ConnectionFactory} + * from the given cluster configuration. If the factory creation is successful, it wraps the factory in a + * {@link CachingConnectionFactory} and returns it as an {@link Optional}. + *

+ * If the {@link ConnectionFactory} could not be created (e.g., due to invalid configuration), it returns + * an empty {@link Optional}. + * + * @param connection The cluster configuration used to create the {@link ConnectionFactory}. + * @return An {@link Optional} containing the {@link CachingConnectionFactory} if the {@link ConnectionFactory} + * was created successfully; otherwise, an empty {@link Optional}. + */ + @Override + public Optional createCacheConnFactory(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback) { + HttpWrapBuilder response = new HttpWrapBuilder<>().ok(null).requestId(Rmq4j.getCurrentSessionId()); + Optional factory = Optional.empty(); + try { + factory = this.createCacheConnFactory(connection); + } catch (Exception e) { + response + .statusCode(HttpStatusBuilder.INTERNAL_SERVER_ERROR) + .message("creating cache connection factory failed") + .debug("cause", e.getMessage()) + .errors(e) + .customFields("conn_string", Json4j.toJson(connection)); + } + if (callback != null) { + callback.onCallback(response.build()); + } + return factory; + } + /** * Creates a {@link RabbitTemplate} for RabbitMQ based on the provided cluster configuration. *

@@ -185,6 +258,41 @@ public Optional dispatch(Rmq4jProperties.Connection connection) return this.dispatch(factory.get()); } + /** + * Creates a {@link RabbitTemplate} for RabbitMQ based on the provided cluster configuration. + *

+ * This method first uses {@link #createCacheConnFactory(Rmq4jProperties.Connection)} to create a + * {@link CachingConnectionFactory} from the given cluster configuration. If the creation of the + * {@link CachingConnectionFactory} is successful, it wraps the factory in a {@link RabbitTemplate} + * and returns it as an {@link Optional}. + *

+ * If the {@link CachingConnectionFactory} could not be created (e.g., due to invalid configuration), + * it returns an empty {@link Optional}. + * + * @param connection The cluster configuration used to create the {@link CachingConnectionFactory}. + * @return An {@link Optional} containing the {@link RabbitTemplate} if the {@link CachingConnectionFactory} + * was created successfully; otherwise, an empty {@link Optional}. + */ + @Override + public Optional dispatch(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback) { + HttpWrapBuilder response = new HttpWrapBuilder<>().ok(null).requestId(Rmq4j.getCurrentSessionId()); + Optional template = Optional.empty(); + try { + template = this.dispatch(connection); + } catch (Exception e) { + response + .statusCode(HttpStatusBuilder.INTERNAL_SERVER_ERROR) + .message("creating RabbitMQ Template failed") + .debug("cause", e.getMessage()) + .errors(e) + .customFields("conn_string", Json4j.toJson(connection)); + } + if (callback != null) { + callback.onCallback(response.build()); + } + return template; + } + /** * Creates a {@link RabbitTemplate} for RabbitMQ based on the provided cluster configuration. *

@@ -210,6 +318,41 @@ public Optional dispatch(CachingConnectionFactory factory) { return Optional.of(template); } + /** + * Creates a {@link RabbitTemplate} for RabbitMQ based on the provided cluster configuration. + *

+ * This method first uses {@link #createCacheConnFactory(Rmq4jProperties.Connection)} to create a + * {@link CachingConnectionFactory} from the given cluster configuration. If the creation of the + * {@link CachingConnectionFactory} is successful, it wraps the factory in a {@link RabbitTemplate} + * and returns it as an {@link Optional}. + *

+ * If the {@link CachingConnectionFactory} could not be created (e.g., due to invalid configuration), + * it returns an empty {@link Optional}. + * + * @param factory The cluster configuration used to create the {@link CachingConnectionFactory}. + * @return An {@link Optional} containing the {@link RabbitTemplate} if the {@link CachingConnectionFactory} + * was created successfully; otherwise, an empty {@link Optional}. + */ + @Override + public Optional dispatch(CachingConnectionFactory factory, Rmq4jWrapCallback callback) { + HttpWrapBuilder response = new HttpWrapBuilder<>().ok(null).requestId(Rmq4j.getCurrentSessionId()); + Optional template = Optional.empty(); + try { + template = this.dispatch(factory); + } catch (Exception e) { + response + .statusCode(HttpStatusBuilder.INTERNAL_SERVER_ERROR) + .message("creating RabbitMQ Template failed") + .debug("cause", e.getMessage()) + .errors(e) + .customFields("cache_conn_string", factory != null ? factory.getCacheProperties().toString() : "undefined cache connection factory"); + } + if (callback != null) { + callback.onCallback(response.build()); + } + return template; + } + /** * Creates a {@link RabbitAdmin} for RabbitMQ based on the provided cluster configuration. *

@@ -235,6 +378,41 @@ public Optional createAdm(Rmq4jProperties.Connection connection) { return Optional.of(new RabbitAdmin(factory.get())); } + /** + * Creates a {@link RabbitAdmin} for RabbitMQ based on the provided cluster configuration. + *

+ * This method first uses {@link #createCacheConnFactory(Rmq4jProperties.Connection)} to create a + * {@link CachingConnectionFactory} from the given cluster configuration. If the creation of the + * {@link CachingConnectionFactory} is successful, it wraps the factory in a {@link RabbitAdmin} + * and returns it as an {@link Optional}. + *

+ * If the {@link CachingConnectionFactory} could not be created (e.g., due to invalid configuration), + * it returns an empty {@link Optional}. + * + * @param connection The cluster configuration used to create the {@link CachingConnectionFactory}. + * @return An {@link Optional} containing the {@link RabbitAdmin} if the {@link CachingConnectionFactory} + * was created successfully; otherwise, an empty {@link Optional}. + */ + @Override + public Optional createAdm(Rmq4jProperties.Connection connection, Rmq4jWrapCallback callback) { + HttpWrapBuilder response = new HttpWrapBuilder<>().ok(null).requestId(Rmq4j.getCurrentSessionId()); + Optional adm = Optional.empty(); + try { + adm = this.createAdm(connection); + } catch (Exception e) { + response + .statusCode(HttpStatusBuilder.INTERNAL_SERVER_ERROR) + .message("creating RabbitMQ Admin failed") + .debug("cause", e.getMessage()) + .errors(e) + .customFields("conn_string", Json4j.toJson(connection)); + } + if (callback != null) { + callback.onCallback(response.build()); + } + return adm; + } + /** * Generates the connection URL schema for RabbitMQ based on the provided cluster configuration. *