All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dk.cloudcreate.essentials.components.queue.postgresql.PostgresqlDurableQueuesBuilder Maven / Gradle / Ivy

Go to download

This library focuses on providing a Durable Queue supporting message redelivery and Dead Letter Message functionality based on postgresql

There is a newer version: 0.40.17
Show newest version
/*
 * Copyright 2021-2024 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package dk.cloudcreate.essentials.components.queue.postgresql;

import dk.cloudcreate.essentials.components.foundation.json.*;
import dk.cloudcreate.essentials.components.foundation.messaging.queue.*;
import dk.cloudcreate.essentials.components.foundation.messaging.queue.operations.*;
import dk.cloudcreate.essentials.components.foundation.postgresql.*;
import dk.cloudcreate.essentials.components.foundation.transaction.*;
import dk.cloudcreate.essentials.components.foundation.transaction.jdbi.*;

import java.time.Duration;
import java.util.function.Function;

import static dk.cloudcreate.essentials.components.queue.postgresql.PostgresqlDurableQueues.*;

/**
 * Security
* It is the responsibility of the user of this component to sanitize the {@link #setSharedQueueTableName(String)} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlDurableQueues} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code sharedQueueTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code sharedQueueTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. */ public final class PostgresqlDurableQueuesBuilder { private HandleAwareUnitOfWorkFactory unitOfWorkFactory; private JSONSerializer jsonSerializer; private String sharedQueueTableName = DEFAULT_DURABLE_QUEUES_TABLE_NAME; private MultiTableChangeListener multiTableChangeListener = null; private Function queuePollingOptimizerFactory = null; private TransactionalMode transactionalMode = TransactionalMode.SingleOperationTransaction; /** * Only used if {@link #transactionalMode} has value {@link TransactionalMode#SingleOperationTransaction} */ private Duration messageHandlingTimeout = Duration.ofSeconds(30); /** * @param unitOfWorkFactory the {@link UnitOfWorkFactory} needed to access the database * @return this builder instance */ public PostgresqlDurableQueuesBuilder setUnitOfWorkFactory(HandleAwareUnitOfWorkFactory unitOfWorkFactory) { this.unitOfWorkFactory = unitOfWorkFactory; return this; } /** * @param jsonSerializer Set the {@link JSONSerializer} that is used to serialize/deserialize message payloads.
* If not set, then {@link JacksonJSONSerializer} with the {@link PostgresqlDurableQueues#createDefaultObjectMapper()} will be used * @return this builder instance */ public PostgresqlDurableQueuesBuilder setJsonSerializer(JSONSerializer jsonSerializer) { this.jsonSerializer = jsonSerializer; return this; } /** * @param sharedQueueTableName the name of the table that will contain all messages (across all {@link QueueName}'s)
* Default is {@link PostgresqlDurableQueues#DEFAULT_DURABLE_QUEUES_TABLE_NAME}
* Note:
* To support customization of storage table name, the {@code sharedQueueTableName} will be directly used in constructing SQL statements * through string concatenation, which exposes the component to SQL injection attacks.
*
* Security Note:
* It is the responsibility of the user of this component to sanitize the {@code sharedQueueTableName} * to ensure the security of all the SQL statements generated by this component. The {@link PostgresqlDurableQueues} component will * call the {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} method to validate the table name as a first line of defense.
* The {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} provides an initial layer of defense against SQL injection by applying naming conventions intended to reduce the risk of malicious input.
* However, Essentials components as well as {@link PostgresqlUtil#checkIsValidTableOrColumnName(String)} does not offer exhaustive protection, nor does it assure the complete security of the resulting SQL against SQL injection threats.
* The responsibility for implementing protective measures against SQL Injection lies exclusively with the users/developers using the Essentials components and its supporting classes.
* Users must ensure thorough sanitization and validation of API input parameters, column, table, and index names.
* Insufficient attention to these practices may leave the application vulnerable to SQL injection, potentially endangering the security and integrity of the database.
*
* It is highly recommended that the {@code sharedQueueTableName} value is only derived from a controlled and trusted source.
* To mitigate the risk of SQL injection attacks, external or untrusted inputs should never directly provide the {@code sharedQueueTableName} value.
* Failure to adequately sanitize and validate this value could expose the application to SQL injection * vulnerabilities, compromising the security and integrity of the database. * @return this builder instance */ public PostgresqlDurableQueuesBuilder setSharedQueueTableName(String sharedQueueTableName) { this.sharedQueueTableName = sharedQueueTableName; return this; } /** * @param multiTableChangeListener optional {@link MultiTableChangeListener} that allows {@link PostgresqlDurableQueues} to use {@link QueuePollingOptimizer} * @return this builder instance */ public PostgresqlDurableQueuesBuilder setMultiTableChangeListener(MultiTableChangeListener multiTableChangeListener) { this.multiTableChangeListener = multiTableChangeListener; return this; } /** * @param queuePollingOptimizerFactory optional {@link QueuePollingOptimizer} factory that creates a {@link QueuePollingOptimizer} per {@link ConsumeFromQueue} command - * if set to null {@link PostgresqlDurableQueues#createQueuePollingOptimizerFor(ConsumeFromQueue)} is used instead * @return this builder instance */ public PostgresqlDurableQueuesBuilder setQueuePollingOptimizerFactory(Function queuePollingOptimizerFactory) { this.queuePollingOptimizerFactory = queuePollingOptimizerFactory; return this; } /** * @param messageHandlingTimeout Only required if transactionalMode is {@link TransactionalMode#SingleOperationTransaction}.
* The parameter defines the timeout for messages being delivered, but haven't yet been acknowledged. * After this timeout the message delivery will be reset and the message will again be a candidate for delivery
* Default is 30 seconds * @return this builder instance */ public PostgresqlDurableQueuesBuilder setMessageHandlingTimeout(Duration messageHandlingTimeout) { this.messageHandlingTimeout = messageHandlingTimeout; return this; } /** * @param transactionalMode The {@link TransactionalMode} for this {@link DurableQueues} instance. If set to {@link TransactionalMode#SingleOperationTransaction} * then the consumer MUST call the {@link DurableQueues#acknowledgeMessageAsHandled(AcknowledgeMessageAsHandled)} explicitly in a new {@link UnitOfWork}
* Note: The default consumer calls {@link DurableQueues#acknowledgeMessageAsHandled(AcknowledgeMessageAsHandled)} after successful message handling * Default value {@link TransactionalMode#SingleOperationTransaction} * @return this builder instance */ public PostgresqlDurableQueuesBuilder setTransactionalMode(TransactionalMode transactionalMode) { this.transactionalMode = transactionalMode; return this; } public PostgresqlDurableQueues build() { return new PostgresqlDurableQueues(unitOfWorkFactory, jsonSerializer != null ? jsonSerializer : new JacksonJSONSerializer(createDefaultObjectMapper()), sharedQueueTableName, multiTableChangeListener, queuePollingOptimizerFactory, transactionalMode, messageHandlingTimeout); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy