{"id":3680,"date":"2025-09-22T10:00:53","date_gmt":"2025-09-22T14:00:53","guid":{"rendered":"https:\/\/www.mymiller.name\/wordpress\/?p=3680"},"modified":"2025-09-22T10:00:53","modified_gmt":"2025-09-22T14:00:53","slug":"sending-sms-and-mms-messages-with-aws-sns-and-java-spring-integration","status":"publish","type":"post","link":"https:\/\/www.mymiller.name\/wordpress\/aws\/sending-sms-and-mms-messages-with-aws-sns-and-java-spring-integration\/","title":{"rendered":"Sending SMS and MMS Messages with AWS SNS and Java (Spring Integration)"},"content":{"rendered":"\n<div class=\"wp-block-jetpack-markdown\"><p>AWS Simple Notification Service (SNS) provides a robust platform for sending notifications across various channels, including SMS and MMS. Let\u2019s explore how to implement this functionality using Java within a Spring framework.<\/p>\n<h3>Prerequisites<\/h3>\n<ul>\n<li><strong>AWS Account:<\/strong> An active AWS account is necessary.<\/li>\n<li><strong>AWS SDK for Java:<\/strong> Make sure you have the AWS SDK for Java integrated into your project. You can include it using Maven or Gradle.<\/li>\n<li><strong>IAM Permissions:<\/strong> Create an IAM user with appropriate permissions to publish SNS messages.<\/li>\n<li><strong>Spring Framework:<\/strong> Ensure your project is set up with the Spring framework.<\/li>\n<\/ul>\n<h3>Setting up AWS Credentials<\/h3>\n<ol>\n<li>\n<p><strong>Access Key and Secret Key:<\/strong> Obtain your AWS access key ID and secret access key. Store them securely.<\/p>\n<\/li>\n<li>\n<p><strong>Configure Credentials:<\/strong> There are multiple ways to configure your AWS credentials. A common approach is to set environment variables:<\/p>\n<pre><code class=\"language-bash\">export AWS_ACCESS_KEY_ID=your_access_key_id\nexport AWS_SECRET_ACCESS_KEY=your_secret_access_key\n<\/code><\/pre>\n<\/li>\n<\/ol>\n<h3>Spring Service Implementation<\/h3>\n<pre><code class=\"language-java\">import org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.stereotype.Service;\nimport software.amazon.awssdk.regions.Region;\nimport software.amazon.awssdk.services.sns.SnsClient;\nimport software.amazon.awssdk.services.sns.model.MessageAttributeValue;\nimport software.amazon.awssdk.services.sns.model.PublishRequest;\nimport software.amazon.awssdk.services.sns.model.PublishResponse;\n\nimport java.util.Map;\n\n@Service\npublic class SnsService {\n\n    private final SnsClient snsClient;\n\n    @Autowired\n    public SnsService(SnsClient snsClient) {\n        this.snsClient = snsClient;\n    }\n\n    public String sendSms(String phoneNumber, String message) {\n        PublishRequest smsRequest = PublishRequest.builder()\n                .message(message)\n                .phoneNumber(phoneNumber)\n                .build();\n\n        PublishResponse smsResponse = snsClient.publish(smsRequest);\n        return smsResponse.messageId();\n    }\n\n    public String sendMms(String phoneNumber, String message, String mediaUrl, String subject) {\n        PublishRequest mmsRequest = PublishRequest.builder()\n                .message(message)\n                .phoneNumber(phoneNumber)\n                .subject(subject)\n                .messageAttributes(\n                        Map.of(&quot;AWS.SNS.MMS.SMIL&quot;, MessageAttributeValue.builder()\n                                        .dataType(&quot;String&quot;)\n                                        .stringValue(&quot;&lt;mms&gt;&lt;body&gt;&lt;par&gt;&lt;img src=\\&quot;&quot; + mediaUrl + &quot;\\&quot; alt=\\&quot;image\\&quot; \/&gt;&lt;\/par&gt;&lt;\/body&gt;&lt;\/mms&gt;&quot;)\n                                        .build()\n                        )\n                )\n                .build();\n\n        PublishResponse mmsResponse = snsClient.publish(mmsRequest);\n        return mmsResponse.messageId();\n    }\n}\n<\/code><\/pre>\n<h3>Using the Spring Service<\/h3>\n<pre><code class=\"language-java\">import org.springframework.beans.factory.annotation.Autowired;\nimport org.springframework.boot.CommandLineRunner;\nimport org.springframework.boot.SpringApplication;\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\n\n@SpringBootApplication\npublic class SnsApplication implements CommandLineRunner {\n\n    @Autowired\n    private SnsService snsService;\n\n    public static void main(String[] args) {\n        SpringApplication.run(SnsApplication.class, args);\n    }\n\n    @Override\n    public void run(String... args) throws Exception {\n        String phoneNumber = &quot;+1234567890&quot;; \/\/ Replace with the recipient's phone number\n        String message = &quot;This is a test SMS message from AWS SNS.&quot;;\n        String mediaUrl = &quot;https:\/\/example.com\/image.jpg&quot;; \/\/ Replace with your media URL\n        String subject = &quot;Test MMS&quot;;\n\n        String smsMessageId = snsService.sendSms(phoneNumber, message);\n        System.out.println(&quot;SMS Message ID: &quot; + smsMessageId);\n\n        String mmsMessageId = snsService.sendMms(phoneNumber, message, mediaUrl, subject);\n        System.out.println(&quot;MMS Message ID: &quot; + mmsMessageId);\n    }\n}\n<\/code><\/pre>\n<h3>Explanation<\/h3>\n<ul>\n<li><strong>Spring <code>@Service<\/code> Annotation:<\/strong> The <code>SnsService<\/code> class is annotated with <code>@Service<\/code> to mark it as a Spring service component.<\/li>\n<li><strong><code>SnsClient<\/code> Injection:<\/strong> The <code>SnsClient<\/code> is injected into the service using constructor-based dependency injection (<code>@Autowired<\/code>).<\/li>\n<li><strong>Methods for SMS and MMS:<\/strong> The service provides <code>sendSms<\/code> and <code>sendMms<\/code> methods for sending messages.<\/li>\n<li><strong>Using the Service:<\/strong> The <code>SnsApplication<\/code> class demonstrates how to use the <code>SnsService<\/code> by autowiring it and calling its methods within the <code>run<\/code> method (triggered when the Spring Boot application starts).<\/li>\n<\/ul>\n<h3>Important Considerations<\/h3>\n<ul>\n<li><strong><code>SnsClient<\/code> Bean:<\/strong> You\u2019ll need to configure an <code>SnsClient<\/code> bean in your Spring application context.<\/li>\n<li><strong>AWS Credentials:<\/strong> Make sure your AWS credentials are configured correctly.<\/li>\n<li><strong>Error Handling:<\/strong> Add proper error handling and exception management.<\/li>\n<li><strong>Opt-Out Mechanism:<\/strong> Provide recipients with a clear way to opt out.<\/li>\n<\/ul>\n<p>Integrating AWS SNS into your Spring applications becomes straightforward with this approach. The Spring service encapsulates the messaging logic, promoting cleaner code and easier maintenance.<\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":3681,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[442],"tags":[431,319],"series":[],"class_list":["post-3680","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-aws","tag-aws","tag-spring"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/smartphone-3152679_1280-jpg.avif","jetpack-related-posts":[{"id":3686,"url":"https:\/\/www.mymiller.name\/wordpress\/aws\/sending-emails-with-aws-simple-email-service-ses-and-attachments\/","url_meta":{"origin":3680,"position":0},"title":"Sending Emails with AWS Simple Email Service (SES) and Attachments","author":"Jeffery Miller","date":"November 17, 2025","format":false,"excerpt":"In this blog article, we\u2019ll delve into using Amazon Simple Email Service (SES) to send emails, both with and without attachments, directly from your applications. SES is a cost-effective, flexible, and scalable email service offered by AWS. Let\u2019s explore how to leverage its capabilities. 1. Set up AWS SES If\u2026","rel":"","context":"In &quot;AWS&quot;","block_context":{"text":"AWS","link":"https:\/\/www.mymiller.name\/wordpress\/category\/aws\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/e-mail-4487083_1280-jpg.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/e-mail-4487083_1280-jpg.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/e-mail-4487083_1280-jpg.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/e-mail-4487083_1280-jpg.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/09\/e-mail-4487083_1280-jpg.avif 3x"},"classes":[]},{"id":3744,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_config\/3744\/","url_meta":{"origin":3680,"position":1},"title":"Spring Cloud Config: Choosing the Right Backend Storage","author":"Jeffery Miller","date":"December 23, 2025","format":false,"excerpt":"Spring Cloud Config offers a flexible way to manage your application\u2019s configuration. A crucial step is selecting the right backend to store your configuration data. Let\u2019s explore popular options, their pros and cons, configuration details, and the necessary dependencies for Maven and Gradle. 1. Git Pros: Version Control: Leverage Git\u2019s\u2026","rel":"","context":"In &quot;Spring Config&quot;","block_context":{"text":"Spring Config","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_config\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/04\/woman-8696271_640.jpg?fit=438%2C640&ssl=1&resize=350%2C200","width":350,"height":200},"classes":[]},{"id":3903,"url":"https:\/\/www.mymiller.name\/wordpress\/docker\/the-s3-local-dev-trick-using-minio-to-simplify-cloud-native-developmen\/","url_meta":{"origin":3680,"position":2},"title":"The S3 Local Dev Trick: Using MinIO to Simplify Cloud-Native Developmen","author":"Jeffery Miller","date":"August 25, 2025","format":false,"excerpt":"As a software architect building cloud-native solutions, you know that working with cloud services like AWS S3 can be a bit tricky in a local development environment. You don't want to constantly connect to a remote bucket, and setting up complex local testing environments can be a pain. But what\u2026","rel":"","context":"In &quot;Docker&quot;","block_context":{"text":"Docker","link":"https:\/\/www.mymiller.name\/wordpress\/category\/docker\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/08\/ai-generated-9268117_1280.avif 3x"},"classes":[]},{"id":3868,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_events\/streamlining-user-events-integrating-aws-cognito-with-kafka\/","url_meta":{"origin":3680,"position":3},"title":"Streamlining User Events: Integrating AWS Cognito with Kafka","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"In modern application architectures, understanding user behavior is crucial. Tracking events like logins, logouts, failed login attempts, and signups can provide valuable insights for analytics, security monitoring, and personalized user experiences. This post will guide you through the process of configuring AWS Cognito to send these events to an Apache\u2026","rel":"","context":"In &quot;Spring Events&quot;","block_context":{"text":"Spring Events","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_events\/"},"img":{"alt_text":"","src":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/binary-7206874_1280.avif","width":350,"height":200,"srcset":"https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/binary-7206874_1280.avif 1x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/binary-7206874_1280.avif 1.5x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/binary-7206874_1280.avif 2x, https:\/\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2025\/05\/binary-7206874_1280.avif 3x"},"classes":[]},{"id":3502,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_databases\/spring-data-jpa-for-dummies-persisting-data-like-a-pro\/","url_meta":{"origin":3680,"position":4},"title":"Spring Data JPA for Dummies: Persisting Data Like a Pro","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Ever feel bogged down by writing tons of code just to interact with your database? If you're a Java developer working with relational databases, Spring Data JPA is your new best friend. This blog post will give you a beginner-friendly introduction to Spring Data JPA, showing you how to save\u2026","rel":"","context":"In &quot;Spring Databases&quot;","block_context":{"text":"Spring Databases","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_databases\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/binary-2904980_1280.jpg?fit=1200%2C674&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/binary-2904980_1280.jpg?fit=1200%2C674&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/binary-2904980_1280.jpg?fit=1200%2C674&ssl=1&resize=525%2C300 1.5x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/binary-2904980_1280.jpg?fit=1200%2C674&ssl=1&resize=700%2C400 2x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/binary-2904980_1280.jpg?fit=1200%2C674&ssl=1&resize=1050%2C600 3x"},"classes":[]},{"id":3842,"url":"https:\/\/www.mymiller.name\/wordpress\/spring_messaging\/taming-the-stream-effective-unit-testing-with-kafka-in-spring-boot\/","url_meta":{"origin":3680,"position":5},"title":"Taming the Stream: Effective Unit Testing with Kafka in Spring Boot","author":"Jeffery Miller","date":"December 24, 2025","format":false,"excerpt":"Kafka\u2019s asynchronous, distributed nature introduces unique challenges to testing. Unlike traditional synchronous systems, testing Kafka interactions requires verifying message production, consumption, and handling potential asynchronous delays. This article explores strategies for robust unit testing of Kafka components within a Spring Boot application. Understanding the Testing Landscape Before diving into specifics,\u2026","rel":"","context":"In &quot;Spring Messaging&quot;","block_context":{"text":"Spring Messaging","link":"https:\/\/www.mymiller.name\/wordpress\/category\/spring_messaging\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/intro-7400243_640.jpg?fit=640%2C334&ssl=1&resize=350%2C200","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/intro-7400243_640.jpg?fit=640%2C334&ssl=1&resize=350%2C200 1x, https:\/\/i0.wp.com\/www.mymiller.name\/wordpress\/wp-content\/uploads\/2024\/06\/intro-7400243_640.jpg?fit=640%2C334&ssl=1&resize=525%2C300 1.5x"},"classes":[]}],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3680","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/comments?post=3680"}],"version-history":[{"count":1,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3680\/revisions"}],"predecessor-version":[{"id":3682,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/posts\/3680\/revisions\/3682"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media\/3681"}],"wp:attachment":[{"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/media?parent=3680"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/categories?post=3680"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/tags?post=3680"},{"taxonomy":"series","embeddable":true,"href":"https:\/\/www.mymiller.name\/wordpress\/wp-json\/wp\/v2\/series?post=3680"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}