List of usage examples for org.springframework.amqp.rabbit.connection RabbitUtils commitIfNecessary
public static void commitIfNecessary(Channel channel)
From source file:org.kurento.rabbitmq.RabbitTemplate.java
/** * Send the given message to the specified exchange. * * @param channel//from w w w . j av a 2s.co m * The RabbitMQ Channel to operate within. * @param exchange * The name of the RabbitMQ exchange to send to. * @param routingKey * The routing key. * @param message * The Message to send. * @param correlationData * The correlation data. * @throws IOException * If thrown by RabbitMQ API methods */ protected void doSend(Channel channel, String exchange, String routingKey, Message message, CorrelationData correlationData) throws Exception { if (logger.isDebugEnabled()) { logger.debug("Publishing message on exchange [" + exchange + "], routingKey = [" + routingKey + "]"); } if (exchange == null) { // try to send to configured exchange exchange = this.exchange; } if (routingKey == null) { // try to send to configured routing key routingKey = this.routingKey; } if (this.confirmCallback != null && channel instanceof PublisherCallbackChannel) { PublisherCallbackChannel publisherCallbackChannel = (PublisherCallbackChannel) channel; publisherCallbackChannel.addPendingConfirm(this, channel.getNextPublishSeqNo(), new PendingConfirm(correlationData, System.currentTimeMillis())); } boolean mandatory = this.returnCallback != null && this.mandatory; MessageProperties messageProperties = message.getMessageProperties(); if (mandatory) { messageProperties.getHeaders().put(PublisherCallbackChannel.RETURN_CORRELATION, this.uuid); } BasicProperties convertedMessageProperties = this.messagePropertiesConverter .fromMessageProperties(messageProperties, encoding); channel.basicPublish(exchange, routingKey, mandatory, convertedMessageProperties, message.getBody()); // Check if commit needed if (isChannelLocallyTransacted(channel)) { // Transacted channel created by this template -> commit. RabbitUtils.commitIfNecessary(channel); } }
From source file:org.springframework.amqp.rabbit.connection.RabbitResourceHolder.java
public void rollbackAll() { for (Channel channel : this.channels) { if (logger.isDebugEnabled()) { logger.debug("Rolling back messages to channel: " + channel); }//from w w w .ja v a2 s.c o m RabbitUtils.rollbackIfNecessary(channel); if (deliveryTags.containsKey(channel)) { for (Long deliveryTag : deliveryTags.get(channel)) { try { channel.basicReject(deliveryTag, true); } catch (IOException ex) { throw new AmqpIOException(ex); } } // Need to commit the reject (=nack) RabbitUtils.commitIfNecessary(channel); } } }
From source file:org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.java
/** * Invoke the specified listener as Spring ChannelAwareMessageListener, exposing a new Rabbit Session (potentially * with its own transaction) to the listener if demanded. * @param listener the Spring ChannelAwareMessageListener to invoke * @param channel the Rabbit Channel to operate on * @param message the received Rabbit Message * @throws Exception if thrown by Rabbit API methods or listener itself. * <p>//from w ww . ja va2 s. com * Exception thrown from listener will be wrapped to {@link ListenerExecutionFailedException}. * @see ChannelAwareMessageListener * @see #setExposeListenerChannel(boolean) */ protected void doInvokeListener(ChannelAwareMessageListener listener, Channel channel, Message message) throws Exception { RabbitResourceHolder resourceHolder = null; Channel channelToUse = channel; boolean boundHere = false; try { if (!isExposeListenerChannel()) { // We need to expose a separate Channel. resourceHolder = getTransactionalResourceHolder(); channelToUse = resourceHolder.getChannel(); /* * If there is a real transaction, the resource will have been bound; otherwise * we need to bind it temporarily here. Any work done on this channel * will be committed in the finally block. */ if (isChannelLocallyTransacted() && !TransactionSynchronizationManager.isActualTransactionActive()) { resourceHolder.setSynchronizedWithTransaction(true); TransactionSynchronizationManager.bindResource(this.getConnectionFactory(), resourceHolder); boundHere = true; } } else { // if locally transacted, bind the current channel to make it available to RabbitTemplate if (isChannelLocallyTransacted()) { RabbitResourceHolder localResourceHolder = new RabbitResourceHolder(channelToUse, false); localResourceHolder.setSynchronizedWithTransaction(true); TransactionSynchronizationManager.bindResource(this.getConnectionFactory(), localResourceHolder); boundHere = true; } } // Actually invoke the message listener... try { listener.onMessage(message, channelToUse); } catch (Exception e) { throw wrapToListenerExecutionFailedExceptionIfNeeded(e, message); } } finally { if (resourceHolder != null && boundHere) { // so the channel exposed (because exposeListenerChannel is false) will be closed resourceHolder.setSynchronizedWithTransaction(false); } ConnectionFactoryUtils.releaseResources(resourceHolder); if (boundHere) { // unbind if we bound TransactionSynchronizationManager.unbindResource(this.getConnectionFactory()); if (!isExposeListenerChannel() && isChannelLocallyTransacted()) { /* * commit the temporary channel we exposed; the consumer's channel * will be committed later. Note that when exposing a different channel * when there's no transaction manager, the exposed channel is committed * on each message, and not based on txSize. */ RabbitUtils.commitIfNecessary(channelToUse); } } } }
From source file:org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.java
/** * Perform a rollback, handling rollback exceptions properly. * //from w w w. jav a2s. co m * @param ex * the thrown application exception or error * @throws Exception * in case of a rollback error */ public void rollbackOnExceptionIfNecessary(Throwable ex) throws Exception { boolean ackRequired = !acknowledgeMode.isAutoAck() && !acknowledgeMode.isManual(); try { if (transactional) { if (logger.isDebugEnabled()) { logger.debug("Initiating transaction rollback on application exception: " + ex); } RabbitUtils.rollbackIfNecessary(channel); } if (ackRequired) { if (logger.isDebugEnabled()) { logger.debug("Rejecting messages"); } boolean shouldRequeue = this.defaultRequeuRejected; Throwable t = ex; while (shouldRequeue && t != null) { if (t instanceof AmqpRejectAndDontRequeueException) { shouldRequeue = false; } t = t.getCause(); } for (Long deliveryTag : deliveryTags) { // With newer RabbitMQ brokers could use basicNack here... channel.basicReject(deliveryTag, shouldRequeue); } if (transactional) { // Need to commit the reject (=nack) RabbitUtils.commitIfNecessary(channel); } } } catch (Exception e) { logger.error("Application exception overridden by rollback exception", ex); throw e; } finally { deliveryTags.clear(); retryDeliveryTags.clear(); } }
From source file:org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.java
/** * Perform a commit or message acknowledgement, as appropriate. * /*from w w w .j a v a2s .c om*/ * @param locallyTransacted * @throws IOException */ public boolean commitIfNecessary(boolean locallyTransacted) throws IOException { if (deliveryTags.isEmpty()) { return false; } try { boolean ackRequired = !acknowledgeMode.isAutoAck() && !acknowledgeMode.isManual(); if (ackRequired) { if (transactional && !locallyTransacted) { // Not locally transacted but it is transacted so it // could be synchronized with an external transaction for (Long deliveryTag : deliveryTags) { ConnectionFactoryUtils.registerDeliveryTag(connectionFactory, channel, deliveryTag); } } else { if (!deliveryTags.isEmpty()) { long deliveryTag = new ArrayList<Long>(deliveryTags).get(deliveryTags.size() - 1); channel.basicAck(deliveryTag, true); } } } if (locallyTransacted) { // For manual acks we still need to commit RabbitUtils.commitIfNecessary(channel); } } finally { deliveryTags.clear(); retryDeliveryTags.clear(); } return true; }