List of usage examples for org.springframework.amqp.rabbit.connection RabbitResourceHolder RabbitResourceHolder
public RabbitResourceHolder(Channel channel, boolean releaseAfterCompletion)
From source file:org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.java
/** * Invoke the specified listener: either as standard MessageListener or (preferably) as SessionAwareMessageListener. * @param channel the Rabbit Channel to operate on * @param message the received Rabbit Message * @throws Exception if thrown by Rabbit API methods * @see #setMessageListener/*from ww w . j av a 2s .c o m*/ */ protected void actualInvokeListener(Channel channel, Message message) throws Exception { Object listener = getMessageListener(); if (listener instanceof ChannelAwareMessageListener) { doInvokeListener((ChannelAwareMessageListener) listener, channel, message); } else if (listener instanceof MessageListener) { boolean bindChannel = isExposeListenerChannel() && isChannelLocallyTransacted(); if (bindChannel) { RabbitResourceHolder resourceHolder = new RabbitResourceHolder(channel, false); resourceHolder.setSynchronizedWithTransaction(true); TransactionSynchronizationManager.bindResource(this.getConnectionFactory(), resourceHolder); } try { doInvokeListener((MessageListener) listener, message); } finally { if (bindChannel) { // unbind if we bound TransactionSynchronizationManager.unbindResource(this.getConnectionFactory()); } } } else if (listener != null) { throw new FatalListenerExecutionException( "Only MessageListener and SessionAwareMessageListener supported: " + listener); } else { throw new FatalListenerExecutionException( "No message listener specified - see property 'messageListener'"); } }
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>/* ww w. ja v a 2s.c o m*/ * 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.SimpleMessageListenerContainer.java
private boolean receiveAndExecute(final BlockingQueueConsumer consumer) throws Throwable { if (this.transactionManager != null) { try {//from www.jav a2 s . c o m return new TransactionTemplate(this.transactionManager, this.transactionAttribute) .execute(new TransactionCallback<Boolean>() { @Override public Boolean doInTransaction(TransactionStatus status) { ConnectionFactoryUtils.bindResourceToTransaction( new RabbitResourceHolder(consumer.getChannel(), false), getConnectionFactory(), true); try { return doReceiveAndExecute(consumer); } catch (RuntimeException e) { throw e; } catch (Throwable e) { //NOSONAR // ok to catch Throwable here because we re-throw it below throw new WrappedTransactionException(e); } } }); } catch (WrappedTransactionException e) { throw e.getCause(); } } return doReceiveAndExecute(consumer); }