dk.cloudcreate.essentials.components.queue.postgresql.PostgresqlDurableQueuesBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of postgresql-queue Show documentation
Show all versions of postgresql-queue Show documentation
This library focuses on providing a Durable Queue supporting message redelivery and Dead Letter Message functionality based on postgresql
/*
* 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 extends HandleAwareUnitOfWork> 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 extends HandleAwareUnitOfWork> 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