class RepublishMessageRecoverer implements MessageRecoverer {

	@Override
	public void recover(Message message, Throwable cause) {
		MessageProperties messageProperties = message.getMessageProperties();
		Map<String, Object> headers = messageProperties.getHeaders();
		String exceptionMessage = cause.getCause() != null ? cause.getCause().getMessage() : cause.getMessage();
		String[] processed = processStackTrace(cause, exceptionMessage);
		String stackTraceAsString = processed[0];
		String truncatedExceptionMessage = processed[1];
		if (truncatedExceptionMessage != null) {
			exceptionMessage = truncatedExceptionMessage;
		}
		headers.put(X_EXCEPTION_STACKTRACE, stackTraceAsString);
		headers.put(X_EXCEPTION_MESSAGE, exceptionMessage);
		headers.put(X_ORIGINAL_EXCHANGE, messageProperties.getReceivedExchange());
		headers.put(X_ORIGINAL_ROUTING_KEY, messageProperties.getReceivedRoutingKey());
		Map<? extends String, ?> additionalHeaders = additionalHeaders(message, cause);
		if (additionalHeaders != null) {
			headers.putAll(additionalHeaders);
		}

		if (messageProperties.getDeliveryMode() == null) {
			messageProperties.setDeliveryMode(this.deliveryMode);
		}

		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
						+ "' with routing key " + routingKey);
			}
		}
		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);
			}
		}
	}

	public  RepublishMessageRecoverer(AmqpTemplate errorTemplate);
	public  RepublishMessageRecoverer(AmqpTemplate errorTemplate, String errorExchange);
	public  RepublishMessageRecoverer(AmqpTemplate errorTemplate, String errorExchange, String errorRoutingKey);

}