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

com.rabbitmq.jms.admin.RMQConnectionFactory Maven / Gradle / Ivy

There is a newer version: 3.4.0
Show newest version
/* Copyright (c) 2013-2023 Broadcom. All Rights Reserved. The term "Broadcom" refers to Broadcom Inc. and/or its subsidiaries. */
package com.rabbitmq.jms.admin;

import static com.rabbitmq.jms.util.UriCodec.encHost;
import static com.rabbitmq.jms.util.UriCodec.encSegment;
import static com.rabbitmq.jms.util.UriCodec.encUserinfo;

import com.rabbitmq.client.AMQP;
import com.rabbitmq.client.Address;
import com.rabbitmq.client.Channel;
import com.rabbitmq.client.DefaultSaslConfig;
import com.rabbitmq.client.MetricsCollector;
import com.rabbitmq.jms.client.AuthenticationMechanism;
import com.rabbitmq.jms.client.ConnectionParams;
import com.rabbitmq.jms.client.DefaultReplyToStrategy;
import com.rabbitmq.jms.client.RMQConnection;
import com.rabbitmq.jms.client.RMQMessage;
import com.rabbitmq.jms.client.ReceivingContext;
import com.rabbitmq.jms.client.ReceivingContextConsumer;
import com.rabbitmq.jms.client.ReplyToStrategy;
import com.rabbitmq.jms.client.RmqJmsContext;
import com.rabbitmq.jms.client.SendingContext;
import com.rabbitmq.jms.client.SendingContextConsumer;
import com.rabbitmq.jms.util.RMQJMSException;
import com.rabbitmq.jms.util.RMQJMSSecurityException;
import com.rabbitmq.jms.util.WhiteListObjectInputStream;
import java.io.IOException;
import java.io.Serializable;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.NoSuchAlgorithmException;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.TimeoutException;
import java.util.function.BiFunction;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import jakarta.jms.BytesMessage;
import jakarta.jms.Connection;
import jakarta.jms.ConnectionFactory;
import jakarta.jms.Destination;
import jakarta.jms.JMSContext;
import jakarta.jms.JMSException;
import jakarta.jms.JMSRuntimeException;
import jakarta.jms.Message;
import jakarta.jms.MessageListener;
import jakarta.jms.MessageProducer;
import jakarta.jms.QueueConnection;
import jakarta.jms.QueueConnectionFactory;
import jakarta.jms.Session;
import jakarta.jms.TextMessage;
import jakarta.jms.TopicConnection;
import jakarta.jms.TopicConnectionFactory;
import javax.naming.NamingException;
import javax.naming.RefAddr;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * RabbitMQ Implementation of JMS {@link ConnectionFactory}
 * TODO - implement SslContext option
 */
public class RMQConnectionFactory implements ConnectionFactory, Referenceable, Serializable, QueueConnectionFactory,
                                 TopicConnectionFactory {
    private final Logger logger = LoggerFactory.getLogger(RMQConnectionFactory.class);

    private static final long serialVersionUID = -4953157213762979615L;

    private static final int DEFAULT_RABBITMQ_SSL_PORT = com.rabbitmq.client.ConnectionFactory.DEFAULT_AMQP_OVER_SSL_PORT;

    private static final int DEFAULT_RABBITMQ_PORT = com.rabbitmq.client.ConnectionFactory.DEFAULT_AMQP_PORT;

    /** Default username to RabbitMQ broker */
    private String username = "guest";
    /** Default password to RabbitMQ broker */
    private String password = "guest";
    /** Default virtualhost */
    private String virtualHost = "/";
    /** Default host to RabbitMQ broker */
    private String host = "localhost";
    /** Default port NOT SET - determined by the type of connection (ssl or non-ssl) */
    private int port = -1;
    /** How long to wait for onMessage to return, in milliseconds */
    private int onMessageTimeoutMs = 2000;
    /**
     * Whether {@link MessageProducer} properties (delivery mode,
     * priority, TTL) take precedence over respective {@link Message}
     * properties or not.
     * Default is true (which is compliant to the JMS specification).
     */
    private boolean preferProducerMessageProperty = true;

    /**
     * Whether requeue message on {@link RuntimeException} in the
     * {@link jakarta.jms.MessageListener} or not.
     * Default is false.
     *
     * @since 1.7.0
     * @see RMQConnectionFactory#requeueOnTimeout
     */
    private boolean requeueOnMessageListenerException = false;

    /**
     * Whether to requeue a message that timed out or not.
     *
     * Only taken into account if requeueOnMessageListenerException is true.
     * Default is false.
     *
     * @since 2.3.0
     * @see RMQConnectionFactory#requeueOnMessageListenerException
     */
    private boolean requeueOnTimeout = false;

    /**
     * Whether to nack messages on rollback or not.
     *
     * Nack-ed messages will be discarded, not re-queued. Queues
     * will typically have dead lettering
     * configured when enabling this feature, so nack-ed messages are routed
     * elsewhere and not discarded forever.
     * 

* Default is false. * * @see Negative Acknowledgements * @see Dead Letter Exchanges * @since 1.14.0 */ private boolean nackOnRollback = false; /** * Whether using auto-delete for server-named queues for non-durable topics. * If set to true, those queues will be deleted when the session is closed. * If set to false, queues will be deleted when the owning connection is closed. * Default is false. * * @since 1.8.0 */ private boolean cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose = false; /** * Callback to customise properties of outbound AMQP messages. * * @since 1.9.0 */ private BiFunction amqpPropertiesCustomiser; /** * Collector for AMQP-client metrics. * * @since 1.10.0 */ private MetricsCollector metricsCollector = new NoOpMetricsCollector(); /** * For post-processing the {@link com.rabbitmq.client.ConnectionFactory} before creating the AMQP connection. * * @since 1.10.0 */ private Consumer amqpConnectionFactoryPostProcessor = new NoOpSerializableConsumer<>(); /** * For post-processing the created {@link com.rabbitmq.client.Connection} * * @since 2.10.0 */ private Consumer amqpConnectionPostProcessor = new NoOpSerializableConsumer<>(); /** * Callback before sending a message. * * @since 1.11.0 */ private SendingContextConsumer sendingContextConsumer = new NoOpSerializableSendingContextConsumer(); /** * Callback before receiving a message. * * @since 1.11.0 */ private ReceivingContextConsumer receivingContextConsumer = new NoOpSerializableReceivingContextConsumer(); /** * Flag to insert automatically an interoperability hint in outbound {@link TextMessage}s. * *

When set to true, the AMQP JMSType header will be set * automatically to "TextMessage" for {@link TextMessage}s published to AMQP-backed * {@link Destination}s. This way JMS consumers will receive {@link TextMessage}s instead of * {@link BytesMessage}. * *

Enabling the feature avoids some additional work in the application code of publishers, * making the publishing and consuming of {@link TextMessage}s through AMQP resources transparent. * *

The default is false. * * @since 2.5.0 */ private boolean keepTextMessageType = false; /** Default not to use ssl */ private boolean ssl = false; private String tlsProtocol; private SSLContext sslContext; private boolean useDefaultSslContext = false; /** * Whether to use hostname verification when TLS is on. * * @since 1.10.0 */ private boolean hostnameVerification = false; /** The maximum number of messages to read on a queue browser, which must be non-negative; * 0 means unlimited and is the default; negative values are interpreted as 0. */ private int queueBrowserReadMax = Math.max(0, Integer.getInteger("rabbit.jms.queueBrowserReadMax", 0)); /** The time to wait for threads/messages to terminate during {@link Connection#close()} */ private volatile long terminationTimeout = Long.getLong("rabbit.jms.terminationTimeout", 15000); /** * QoS setting for channels created by this connection factory. * * @see com.rabbitmq.client.Channel#basicQos(int) */ private int channelsQos = RMQConnection.NO_CHANNEL_QOS; /** * Classes in these packages can be transferred via ObjectMessage. * * @see WhiteListObjectInputStream */ private List trustedPackages = WhiteListObjectInputStream.DEFAULT_TRUSTED_PACKAGES; /** * List of nodes URIs to connect to. * * @since 1.10.0 */ private List uris = Collections.emptyList(); /** * Whether replyTo destination for consumed messages should be declared. * * @since 1.11.0 */ private boolean declareReplyToDestination = true; /** * The strategy to apply to reply-to queue handling. Defaults to handling * "amq.rabbitmq.reply-to" queues. * * @since 2.9.0 */ private ReplyToStrategy replyToStrategy = DefaultReplyToStrategy.INSTANCE; /** * The authentication mechanism to use. * * @since 3.2.0 */ private AuthenticationMechanism authenticationMechanism = AuthenticationMechanism.PLAIN; /** * {@inheritDoc} */ @Override public Connection createConnection() throws JMSException { return this.createConnection(username, password); } public Connection createConnection(List

endpoints) throws JMSException { return this.createConnection(username, password, endpoints); } /** * {@inheritDoc} */ @Override public Connection createConnection(String username, String password) throws JMSException { if (this.uris == null || this.uris.isEmpty()) { return createConnection(username, password, cf -> cf.newConnection()); } else { List
addresses = this.uris.stream().map(uri -> { String host = uri.getHost(); int port = uri.getPort(); if (port == -1) { port = isSsl() ? DEFAULT_RABBITMQ_SSL_PORT : DEFAULT_RABBITMQ_PORT; } return new Address(host, port); }).collect(Collectors.toList()); return createConnection(username, password, cf -> cf.newConnection(addresses)); } } public Connection createConnection(String username, String password, List
endpoints) throws JMSException { return createConnection(username, password, cf -> cf.newConnection(endpoints)); } protected Connection createConnection(String username, String password, ConnectionCreator connectionCreator) throws JMSException { logger.trace("Creating a connection for username '{}', password 'xxxxxxxx'.", username); this.username = username; this.password = password; com.rabbitmq.client.ConnectionFactory cf = createConnectionFactory(); maybeEnableTLS(cf); setRabbitUri(logger, this, cf, getUri()); maybeEnableHostnameVerification(cf); cf.setMetricsCollector(this.metricsCollector); setSaslConfig(cf, authenticationMechanism); if (this.amqpConnectionFactoryPostProcessor != null) { this.amqpConnectionFactoryPostProcessor.accept(cf); } com.rabbitmq.client.Connection rabbitConnection = instantiateNodeConnection(cf, connectionCreator); if (this.amqpConnectionPostProcessor != null) { this.amqpConnectionPostProcessor.accept(rabbitConnection); } ReceivingContextConsumer rcc; if (this.declareReplyToDestination) { rcc = this.receivingContextConsumer; } else { rcc = ctx -> RMQMessage.doNotDeclareReplyToDestination(ctx.getMessage()); if (this.receivingContextConsumer != null) { rcc = rcc.andThen(this.receivingContextConsumer); } } RMQConnection conn = new RMQConnection(new ConnectionParams() .setRabbitConnection(rabbitConnection) .setTerminationTimeout(getTerminationTimeout()) .setQueueBrowserReadMax(getQueueBrowserReadMax()) .setOnMessageTimeoutMs(getOnMessageTimeoutMs()) .setChannelsQos(channelsQos) .setPreferProducerMessageProperty(preferProducerMessageProperty) .setRequeueOnMessageListenerException(requeueOnMessageListenerException) .setNackOnRollback(nackOnRollback) .setCleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose(this.cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose) .setAmqpPropertiesCustomiser(amqpPropertiesCustomiser) .setSendingContextConsumer(sendingContextConsumer) .setReceivingContextConsumer(rcc) .setTrustedPackages(this.trustedPackages) .setRequeueOnTimeout(this.requeueOnTimeout) .setKeepTextMessageType(this.keepTextMessageType) .setReplyToStrategy(replyToStrategy) ); logger.debug("Connection {} created.", conn); return conn; } protected com.rabbitmq.client.ConnectionFactory createConnectionFactory() { return new com.rabbitmq.client.ConnectionFactory(); } private com.rabbitmq.client.Connection instantiateNodeConnection(com.rabbitmq.client.ConnectionFactory cf, ConnectionCreator connectionCreator) throws JMSException { try { return connectionCreator.create(cf); } catch (SSLException ssle) { throw new RMQJMSSecurityException("SSL Exception establishing RabbitMQ Connection", ssle); } catch (Exception x) { if (x instanceof IOException) { IOException ioe = (IOException) x; String msg = ioe.getMessage(); if (msg!=null) { if (msg.contains("authentication failure") || msg.contains("refused using authentication")) throw new RMQJMSSecurityException(ioe); else if (msg.contains("Connection refused")) throw new RMQJMSException("RabbitMQ connection was refused. RabbitMQ broker may not be available.", ioe); } throw new RMQJMSException(ioe); } else if (x instanceof TimeoutException) { TimeoutException te = (TimeoutException) x; throw new RMQJMSException("Timed out establishing RabbitMQ Connection", te); } else { throw new RMQJMSException("Unexpected exception thrown by newConnection()", x); } } } /** * Returns the current factory connection parameters in a URI String. * @return URI for RabbitMQ connection (as a coded String) */ public String getUri() { StringBuilder sb = new StringBuilder(getScheme(isSsl())).append("://"); sb.append(uriUInfoEscape(this.username, this.password)).append('@'); sb.append(uriHostEscape(this.host)).append(':').append(this.getPort()).append("/"); sb.append(uriVirtualHostEscape(this.virtualHost)); return sb.toString(); } public String toString() { StringBuilder sb = new StringBuilder("RMQConnectionFactory{"); return (this.isSsl() ? sb.append("SSL, ") : sb) .append("user='").append(this.username) .append("', password").append(this.password!=null ? "=xxxxxxxx" : " not set") .append(", host='").append(this.host) .append("', port=").append(this.getPort()) .append(", virtualHost='").append(this.virtualHost) .append("', onMessageTimeoutMs=").append(this.onMessageTimeoutMs) .append(", queueBrowserReadMax=").append(this.queueBrowserReadMax) .append('}').toString(); } /** * Set connection factory parameters by URI String. * @param uriString URI to use for instantiated connection * @throws JMSException if connection URI is invalid */ public void setUri(String uriString) throws JMSException { logger.trace("Set connection factory parameters by URI '{}'", uriString); if (uriString != null && !uriString.trim().isEmpty()) { // Create a temp factory and set the properties by uri com.rabbitmq.client.ConnectionFactory factory = createConnectionFactory(); // Generates a TrustEverythingTrustManager warning which can be ignored as the SSLContext is not copied over setRabbitUri(logger, this, factory, uriString); // Now extract our properties from this factory, leaving the rest unchanged. this.host = factory.getHost(); this.password = factory.getPassword(); this.port = factory.getPort(); this.ssl = factory.isSSL(); this.username = factory.getUsername(); this.virtualHost = factory.getVirtualHost(); } else { this.host = null; this.password = null; this.port = -1; this.ssl = false; this.username = null; this.virtualHost = null; } } /** * Sets the nodes URIs to connect to. * * @param urisAsStrings * @throws JMSException * @since 1.10.0 */ public void setUris(List urisAsStrings) throws JMSException { if (urisAsStrings != null && !urisAsStrings.isEmpty()) { this.uris = urisAsStrings.stream().map(uriAsString -> { try { URI uri = new URI(uriAsString); if (uri.getScheme() == null || (!"amqp".equals(uri.getScheme()) && !"amqps".equals(uri.getScheme()))) { throw new IllegalArgumentException("Wrong scheme in AMQP URI: " + uri.getScheme()); } return uri; } catch (URISyntaxException e) { throw new IllegalArgumentException("Invalid URI: " + uriAsString); } }).collect(Collectors.toList()); this.setUri(urisAsStrings.get(0)); } else { this.uris = Collections.emptyList(); setUri(null); } } /** * @param value list of trusted package prefixes */ public void setTrustedPackages(List value) { this.trustedPackages = value; } /** * @return list of package prefixes that are whitelisted for transfer over {@link jakarta.jms.ObjectMessage} */ public List getTrustedPackages() { return trustedPackages; } private static void setRabbitUri(Logger logger, RMQConnectionFactory rmqFactory, com.rabbitmq.client.ConnectionFactory factory, String uriString) throws RMQJMSException { if (uriString != null) { // we get the defaults if the uri is null try { factory.setUri(uriString); } catch (Exception e) { logger.error("Could not set URI on {}", rmqFactory, e); throw new RMQJMSException("Could not set URI on RabbitMQ connection factory.", e); } } } private void maybeEnableTLS(com.rabbitmq.client.ConnectionFactory factory) { if (this.ssl) try { if(this.useDefaultSslContext) { factory.useSslProtocol(SSLContext.getDefault()); } else { if (this.sslContext != null) { factory.useSslProtocol(this.sslContext); } else if (this.tlsProtocol != null) { factory.useSslProtocol(this.tlsProtocol); } else { factory.useSslProtocol(); } } } catch (Exception e) { this.logger.warn("Could not set SSL protocol on connection factory, {}. SSL set off.", this, e); this.ssl = false; } } private void maybeEnableHostnameVerification(com.rabbitmq.client.ConnectionFactory factory) { if (hostnameVerification) { if (this.ssl) { factory.enableHostnameVerification(); } else { logger.warn("Hostname verification enabled, but not TLS, please enable TLS too."); } } } private void setSaslConfig(com.rabbitmq.client.ConnectionFactory factory, AuthenticationMechanism authenticationMechanism) { switch (authenticationMechanism) { case PLAIN: factory.setSaslConfig(DefaultSaslConfig.PLAIN); break; case EXTERNAL: factory.setSaslConfig(DefaultSaslConfig.EXTERNAL); break; default: throw new IllegalArgumentException("Unhandled AuthenticationMechanism: " + authenticationMechanism); } } public boolean isSsl() { return this.ssl; } /** * @deprecated Use {@link #useSslProtocol()}, {@link #useSslProtocol(String)} * or {@link #useSslProtocol(SSLContext)}. * @param ssl if true, enables TLS for connections opened */ @Deprecated public void setSsl(boolean ssl) { this.ssl = ssl; } /** * Enables TLS on opened connections with the highest TLS * version available. * @throws NoSuchAlgorithmException see {@link NoSuchAlgorithmException} */ public void useSslProtocol() throws NoSuchAlgorithmException { this.useSslProtocol( com.rabbitmq.client.ConnectionFactory.computeDefaultTlsProtocol( SSLContext.getDefault().getSupportedSSLParameters().getProtocols())); } /** * Enables TLS on opened connections using the provided TLS protocol * version. * @param protocol TLS or SSL protocol version. * @see JDK documentation on protocol names */ public void useSslProtocol(String protocol) { this.tlsProtocol = protocol; this.ssl = true; } /** * Enables TLS on opened connections using the provided {@link SSLContext}. * @param context {@link SSLContext} to use */ public void useSslProtocol(SSLContext context) { this.sslContext = context; this.ssl = true; } /** * Whether to use the default {@link SSLContext} or not. * Default is false. * * When this option is enabled, the default {@link SSLContext} * will always be used and will override any other {@link SSLContext} * set. * * @param useDefaultSslContext * @see SSLContext#getDefault() */ public void useDefaultSslContext(boolean useDefaultSslContext) { this.useDefaultSslContext = useDefaultSslContext; this.ssl = true; } /** * Whether to use the default {@link SSLContext} or not. * * @see SSLContext#getDefault() */ public boolean isUseDefaultSslContext() { return useDefaultSslContext; } /** * Whether to use the default {@link SSLContext} or not. * Default is false. * * When this option is enabled, the default {@link SSLContext} * will always be used and will override any other {@link SSLContext} * set. * * @param useDefaultSslContext * @see SSLContext#getDefault() */ public void setUseDefaultSslContext(boolean useDefaultSslContext) { this.useDefaultSslContext(useDefaultSslContext); } private static String getScheme(boolean isSsl) { return (isSsl ? "amqps" : "amqp"); } private static String uriUInfoEscape(String user, String pass) { if (null == user) return null; if (null == pass) return encUserinfo(user, "UTF-8"); return encUserinfo(user + ":" + pass, "UTF-8"); } private static String uriHostEscape(String host) { return encHost(host, "UTF-8"); } private static String uriVirtualHostEscape(String vHost) { return encSegment(vHost, "UTF-8"); } /** * {@inheritDoc} */ @Override public Reference getReference() throws NamingException { Reference ref = new Reference(RMQConnectionFactory.class.getName(), RMQObjectFactory.class.getName(), null); addStringRefProperty(ref, "uri", this.getUri()); addStringRefProperty(ref, "host", this.getHost()); addStringRefProperty(ref, "password", this.getPassword()); addIntegerRefProperty(ref, "port", this.getPort()); addIntegerRefProperty(ref, "queueBrowserReadMax", this.getQueueBrowserReadMax()); addIntegerRefProperty(ref, "onMessageTimeoutMs", this.getOnMessageTimeoutMs()); addIntegerRefProperty(ref, "channelsQos", this.getChannelsQos()); addBooleanProperty(ref, "ssl", this.ssl); addLongRefProperty(ref, "terminationTimeout", this.getTerminationTimeout()); addStringRefProperty(ref, "username", this.getUsername()); addStringRefProperty(ref, "virtualHost", this.getVirtualHost()); addBooleanProperty(ref, "cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose", this.isCleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose()); addBooleanProperty(ref, "declareReplyToDestination", this.declareReplyToDestination); addStringRefProperty(ref, "authenticationMechanism", this.authenticationMechanism.name()); return ref; } /** * Adds a String valued property to a Reference (as a RefAddr) * @param ref - the reference to contain the value * @param propertyName - the name of the property * @param value - the value to store with the property */ private static void addStringRefProperty(Reference ref, String propertyName, String value) { if (value==null || propertyName==null) return; RefAddr ra = new StringRefAddr(propertyName, value); ref.add(ra); } /** * Adds an integer valued property to a Reference (as a RefAddr). * @param ref - the reference to contain the value * @param propertyName - the name of the property * @param value - the value to store with the property */ private static void addIntegerRefProperty(Reference ref, String propertyName, Integer value) { if (value == null || propertyName == null) return; RefAddr ra = new StringRefAddr(propertyName, String.valueOf(value)); ref.add(ra); } /** * Adds an long valued property to a Reference (as a RefAddr). * @param ref - the reference to contain the value * @param propertyName - the name of the property * @param value - the value to store with the property */ private static void addLongRefProperty(Reference ref, String propertyName, Long value) { if (value == null || propertyName == null) return; RefAddr ra = new StringRefAddr(propertyName, String.valueOf(value)); ref.add(ra); } /** * Adds a boolean valued property to a Reference (as a StringRefAddr) if the value is true * (default false on read assumed). * @param ref - the reference to contain the value * @param propertyName - the name of the property * @param value - the value to store with the property */ private static final void addBooleanProperty(Reference ref, String propertyName, boolean value) { if (propertyName==null) return; RefAddr ra = new StringRefAddr(propertyName, String.valueOf(value)); ref.add(ra); } /** * {@inheritDoc} */ @Override public TopicConnection createTopicConnection() throws JMSException { return (TopicConnection) this.createConnection(); } /** * {@inheritDoc} */ @Override public TopicConnection createTopicConnection(String userName, String password) throws JMSException { return (TopicConnection) this.createConnection(userName, password); } /** * {@inheritDoc} */ @Override public QueueConnection createQueueConnection() throws JMSException { return (QueueConnection) this.createConnection(); } /** * {@inheritDoc} */ @Override public QueueConnection createQueueConnection(String userName, String password) throws JMSException { return (QueueConnection) this.createConnection(userName, password); } /** * Returns the configured username used when creating a connection If * {@link RMQConnectionFactory#setUsername(String)} has not been called the default value of 'guest' is returned. * * @return a string representing the username for a RabbitMQ connection */ public String getUsername() { return username; } /** * Sets the username to be used when creating a connection to the RabbitMQ broker. * If the parameter is null the current username is not changed. * * @param username - username to be used when creating a connection to the RabbitMQ broker */ public void setUsername(String username) { if (username != null) this.username = username; else this.logger.warn("Cannot set username to null (on {})", this); } /** * Returns the configured password used when creating a connection If * {@link RMQConnectionFactory#setPassword(String)} has not been called the default value of 'guest' is returned. * * @return a string representing the password for a Rabbit connection */ public String getPassword() { return password; } /** * Sets the password to be used when creating a connection to the RabbitMQ broker * * @param password - password to be used when creating a connection to the RabbitMQ broker */ public void setPassword(String password) { this.password = password; } /** * Returns the virtual host used when creating a connection. If * {@link RMQConnectionFactory#setVirtualHost(String)} has not been called the default value of '/' is returned. * * @return a String representing the virtual host for a RabbitMQ connection */ public String getVirtualHost() { return virtualHost; } /** * Sets the virtualHost to be used when creating a connection to the RabbitMQ broker. * If the parameter is null the current virtualHost is not changed. * * @param virtualHost - virtual host to be used when creating a connection to the RabbitMQ broker */ public void setVirtualHost(String virtualHost) { if (virtualHost != null) this.virtualHost = virtualHost; else this.logger.warn("Cannot set virtualHost to null (on {})", this); } /** * Returns the host name to be used when creating a connection to the RabbitMQ broker. * * @return the host name of the RabbitMQ broker */ public String getHost() { return host; } /** * Sets the host of the RabbitMQ broker. The host name can be an IP address or a host name. * If the parameter is null the current host name is not changed. * * @param host - IP address or a host name of the RabbitMQ broker, in String form */ public void setHost(String host) { if (host != null) this.host = host; else this.logger.warn("Cannot set host to null (on {})", this); } /** * Returns the port the RabbitMQ broker listens to; this port is used to connect to the broker. * If the port has not been set (defaults to -1) then the default port for this type of connection is returned. * * @return the port the RabbitMQ broker listens to */ public int getPort() { return this.port!=-1 ? this.port : isSsl() ? DEFAULT_RABBITMQ_SSL_PORT : DEFAULT_RABBITMQ_PORT; } /** * Set the port to be used when making a connection to the RabbitMQ broker. This is the port number the broker will listen on. * Setting this to -1 means take the RabbitMQ default (which depends on the type of connection). * * @param port - a TCP port number */ public void setPort(int port) { this.port = port; } /** * Returns the time to wait in milliseconds when {@link Connection#close()} has been called for listeners and threads to * complete. * * @return the duration in milliseconds for which the {@link Connection#close()} waits before continuing shutdown sequence */ public long getTerminationTimeout() { return terminationTimeout; } /** * Sets terminationTimeout: the time in milliseconds a {@link Connection#close()} should wait for threads/tasks/listeners to complete * * @param terminationTimeout - duration in milliseconds */ public void setTerminationTimeout(long terminationTimeout) { this.terminationTimeout = terminationTimeout; } /** * Returns the maximum number of messages to read on a queue browser, or zero if there is no limit. * * @return the maximum number of messages to read on a queue browser */ public int getQueueBrowserReadMax() { return this.queueBrowserReadMax; } /** * Sets queueBrowserReadMax: the maximum number of messages to read on a queue browser. * Non-positive values are set to zero, which is interpreted as no limit. * * @param queueBrowserReadMax - read no more than this number of messages on a queue browser. */ public void setQueueBrowserReadMax(int queueBrowserReadMax) { this.queueBrowserReadMax = Math.max(0, queueBrowserReadMax); } /** * Returns the time in milliseconds {@link MessageListener#onMessage(Message)} can take to process a message * @return the time in milliseconds {@link MessageListener#onMessage(Message)} can take to process a message */ public int getOnMessageTimeoutMs() { return this.onMessageTimeoutMs; } /** * Sets onMessageTimeoutMs: the time in milliseconds {@link MessageListener#onMessage(Message)} can take to process a message. * Non-positive values are rejected. * @param onMessageTimeoutMs - duration in milliseconds */ public void setOnMessageTimeoutMs(int onMessageTimeoutMs){ if (onMessageTimeoutMs > 0) this.onMessageTimeoutMs = onMessageTimeoutMs; else this.logger.warn("Cannot set onMessageTimeoutMs to non-positive value {} (on {})", onMessageTimeoutMs, this); } /** * QoS setting for channels created by this connection factory. * * @see com.rabbitmq.client.Channel#basicQos(int) */ public int getChannelsQos() { return channelsQos; } /** * QoS setting for channels created by this connection factory. * * @see com.rabbitmq.client.Channel#basicQos(int) * @param channelsQos maximum number of messages that the server * will deliver, 0 if unlimited */ public void setChannelsQos(int channelsQos) { this.channelsQos = channelsQos; } /** * Whether {@link MessageProducer} properties (delivery mode, * priority, TTL) take precedence over respective {@link Message} * properties or not. * Default is true (which is compliant to the JMS specification). */ public void setPreferProducerMessageProperty(boolean preferProducerMessageProperty) { this.preferProducerMessageProperty = preferProducerMessageProperty; } public boolean isPreferProducerMessageProperty() { return preferProducerMessageProperty; } /** * Whether requeue message on {@link RuntimeException} in the * {@link jakarta.jms.MessageListener} or not. * * Default is false. * * @since 1.7.0 * @see RMQConnectionFactory#setRequeueOnTimeout(boolean) */ public void setRequeueOnMessageListenerException(boolean requeueOnMessageListenerException) { this.requeueOnMessageListenerException = requeueOnMessageListenerException; } public boolean isRequeueOnMessageListenerException() { return requeueOnMessageListenerException; } /** * Whether to nack messages on rollback or not. * * Nack-ed messages will be discarded, not re-queued. Queues * will typically have dead lettering * configured when enabling this feature, so nack-ed messages are routed * elsewhere and not discarded forever. *

* Default is false. * * @param nackOnRollback true to nack and discard messages on rollback, false to requeue them * @see Negative Acknowledgements * @see Dead Letter Exchanges * @since 1.14.0 */ public void setNackOnRollback(boolean nackOnRollback) { this.nackOnRollback = nackOnRollback; } public boolean isNackOnRollback() { return nackOnRollback; } public void setCleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose(boolean cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose) { this.cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose = cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose; } public boolean isCleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose() { return this.cleanUpServerNamedQueuesForNonDurableTopicsOnSessionClose; } public void setAmqpPropertiesCustomiser(BiFunction amqpPropertiesCustomiser) { this.amqpPropertiesCustomiser = amqpPropertiesCustomiser; } /** * Enable or disable hostname verification when TLS is used. * * @param hostnameVerification * @see com.rabbitmq.client.ConnectionFactory#enableHostnameVerification() * @since 1.10.0 */ public void setHostnameVerification(boolean hostnameVerification) { this.hostnameVerification = hostnameVerification; } /** * Set the collector for AMQP-client metrics. * * @param metricsCollector * @since 1.10.0 * @see com.rabbitmq.client.ConnectionFactory#setMetricsCollector(MetricsCollector) */ public void setMetricsCollector(MetricsCollector metricsCollector) { this.metricsCollector = metricsCollector; } public List getUris() { return this.uris.stream().map(uri -> uri.toString()).collect(Collectors.toList()); } /** * Set a post-processor for the AMQP {@link com.rabbitmq.client.ConnectionFactory}. *

* The post-processor is called before the AMQP connection creation. This callback can be * useful to customize the {@link com.rabbitmq.client.ConnectionFactory}: * TLS-related configuration, metrics collection, etc. * * @param amqpConnectionFactoryPostProcessor * @since 1.10.0 */ public void setAmqpConnectionFactoryPostProcessor(Consumer amqpConnectionFactoryPostProcessor) { this.amqpConnectionFactoryPostProcessor = amqpConnectionFactoryPostProcessor; } /** * Sets a post-processor for the created {@link com.rabbitmq.client.Connection}. *

* The post-processor is called after the {@link com.rabbitmq.client.Connection} is created and established. This callback * can be used to customize the {@link com.rabbitmq.client.Connection} e.g. adding a {@link com.rabbitmq.client.BlockedListener} * that emits a log message when this connection gets blocked: *

     * {@code
     * RMQConnectionFactory factory = new RMQConnectionFactory();
     * // ...
     * factory.setAmqpConnectionPostProcessor(connection ->
     *                 connection.addBlockedListener(
     *                         reason -> log.warn("Connection blocked: {}", reason),
     *                         () -> log.info("Connection unblocked"))
     *         );
     * }
     * 
* * @param amqpConnectionPostProcessor callback that processes the AMQP connections after they are established * @since 2.10.0 */ public void setAmqpConnectionPostProcessor(Consumer amqpConnectionPostProcessor) { this.amqpConnectionPostProcessor = amqpConnectionPostProcessor; } /** * Set callback called before sending a message. * Can be used to customize the message or the destination * before the message is actually sent. * * @see SendingContextConsumer * @see com.rabbitmq.jms.client.SendingContext * @since 1.11.0 */ public void setSendingContextConsumer(SendingContextConsumer sendingContextConsumer) { this.sendingContextConsumer = sendingContextConsumer; } /** * Set callback called before dispatching a received message to application code. * Can be used to customize messages before they handed * over application. * * @param receivingContextConsumer * @see ReceivingContextConsumer * @since 1.11.0 */ public void setReceivingContextConsumer(ReceivingContextConsumer receivingContextConsumer) { this.receivingContextConsumer = receivingContextConsumer; } /** * Whether replyTo destination for consumed messages should be declared. *

* Default is true. Set this value to false for the * server-side of RPC, this avoids creating a temporary reply-to destination on * both client and server, leading to an error. *

* This is implemented as {@link ReceivingContextConsumer}. * * @see RMQConnectionFactory#setReceivingContextConsumer(ReceivingContextConsumer) * @since 1.11.0 */ public void setDeclareReplyToDestination(boolean declareReplyToDestination) { this.declareReplyToDestination = declareReplyToDestination; } /** * Sets the strategy to use when receiving messages with a reply-to * specified. * * @param replyToStrategy The reply to strategy. */ public void setReplyToStrategy(final ReplyToStrategy replyToStrategy) { this.replyToStrategy = replyToStrategy; } /** * Gets ths reply to strategy to use when receiving messages with a * reply-to specified. * * @return The strategy. */ public ReplyToStrategy getReplyToStrategy() { return replyToStrategy; } /** * Sets the authentication mechanism to use. * * @param authenticationMechanism authentication mechanism */ public void setAuthenticationMechanism(AuthenticationMechanism authenticationMechanism) { this.authenticationMechanism = authenticationMechanism; } /** * Whether to requeue a message that timed out or not. * * Only taken into account if requeueOnMessageListenerException is true. * Default is false. * * @since 2.3.0 * @see RMQConnectionFactory#setRequeueOnMessageListenerException(boolean) */ public void setRequeueOnTimeout(boolean requeueOnTimeout) { this.requeueOnTimeout = requeueOnTimeout; } public void setKeepTextMessageType(boolean keepTextMessageType) { this.keepTextMessageType = keepTextMessageType; } @FunctionalInterface private interface ConnectionCreator { com.rabbitmq.client.Connection create(com.rabbitmq.client.ConnectionFactory cf) throws Exception; } private static final class NoOpMetricsCollector implements MetricsCollector, Serializable { private static final long serialVersionUID = 1L; @Override public void newConnection(com.rabbitmq.client.Connection connection) { } @Override public void closeConnection(com.rabbitmq.client.Connection connection) { } @Override public void newChannel(Channel channel) { } @Override public void closeChannel(Channel channel) { } @Override public void basicPublish(Channel channel) { } @Override public void consumedMessage(Channel channel, long deliveryTag, boolean autoAck) { } @Override public void consumedMessage(Channel channel, long deliveryTag, String consumerTag) { } @Override public void basicAck(Channel channel, long deliveryTag, boolean multiple) { } @Override public void basicNack(Channel channel, long deliveryTag) { } @Override public void basicReject(Channel channel, long deliveryTag) { } @Override public void basicConsume(Channel channel, String consumerTag, boolean autoAck) { } @Override public void basicCancel(Channel channel, String consumerTag) { } } private static final class NoOpSerializableConsumer implements Consumer, Serializable { private static final long serialVersionUID = 1L; @Override public void accept(T t) { } } private static final class NoOpSerializableSendingContextConsumer implements SendingContextConsumer, Serializable { private static final long serialVersionUID = 1L; @Override public void accept(SendingContext sendingContext) { } } private static final class NoOpSerializableReceivingContextConsumer implements ReceivingContextConsumer, Serializable { private static final long serialVersionUID = 1L; @Override public void accept(ReceivingContext receivingContext) { } } @Override public JMSContext createContext() { return createContext(this.username, this.password, Session.AUTO_ACKNOWLEDGE); } @Override public JMSContext createContext(String username, String password) { return createContext(username, password, Session.AUTO_ACKNOWLEDGE); } @Override public JMSContext createContext(String username, String password, int sessionMode) { try { RMQConnection connection = (RMQConnection) createConnection(username, password); return new RmqJmsContext(connection, sessionMode); } catch (JMSException e) { throw new JMSRuntimeException("Error while creating JMSContext", e.getErrorCode(), e); } } @Override public JMSContext createContext(int sessionMode) { return createContext(this.username, this.password, sessionMode); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy