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

fi.evolver.basics.spring.messaging.sender.aws.SnsSender Maven / Gradle / Ivy

package fi.evolver.basics.spring.messaging.sender.aws;

import static fi.evolver.basics.spring.messaging.sender.aws.AwsUtils.STATUS_FAILED;
import static fi.evolver.basics.spring.messaging.sender.aws.AwsUtils.STATUS_OK;

import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Set;

import org.apache.commons.io.IOUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import fi.evolver.basics.spring.log.MessageLogService;
import fi.evolver.basics.spring.log.entity.MessageLog.Direction;
import fi.evolver.basics.spring.messaging.SendResult;
import fi.evolver.basics.spring.messaging.entity.Message;
import fi.evolver.basics.spring.messaging.sender.Sender;
import fi.evolver.basics.spring.messaging.util.SendUtils;
import fi.evolver.utils.CommunicationException;
import software.amazon.awssdk.auth.credentials.AwsCredentialsProvider;
import software.amazon.awssdk.core.client.config.ClientOverrideConfiguration;
import software.amazon.awssdk.regions.Region;
import software.amazon.awssdk.services.sns.SnsClient;
import software.amazon.awssdk.services.sns.SnsClientBuilder;

@Component
public class SnsSender implements Sender {
	private static final Logger LOG = LoggerFactory.getLogger(SnsSender.class);

	private static final String PROTOCOL_SNS = "sns";

	private static final String PROPERTY_SNS_TOPIC_ARN = "TopicArn";

	private final MessageLogService logHandler;


	@Autowired
	public SnsSender(MessageLogService messageLogService) {
		this.logHandler = messageLogService;
	}

	@Override
	public SendResult send(Message message, URI uri) {
		return publishMessageToSns(message, uri);
	}

	@Override
	public Set getSupportedProtocols() {
		return Set.of(PROTOCOL_SNS);
	}

	private SendResult publishMessageToSns(Message message, URI uri) {
		LocalDateTime start = LocalDateTime.now();
		String statusCode = STATUS_FAILED;
		String body = null;

		try (Reader reader = new InputStreamReader(message.getDataStream(), StandardCharsets.UTF_8)) {
			AwsCredentialsProvider credentialsProvider = AwsUtils.createCredentialsProvider(message, Region.of(uri.getHost()));
			ClientOverrideConfiguration config = AwsUtils.buildClientConfiguration(message);

			body = IOUtils.toString(reader);
			if (body != null && !body.isEmpty())
				publishToSns(message, body, uri, config, credentialsProvider);
			statusCode = STATUS_OK;
			return SendResult.success();
		}
		catch (IOException e) {
			LOG.warn("SNS publish failed", e);
			return SendResult.error("SNS publish failed: %s", e.getMessage());
		}
		finally {
			logHandler.logMessage(
					start,
					message.getMessageType(),
					"sns",
					uri.toString(),
					logHandler.getApplicationName(),
					message.getTargetSystem(),
					Direction.OUTBOUND,
					body,
					AwsUtils.removeRequestParameterValueMap(message),
					null,
					null,
					statusCode,
					null,
					SendUtils.mapMetadata(message.getMetadata()));
		}
	}

	public static void publishToSns(Message message, String text, URI uri, ClientOverrideConfiguration config, AwsCredentialsProvider credentialsProvider)
			throws CommunicationException {
		try (SnsClient snsClient = buildSnsClient(uri, config, credentialsProvider)) {
			String snsTopicArn = AwsUtils.getStringParameter(message, PROPERTY_SNS_TOPIC_ARN);
			snsClient.publish(b -> b
					.topicArn(snsTopicArn)
					.message(text));
		}
		catch (Exception e) {
			throw new CommunicationException(e, "Failed publishing message (%s) to SNS", text);
		}
	}

	private static SnsClient buildSnsClient(URI uri, ClientOverrideConfiguration config, AwsCredentialsProvider credentialsProvider) throws CommunicationException {
		SnsClientBuilder builder = SnsClient.builder()
				.overrideConfiguration(config)
				.credentialsProvider(credentialsProvider);

		URI override = AwsUtils.getEndpointOverride().orElse(null);
		if (override != null) {
			builder.endpointOverride(override);
		}
		else {
			builder.region(Region.of(AwsUtils.parseHost(uri)));
		}
		return builder.build();
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy