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

io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.retry.RepublishMessageRecoverer Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2014-2016 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
 *
 *      http://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 io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.rabbit.retry;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Map;

import io.bitsensor.plugins.shaded.org.apache.commons.logging.Log;
import io.bitsensor.plugins.shaded.org.apache.commons.logging.LogFactory;

import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.core.AmqpTemplate;
import io.bitsensor.plugins.shaded.io.bitsensor.plugins.shaded.org.springframework.amqp.core.Message;
import io.bitsensor.plugins.shaded.org.springframework.util.Assert;

/**
 * {@link MessageRecoverer} implementation that republishes recovered messages
 * to a specified exchange with the exception stack trace stored in the
 * message header x-exception.
 * 

* If no routing key is provided, the original routing key for the message, * prefixed with {@link #setErrorRoutingKeyPrefix(String)} (default "error.") * will be used to publish the message to the exchange provided in * name, or the template's default exchange if none is set. * * @author James Carr * @author Gary Russell * @since 1.3 */ public class RepublishMessageRecoverer implements MessageRecoverer { public static final String X_EXCEPTION_STACKTRACE = "x-exception-stacktrace"; public static final String X_EXCEPTION_MESSAGE = "x-exception-message"; public static final String X_ORIGINAL_EXCHANGE = "x-original-exchange"; public static final String X_ORIGINAL_ROUTING_KEY = "x-original-routingKey"; private final Log logger = LogFactory.getLog(getClass()); private final AmqpTemplate errorTemplate; private final String errorRoutingKey; private volatile String errorRoutingKeyPrefix = "error."; private final String errorExchangeName; public RepublishMessageRecoverer(AmqpTemplate errorTemplate) { this(errorTemplate, null, null); } public RepublishMessageRecoverer(AmqpTemplate errorTemplate, String errorExchange) { this(errorTemplate, errorExchange, null); } public RepublishMessageRecoverer(AmqpTemplate errorTemplate, String errorExchange, String errorRoutingKey) { Assert.notNull(errorTemplate, "'errorTemplate' cannot be null"); this.errorTemplate = errorTemplate; this.errorExchangeName = errorExchange; this.errorRoutingKey = errorRoutingKey; } /** * Apply a prefix to the outbound routing key, which will be prefixed to the original message * routing key (if no explicit routing key was provided in the constructor; ignored otherwise. * Use an empty string ("") for no prefixing. * @param errorRoutingKeyPrefix The prefix (default "error."). * @return this. */ public RepublishMessageRecoverer errorRoutingKeyPrefix(String errorRoutingKeyPrefix) { this.setErrorRoutingKeyPrefix(errorRoutingKeyPrefix); return this; } /** * @see #errorRoutingKeyPrefix(String) * @param errorRoutingKeyPrefix The prefix (default "error."). */ public void setErrorRoutingKeyPrefix(String errorRoutingKeyPrefix) { Assert.notNull(errorRoutingKeyPrefix, "'errorRoutingKeyPrefix' cannot be null"); this.errorRoutingKeyPrefix = errorRoutingKeyPrefix; } @Override public void recover(Message message, Throwable cause) { Map headers = message.getMessageProperties().getHeaders(); headers.put(X_EXCEPTION_STACKTRACE, getStackTraceAsString(cause)); headers.put(X_EXCEPTION_MESSAGE, cause.getCause() != null ? cause.getCause().getMessage() : cause.getMessage()); headers.put(X_ORIGINAL_EXCHANGE, message.getMessageProperties().getReceivedExchange()); headers.put(X_ORIGINAL_ROUTING_KEY, message.getMessageProperties().getReceivedRoutingKey()); Map additionalHeaders = additionalHeaders(message, cause); if (additionalHeaders != null) { headers.putAll(additionalHeaders); } if (null != this.errorExchangeName) { String routingKey = this.errorRoutingKey != null ? this.errorRoutingKey : this.prefixedOriginalRoutingKey(message); this.errorTemplate.send(this.errorExchangeName, routingKey, message); if (this.logger.isWarnEnabled()) { this.logger.warn("Republishing failed message to exchange " + this.errorExchangeName); } } else { final String routingKey = this.prefixedOriginalRoutingKey(message); this.errorTemplate.send(routingKey, message); if (this.logger.isWarnEnabled()) { this.logger.warn("Republishing failed message to the template's default exchange with routing key " + routingKey); } } } /** * Subclasses can override this method to add more headers to the republished message. * @param message The failed message. * @param cause The cause. * @return A {@link Map} of additional headers to add. */ protected Map additionalHeaders(Message message, Throwable cause) { return null; } private String prefixedOriginalRoutingKey(Message message) { return this.errorRoutingKeyPrefix + message.getMessageProperties().getReceivedRoutingKey(); } private String getStackTraceAsString(Throwable cause) { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter, true); cause.printStackTrace(printWriter); return stringWriter.getBuffer().toString(); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy