

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Amazon SQS에서 JMS 사용
<a name="sqs-java-message-service-jms-client"></a>

Amazon SQS Java 메시징 라이브러리는 이미 JMS를 사용하고 있는 애플리케이션에서 Amazon SQS를 활용하도록 해주는 Amazon SQS용 Java 메시지 서비스(JMS) 인터페이스입니다. 이 인터페이스를 통해 코드 변경을 최소화하면서 Amazon SQS를 JMS 공급자로서 사용할 수 있습니다. AWS SDK for Java와 함께 Amazon SQS Java 메시징 라이브러리를 통해 JMS 연결과 세션뿐 아니라 Amazon SQS 대기열과 메시지를 주고 받는 생성자 및 소비자를 생성할 수 있습니다.

이 라이브러리는 [JMS 1.1 사양](http://docs.oracle.com/javaee/6/api/javax/jms/package-summary.html)에 따라 대기열(JMS 지점 간 모델)과의 메시지 송수신을 지원합니다. 이 라이브러리는 Amazon SQS 대기열로의 문자, 바이트 또는 객체 메시지 동기식 전송을 지원합니다. 또한, 동기 또는 비동기식 객체 수신도 지원합니다.

JMS 1.1 사양을 지원하는 Amazon SQS Java 메시징 라이브러리의 기능에 대한 자세한 내용은 [Amazon SQS 지원 JMS 1.1 구현](supported-implementations.md) 및 [Amazon SQS FAQ](https://aws.amazon.com/sqs/faqs/)를 참조하세요.

# JMS 및 Amazon SQS 작업을 위한 사전 조건
<a name="prerequisites"></a>

시작하기 전에 다음 사전 요구 사항을 완비해야 합니다.
+ **Java용 SDK**

  프로젝트에 Java용 SDK를 포함시키는 두 가지 방법이 있습니다.
  + Java용 SDK 다운로드 및 설치
  + Maven을 사용하여 Amazon SQS Java 메시징 라이브러리를 다운로드합니다.
**참고**  
Java용 SDK는 종속적으로 포함되어 있습니다.  
[Java용 SDK](https://aws.amazon.com/sdkforjava/) 및 Java용 Amazon SQS 확장 클라이언트 라이브러리를 사용하려면 J2SE 개발 키트 8.0 이상이 필요합니다.

    Java용 SDK 다운로드에 대한 자세한 내용은 [Java용 SDK](https://aws.amazon.com/sdkforjava/)를 참조하세요.
+ **Amazon SQS Java 메시징 라이브러리** 

  Maven을 사용하지 않을 경우, `amazon-sqs-java-messaging-lib.jar` 패키지를 Java 빌드 클래스 경로에 추가해야 합니다. 라이브러리 다운로드에 대한 자세한 내용은 [Amazon SQS Java 메시징 라이브러리](https://github.com/awslabs/amazon-sqs-java-messaging-lib)를 참조하세요.
**참고**  
Amazon SQS Java 메시징 라이브러리에는 [Maven](http://maven.apache.org/)과 [Spring 프레임워크](http://projects.spring.io/spring-framework/)에 대한 지원이 포함되어 있습니다.  
Maven, Spring Framework, Amazon SQS Java 메시징 라이브러리를 사용하는 코드 샘플은 [Amazon SQS 표준 대기열에 JMS를 사용하는 Java 작업 예제](sqs-jms-code-examples.md) 섹션을 참조하세요.  

  ```
  <dependency>
    <groupId>com.amazonaws</groupId>
    <artifactId>amazon-sqs-java-messaging-lib</artifactId>
    <version>1.0.4</version>
    <type>jar</type>
  </dependency>
  ```
+ **Amazon SQS 대기열**

  Amazon SQS용 AWS Management Console, `CreateQueue` API 또는 Amazon SQS Java 메시징 라이브러리에 들어 있는 래핑된 Amazon SQS 클라이언트를 사용하여 대기열을 생성합니다.
  + AWS Management Console 또는 `CreateQueue` API를 사용하여 Amazon SQS에서 대기열을 만드는 방법에 대한 정보는 [대기열 만들기](creating-sqs-standard-queues.md#step-create-standard-queue)를 참조하세요.
  + Amazon SQS Java 메시징 라이브러리 사용에 대한 자세한 내용은 [Amazon SQS Java 메시징 라이브러리 사용](getting-started.md) 섹션을 참조하세요.

# Amazon SQS Java 메시징 라이브러리 사용
<a name="getting-started"></a>

Amazon SQS에서 Java 메시지 서비스(JMS) 사용을 시작하려면 이 섹션의 코드 예제를 사용합니다. 다음 섹션에는 JMS 연결 및 세션 생성 방법과 메시지 전송 및 수신 방법이 나와 있습니다.

Amazon SQS Java 메시징 라이브러리에 포함된 래핑된 Amazon SQS 클라이언트 객체는 Amazon SQS 대기열이 존재하는지 확인합니다. 대기열이 존재하지 않는 경우, 클라이언트가 이 대기열을 생성합니다.

## JMS 연결 생성
<a name="creating-connection"></a>

시작하기 전에 [JMS 및 Amazon SQS 작업을 위한 사전 조건](prerequisites.md)에서 사전 조건을 참조하세요.

1. 연결 팩토리를 생성하고 이 팩토리에 대한 `createConnection` 메서드를 호출합니다.

   ```
   // Create a new connection factory with all defaults (credentials and region) set automatically
   SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
           new ProviderConfiguration(),
           AmazonSQSClientBuilder.defaultClient()
           );
    
   // Create the connection.
   SQSConnection connection = connectionFactory.createConnection();
   ```

   `SQSConnection` 클래스는 `javax.jms.Connection`을 확장합니다. JMS 표준 연결 메서드와 더불어 `SQSConnection`은 `getAmazonSQSClient` 및 `getWrappedAmazonSQSClient`와 같은 추가 메서드를 제공합니다. 이 두 메서드를 통해 새로운 대기열 생성과 같이 JMS 사양에 포함되지 않은 관리 작업을 수행할 수 있습니다. 그렇지만, `getWrappedAmazonSQSClient` 메서드는 최신 연결을 통해 사용되는 래핑된 버전의 Amazon SQS 클라이언트도 제공합니다. 래퍼는 클라이언트에서 `JMSException`으로 모든 예외를 변환하므로, `JMSException` 발생이 예상되는 기존 코드에서 보다 쉽게 사용할 수 있습니다.

1. `getAmazonSQSClient` 및 `getWrappedAmazonSQSClient`에서 반환되는 클라이언트 객체를 사용하여 JMS 사양에 포함되지 않은 관리 작업(예: Amazon SQS 대기열 생성 가능)을 수행할 수 있습니다.

    JMS 예외가 예상되는 기존 코드가 있는 경우, `getWrappedAmazonSQSClient`를 사용해야 합니다.
   + `getWrappedAmazonSQSClient`를 사용한 경우, 반환된 클라이언트 객체는 모든 예외를 JMS 예외로 변환합니다.
   + `getAmazonSQSClient`를 사용하는 경우, 예외는 모두 Amazon SQS 예외입니다.

## Amazon SQS 대기열 생성
<a name="creating-queue"></a>

래핑된 클라이언트 객체는 Amazon SQS 대기열이 있는지를 확인합니다.

대기열이 존재하지 않는 경우, 클라이언트가 이 대기열을 생성합니다. 대기열이 존재하지 않는 경우, 이 함수는 어느 항목도 반환하지 않습니다. 자세한 내용은 [TextMessageSender.java](sqs-jms-code-examples.md#example-sender) 예제에서 "필요한 경우 대기열 생성"을 참조하십시오.

### 표준 대기열을 생성하려면
<a name="creating-queue-standard"></a>

```
// Get the wrapped client
AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();
 
// Create an SQS queue named MyQueue, if it doesn't already exist
if (!client.queueExists("MyQueue")) {
    client.createQueue("MyQueue");
}
```

### FIFO 대기열을 생성하려면
<a name="creating-queue-FIFO"></a>

```
// Get the wrapped client
AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();

// Create an Amazon SQS FIFO queue named MyQueue.fifo, if it doesn't already exist
if (!client.queueExists("MyQueue.fifo")) {
    Map<String, String> attributes = new HashMap<String, String>();
    attributes.put("FifoQueue", "true");
    attributes.put("ContentBasedDeduplication", "true");
    client.createQueue(new CreateQueueRequest().withQueueName("MyQueue.fifo").withAttributes(attributes));
}
```

**참고**  
FIFO 대기열의 이름은 `.fifo` 접미사로 끝나야 합니다.  
`ContentBasedDeduplication` 속성에 대한 자세한 내용은 [Amazon SQS의 정확히 1회 처리](FIFO-queues-exactly-once-processing.md)를 참조하십시오.

## 메시지 동기식 전송
<a name="send-messages-synchronously"></a>

1. 연결 및 기본 Amazon SQS 대기열이 준비가 되면, `AUTO_ACKNOWLEDGE` 모드로 트랜잭션 처리되지 않는 JMS 세션을 생성합니다.

   ```
   // Create the nontransacted session with AUTO_ACKNOWLEDGE mode
   Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
   ```

1. 대기열에 문자 메시지를 전송하려면, JMS 대기열 자격 증명과 메시지 생성자를 생성합니다.

   ```
   // Create a queue identity and specify the queue name to the session
   Queue queue = session.createQueue("MyQueue");
    
   // Create a producer for the 'MyQueue'
   MessageProducer producer = session.createProducer(queue);
   ```

1. 문자 메시지를 작성하고 대기열로 전송합니다.
   + 메시지를 표준 대기열로 전송하는 경우 추가 파라미터를 설정할 필요가 없습니다.

     ```
     // Create the text message
     TextMessage message = session.createTextMessage("Hello World!");
      
     // Send the message
     producer.send(message);
     System.out.println("JMS Message " + message.getJMSMessageID());
     ```
   + 메시지를 FIFO 대기열로 전송하는 경우 메시지 그룹 ID를 설정해야 합니다. 메시지 중복 제거 ID를 설정할 수도 있습니다. 자세한 내용은 [Amazon SQS FIFO 대기열 주요 용어](FIFO-key-terms.md) 단원을 참조하십시오.

     ```
     // Create the text message
     TextMessage message = session.createTextMessage("Hello World!");
     
     // Set the message group ID
     message.setStringProperty("JMSXGroupID", "Default");
     
     // You can also set a custom message deduplication ID
     // message.setStringProperty("JMS_SQS_DeduplicationId", "hello");
     // Here, it's not needed because content-based deduplication is enabled for the queue
     
     // Send the message
     producer.send(message);
     System.out.println("JMS Message " + message.getJMSMessageID());
     System.out.println("JMS Message Sequence Number " + message.getStringProperty("JMS_SQS_SequenceNumber"));
     ```

## 메시지 동기식 수신
<a name="receive-messages-synchronously"></a>

1. 메시지를 수신하려면 동일한 대기열에 대한 소비자를 생성하고 `start` 메서드를 호출합니다.

   언제든지 연결에서 `start` 메서드를 호출할 수 있습니다. 그렇지만, 소비자는 사용자가 메시지를 호출할 때까지 메시지 수신을 시작하지 않습니다.

   ```
   // Create a consumer for the 'MyQueue'
   MessageConsumer consumer = session.createConsumer(queue);
   // Start receiving incoming messages
   connection.start();
   ```

1. 제한 시간을 1초로 설정한 소비자에서 `receive` 메서드를 호출한 다음 수신된 메시지의 내용을 인쇄합니다.
   + 표준 대기열에서 메시지를 수신한 후 해당 메시지의 내용에 액세스할 수 있습니다.

     ```
     // Receive a message from 'MyQueue' and wait up to 1 second
     Message receivedMessage = consumer.receive(1000);
      
     // Cast the received message as TextMessage and display the text
     if (receivedMessage != null) {
         System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
     }
     ```
   + FIFO 대기열에서 메시지를 수신한 후 메시지 그룹 ID, 메시지 중복 제거 ID 및 시퀀스 번호와 같은 메시지 내용 및 기타 FIFO 관련 메시지 속성에 액세스할 수 있습니다. 자세한 내용은 [Amazon SQS FIFO 대기열 주요 용어](FIFO-key-terms.md) 단원을 참조하십시오.

     ```
     // Receive a message from 'MyQueue' and wait up to 1 second
     Message receivedMessage = consumer.receive(1000);
     
     // Cast the received message as TextMessage and display the text
     if (receivedMessage != null) {
         System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
         System.out.println("Group id: " + receivedMessage.getStringProperty("JMSXGroupID"));
         System.out.println("Message deduplication id: " + receivedMessage.getStringProperty("JMS_SQS_DeduplicationId"));
         System.out.println("Message sequence number: " + receivedMessage.getStringProperty("JMS_SQS_SequenceNumber"));
     }
     ```

1. 연결과 세션을 종료합니다.

   ```
   // Close the connection (and the session).
   connection.close();
   ```

출력 결과는 다음과 비슷합니다:

```
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
```

**참고**  
Spring Framework를 사용하여 이 객체를 초기화할 수 있습니다.  
추가 정보는 `SpringExampleConfiguration.xml`, `SpringExample.java` 및 `ExampleConfiguration.java` 단원의 `ExampleCommon.java`와 [Amazon SQS 표준 대기열에 JMS를 사용하는 Java 작업 예제](sqs-jms-code-examples.md)에 있는 기타 헬퍼 클래스를 참조하십시오.

객체 전송 및 수신 예제 전체를 보려면, [TextMessageSender.java](sqs-jms-code-examples.md#example-sender) 및 [SyncMessageReceiver.java](sqs-jms-code-examples.md#example-synchronous-message-receiver)를 참조하십시오.

## 메시지 비동기식 수신
<a name="receive-messages-asynchronously"></a>

[Amazon SQS Java 메시징 라이브러리 사용](#getting-started)의 예제에서 메시지는 `MyQueue`로 전송되고 동기식으로 수신됩니다.

다음 예제는 리스너를 통해 비동기식으로 메시지를 수신하는 방법을 나타냅니다.

1. `MessageListener` 인터페이스를 구현합니다.

   ```
   class MyListener implements MessageListener {
    
       @Override
       public void onMessage(Message message) {
           try {
               // Cast the received message as TextMessage and print the text to screen.
               System.out.println("Received: " + ((TextMessage) message).getText());
           } catch (JMSException e) {
               e.printStackTrace();
           }
       }
   }
   ```

   메시지를 수신하면 `MessageListener` 인터페이스의 `onMessage` 메서드가 호출됩니다. 이 리스너 구현에서 메시지에 저장된 텍스트가 인쇄됩니다.

1. 소비자에서 `receive` 메서드를 명시적으로 호출하지 않고, 소비자의 메시지 리스너를 `MyListener` 구현의 인스턴스로 설정합니다. 기본 스레드는 1초간 대기합니다.

   ```
   // Create a consumer for the 'MyQueue'.
   MessageConsumer consumer = session.createConsumer(queue);
    
   // Instantiate and set the message listener for the consumer.
   consumer.setMessageListener(new MyListener());
    
   // Start receiving incoming messages.
   connection.start();
    
   // Wait for 1 second. The listener onMessage() method is invoked when a message is received.
   Thread.sleep(1000);
   ```

나머지 단계는 [Amazon SQS Java 메시징 라이브러리 사용](#getting-started) 예제의 단계와 동일합니다. 비동기식 소비자의 예제 전체는 `AsyncMessageReceiver.java`의 [Amazon SQS 표준 대기열에 JMS를 사용하는 Java 작업 예제](sqs-jms-code-examples.md)를 참조하십시오.

이 예제의 출력은 다음과 비슷합니다.

```
JMS Message ID:8example-588b-44e5-bbcf-d816example2
Received: Hello World!
```

## 클라이언트 승인 모드 사용
<a name="using-client-acknowledge-mode"></a>

[Amazon SQS Java 메시징 라이브러리 사용](#getting-started)의 예제는 모든 수신 메시지가 자동으로 승인되고 나서 기본 Amazon SQS 대기열에서 삭제되는 `AUTO_ACKNOWLEDGE` 모드를 사용합니다.

1. 메시지를 처리한 후 명시적으로 승인하려면, `CLIENT_ACKNOWLEDGE` 모드로 세션을 생성해야 합니다.

   ```
   // Create the non-transacted session with CLIENT_ACKNOWLEDGE mode.
   Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
   ```

1. 메시지를 수신하면 메시지를 표시한 후 명시적으로 승인합니다.

   ```
   // Cast the received message as TextMessage and print the text to screen. Also acknowledge the message.
   if (receivedMessage != null) {
       System.out.println("Received: " + ((TextMessage) receivedMessage).getText());
       receivedMessage.acknowledge();
       System.out.println("Acknowledged: " + message.getJMSMessageID());
   }
   ```
**참고**  
이 모드에서 메시지를 승인하면, 이 메시지를 이전에 받은 모든 메시지도 명시적으로 승인됩니다. 예를 들어, 메시지 10개를 수신하고 10번째(메시지 수신 순서) 메시지만을 승인하면, 이전의 9개 메시지 전체도 승인됩니다.

나머지 단계는 [Amazon SQS Java 메시징 라이브러리 사용](#getting-started) 예제의 단계와 동일합니다. 클라이언트 승인 모드를 사용하는 비동기식 소비자의 예제 전체는 `SyncMessageReceiverClientAcknowledge.java`의 [Amazon SQS 표준 대기열에 JMS를 사용하는 Java 작업 예제](sqs-jms-code-examples.md)를 참조하십시오.

이 예제의 출력은 다음과 비슷합니다.

```
JMS Message ID:4example-aa0e-403f-b6df-5e02example5
Received: Hello World!
Acknowledged: ID:4example-aa0e-403f-b6df-5e02example5
```

## 정렬되어 있지 않은 승인 모드 사용
<a name="using-unordered-acknowledge-mode"></a>

`CLIENT_ACKNOWLEDGE` 모드를 사용하면, 명시적으로 승인한 메시지 이전에 받은 모든 메시지가 자동으로 승인됩니다. 자세한 내용은 [클라이언트 승인 모드 사용](#using-client-acknowledge-mode) 단원을 참조하십시오.

Amazon SQS Java 메시징 라이브러리는 또 다른 승인 모드를 제공합니다. `UNORDERED_ACKNOWLEDGE` 모드를 사용하면, 수신한 모든 메시지가 수신 순서에 상관 없이 개별적 및 명시적으로 승인됩니다. 이렇게 하려면 `UNORDERED_ACKNOWLEDGE` 모드를 사용하여 세션을 생성합니다.

```
// Create the non-transacted session with UNORDERED_ACKNOWLEDGE mode.
Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
```

나머지 단계는 [클라이언트 승인 모드 사용](#using-client-acknowledge-mode) 예제의 단계와 동일합니다. `UNORDERED_ACKNOWLEDGE` 모드에서 동기식 소비자의 예제 전체는 `SyncMessageReceiverUnorderedAcknowledge.java`를 참조하십시오.

이 예제의 출력은 다음과 비슷합니다.

```
JMS Message ID:dexample-73ad-4adb-bc6c-4357example7
Received: Hello World!
Acknowledged: ID:dexample-73ad-4adb-bc6c-4357example7
```

# Java 메시지 서비스를 다른 Amazon SQS 클라이언트와 함께 사용
<a name="sqs-jms-client-with-sqs-clients"></a>

 AWS SDK와 함께 Amazon SQS Java Message Service(JMS) 클라이언트를 사용하면 Amazon SQS 메시지 크기가 256KB로 제한됩니다. 그러나 Amazon SQS 클라이언트를 사용하여 JMS 공급자를 생성할 수 있습니다. 예를 들어, JMS 클라이언트와 함께 Java용 Amazon SQS 확장 클라이언트 라이브러리를 사용하여 Amazon S3의 메시지 페이로드(최대 2GB)에 대한 참조가 들어 있는 Amazon SQS 메시지를 전송할 수 있습니다. 자세한 내용은 [Java 및 Amazon S3를 사용하여 대규모 Amazon SQS 메시지 관리](sqs-s3-messages.md) 단원을 참조하십시오.

다음의 Java 코드 예제에서는 확장 클라이언트 라이브러리에 대한 JMS 공급자를 생성합니다.

이 예제를 테스트하기 전에 [JMS 및 Amazon SQS 작업을 위한 사전 조건](prerequisites.md)에서 사전 조건을 참조하세요.

```
AmazonS3 s3 = new AmazonS3Client(credentials);
Region s3Region = Region.getRegion(Regions.US_WEST_2);
s3.setRegion(s3Region);
 
// Set the Amazon S3 bucket name, and set a lifecycle rule on the bucket to
// permanently delete objects a certain number of days after each object's creation date.
// Next, create the bucket, and enable message objects to be stored in the bucket.
BucketLifecycleConfiguration.Rule expirationRule = new BucketLifecycleConfiguration.Rule();
expirationRule.withExpirationInDays(14).withStatus("Enabled");
BucketLifecycleConfiguration lifecycleConfig = new BucketLifecycleConfiguration().withRules(expirationRule);
 
s3.createBucket(s3BucketName);
s3.setBucketLifecycleConfiguration(s3BucketName, lifecycleConfig);
System.out.println("Bucket created and configured.");

// Set the SQS extended client configuration with large payload support enabled.
ExtendedClientConfiguration extendedClientConfig = new ExtendedClientConfiguration()
    .withLargePayloadSupportEnabled(s3, s3BucketName);
 
AmazonSQS sqsExtended = new AmazonSQSExtendedClient(new AmazonSQSClient(credentials), extendedClientConfig);
Region sqsRegion = Region.getRegion(Regions.US_WEST_2);
sqsExtended.setRegion(sqsRegion);
```

다음의 Java 코드 예제에서는 연결 팩토리를 생성합니다.

```
// Create the connection factory using the environment variable credential provider.
// Pass the configured Amazon SQS Extended Client to the JMS connection factory.
SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
        new ProviderConfiguration(),
        sqsExtended
        );
 
// Create the connection.
SQSConnection connection = connectionFactory.createConnection();
```

# Amazon SQS 표준 대기열에 JMS를 사용하는 Java 작업 예제
<a name="sqs-jms-code-examples"></a>

다음 코드 예시에서는 Amazon SQS 표준 대기열과 함께 Java 메시지 서비스(JMS)를 사용하는 방법을 보여줍니다. FIFO 대기열 작업에 대한 자세한 내용은 [FIFO 대기열을 생성하려면](getting-started.md#creating-queue-FIFO), [메시지 동기식 전송](getting-started.md#send-messages-synchronously) 및 [메시지 동기식 수신](getting-started.md#receive-messages-synchronously) 섹션을 참조하세요. (메시지를 동기적으로 수신하는 것은 표준 대기열과 FIFO 대기열에서 동일합니다. 그러나 FIFO 대기열의 메시지에는 더 많은 속성이 포함되어 있습니다.)

다음 예제를 테스트하기 전에 [JMS 및 Amazon SQS 작업을 위한 사전 조건](prerequisites.md)에서 사전 조건을 참조하세요.

## ExampleConfiguration.java
<a name="example-configuration"></a>

다음 Java SDK v 1.x 코드 예제에서는 다른 Java 예제에서 사용되는 기본 대기열 이름, 리전 및 자격 증명을 설정한 것입니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

public class ExampleConfiguration {
    public static final String DEFAULT_QUEUE_NAME = "SQSJMSClientExampleQueue";
    
    public static final Region DEFAULT_REGION = Region.getRegion(Regions.US_EAST_2);
    
    private static String getParameter( String args[], int i ) {
        if( i + 1 >= args.length ) {
            throw new IllegalArgumentException( "Missing parameter for " + args[i] );
        }
        return args[i+1];
    }
    
    /**
     * Parse the command line and return the resulting config. If the config parsing fails
     * print the error and the usage message and then call System.exit
     * 
     * @param app the app to use when printing the usage string
     * @param args the command line arguments
     * @return the parsed config
     */
    public static ExampleConfiguration parseConfig(String app, String args[]) {
        try {
            return new ExampleConfiguration(args);
        } catch (IllegalArgumentException e) {
            System.err.println( "ERROR: " + e.getMessage() );
            System.err.println();
            System.err.println( "Usage: " + app + " [--queue <queue>] [--region <region>] [--credentials <credentials>] ");
            System.err.println( "  or" );
            System.err.println( "       " + app + " <spring.xml>" );
            System.exit(-1);
            return null;
        }
    }
    
    private ExampleConfiguration(String args[]) {
        for( int i = 0; i < args.length; ++i ) {
            String arg = args[i];
            if( arg.equals( "--queue" ) ) {
                setQueueName(getParameter(args, i));
                i++;
            } else if( arg.equals( "--region" ) ) {
                String regionName = getParameter(args, i);
                try {
                    setRegion(Region.getRegion(Regions.fromName(regionName)));
                } catch( IllegalArgumentException e ) {
                    throw new IllegalArgumentException( "Unrecognized region " + regionName );  
                }
                i++;
            } else if( arg.equals( "--credentials" ) ) {
                String credsFile = getParameter(args, i);
                try {
                    setCredentialsProvider( new PropertiesFileCredentialsProvider(credsFile) );
                } catch (AmazonClientException e) {
                    throw new IllegalArgumentException("Error reading credentials from " + credsFile, e );
                }
                i++;
            } else {
                throw new IllegalArgumentException("Unrecognized option " + arg);
            }
        }
    }
    
    private String queueName = DEFAULT_QUEUE_NAME;
    private Region region = DEFAULT_REGION;
    private AWSCredentialsProvider credentialsProvider = new DefaultAWSCredentialsProviderChain();
    
    public String getQueueName() {
        return queueName;
    }
    
    public void setQueueName(String queueName) {
        this.queueName = queueName;
    }
    
    public Region getRegion() {
        return region;
    }
    
    public void setRegion(Region region) {
        this.region = region;
    }
 
    public AWSCredentialsProvider getCredentialsProvider() {
        return credentialsProvider;
    }
    
    public void setCredentialsProvider(AWSCredentialsProvider credentialsProvider) {
        // Make sure they're usable first
        credentialsProvider.getCredentials();
        this.credentialsProvider = credentialsProvider;
    }
}
```

## TextMessageSender.java
<a name="example-sender"></a>

다음 Java 코드 예제는 문자 메시지 생성자를 생성합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

public class TextMessageSender {
    public static void main(String args[]) throws JMSException {
        ExampleConfiguration config = ExampleConfiguration.parseConfig("TextMessageSender", args);
        
        ExampleCommon.setupLogging();
        
        // Create the connection factory based on the config       
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
        
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
        
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
            
        // Create the session
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        MessageProducer producer = session.createProducer( session.createQueue( config.getQueueName() ) );
        
        sendMessages(session, producer);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println( "Connection closed" );
    }
 
    private static void sendMessages( Session session, MessageProducer producer ) {
        BufferedReader inputReader = new BufferedReader(
            new InputStreamReader( System.in, Charset.defaultCharset() ) );
        
        try {
            String input;
            while( true ) { 
                System.out.print( "Enter message to send (leave empty to exit): " );
                input = inputReader.readLine();
                if( input == null || input.equals("" ) ) break;
                
                TextMessage message = session.createTextMessage(input);
                producer.send(message);
                System.out.println( "Send message " + message.getJMSMessageID() );
            }
        } catch (EOFException e) {
            // Just return on EOF
        } catch (IOException e) {
            System.err.println( "Failed reading input: " + e.getMessage() );
        } catch (JMSException e) {
            System.err.println( "Failed sending message: " + e.getMessage() );
            e.printStackTrace();
        }
    }
}
```

## SyncMessageReceiver.java
<a name="example-synchronous-message-receiver"></a>

다음 Java 코드 예제는 동기식 메시지 소비자를 생성합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

public class SyncMessageReceiver {
public static void main(String args[]) throws JMSException {
    ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiver", args);
    
    ExampleCommon.setupLogging();
    
    // Create the connection factory based on the config
    SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
            new ProviderConfiguration(),
            AmazonSQSClientBuilder.standard()
                    .withRegion(config.getRegion().getName())
                    .withCredentials(config.getCredentialsProvider())
            );
    
    // Create the connection
    SQSConnection connection = connectionFactory.createConnection();
    
    // Create the queue if needed
    ExampleCommon.ensureQueueExists(connection, config.getQueueName());
        
    // Create the session
    Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    MessageConsumer consumer = session.createConsumer( session.createQueue( config.getQueueName() ) );

    connection.start();
    
    receiveMessages(session, consumer);

    // Close the connection. This closes the session automatically
    connection.close();
    System.out.println( "Connection closed" );
}

private static void receiveMessages( Session session, MessageConsumer consumer ) {
    try {
        while( true ) {
            System.out.println( "Waiting for messages");
            // Wait 1 minute for a message
            Message message = consumer.receive(TimeUnit.MINUTES.toMillis(1));
            if( message == null ) {
                System.out.println( "Shutting down after 1 minute of silence" );
                break;
            }
            ExampleCommon.handleMessage(message);
            message.acknowledge();
            System.out.println( "Acknowledged message " + message.getJMSMessageID() );
        }
    } catch (JMSException e) {
        System.err.println( "Error receiving from SQS: " + e.getMessage() );
        e.printStackTrace();
    }
}
}
```

## AsyncMessageReceiver.java
<a name="example-asynchronous-message-receiver"></a>

다음 Java 코드 예제는 비동기식 메시지 소비자를 생성합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

public class AsyncMessageReceiver {
    public static void main(String args[]) throws JMSException, InterruptedException {
        ExampleConfiguration config = ExampleConfiguration.parseConfig("AsyncMessageReceiver", args);
         
        ExampleCommon.setupLogging();          
         
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
         
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
         
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
             
        // Create the session
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer( session.createQueue( config.getQueueName() ) );
         
        // No messages are processed until this is called
        connection.start();

        ReceiverCallback callback = new ReceiverCallback();
        consumer.setMessageListener( callback );
         
        callback.waitForOneMinuteOfSilence();
        System.out.println( "Returning after one minute of silence" );

        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println( "Connection closed" );
    }
    
    
    private static class ReceiverCallback implements MessageListener {
        // Used to listen for message silence
        private volatile long timeOfLastMessage = System.nanoTime();
         
        public void waitForOneMinuteOfSilence() throws InterruptedException {
            for(;;) {
                long timeSinceLastMessage = System.nanoTime() - timeOfLastMessage;
                long remainingTillOneMinuteOfSilence = 
                    TimeUnit.MINUTES.toNanos(1) - timeSinceLastMessage;
                if( remainingTillOneMinuteOfSilence < 0 ) {
                    break;
                }
                TimeUnit.NANOSECONDS.sleep(remainingTillOneMinuteOfSilence);
            }
        }
         

        @Override
        public void onMessage(Message message) {
            try {
                ExampleCommon.handleMessage(message);
                message.acknowledge();
                System.out.println( "Acknowledged message " + message.getJMSMessageID() );
                timeOfLastMessage = System.nanoTime();
            } catch (JMSException e) {
                System.err.println( "Error processing message: " + e.getMessage() );
                e.printStackTrace();
            }
        }
    }
}
```

## SyncMessageReceiverClientAcknowledge.java
<a name="example-synchronous-receiver-client-acknowledge-mode"></a>

다음 Java 코드 예제는 클라이언트 승인 모드를 사용하는 비동기식 소비자를 생성합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

/**
 * An example class to demonstrate the behavior of CLIENT_ACKNOWLEDGE mode for received messages. This example
 * complements the example given in {@link SyncMessageReceiverUnorderedAcknowledge} for UNORDERED_ACKNOWLEDGE mode.
 *
 * First, a session, a message producer, and a message consumer are created. Then, two messages are sent. Next, two messages
 * are received but only the second one is acknowledged. After waiting for the visibility time out period, an attempt to
 * receive another message is made. It's shown that no message is returned for this attempt since in CLIENT_ACKNOWLEDGE mode,
 * as expected, all the messages prior to the acknowledged messages are also acknowledged.
 *
 * This ISN'T the behavior for UNORDERED_ACKNOWLEDGE mode. Please see {@link SyncMessageReceiverUnorderedAcknowledge}
 * for an example.
 */
public class SyncMessageReceiverClientAcknowledge {
 
    // Visibility time-out for the queue. It must match to the one set for the queue for this example to work.
    private static final long TIME_OUT_SECONDS = 1;
 
    public static void main(String args[]) throws JMSException, InterruptedException {
        // Create the configuration for the example
        ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiverClientAcknowledge", args);
 
        // Setup logging for the example
        ExampleCommon.setupLogging();
 
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
 
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
 
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
 
        // Create the session  with client acknowledge mode
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
 
        // Create the producer and consume
        MessageProducer producer = session.createProducer(session.createQueue(config.getQueueName()));
        MessageConsumer consumer = session.createConsumer(session.createQueue(config.getQueueName()));
 
        // Open the connection
        connection.start();
 
        // Send two text messages
        sendMessage(producer, session, "Message 1");
        sendMessage(producer, session, "Message 2");
 
        // Receive a message and don't acknowledge it
        receiveMessage(consumer, false);
 
        // Receive another message and acknowledge it
        receiveMessage(consumer, true);
 
        // Wait for the visibility time out, so that unacknowledged messages reappear in the queue
        System.out.println("Waiting for visibility timeout...");
        Thread.sleep(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        // Attempt to receive another message and acknowledge it. This results in receiving no messages since
        // we have acknowledged the second message. Although we didn't explicitly acknowledge the first message,
        // in the CLIENT_ACKNOWLEDGE mode, all the messages received prior to the explicitly acknowledged message
        // are also acknowledged. Therefore, we have implicitly acknowledged the first message.
        receiveMessage(consumer, true);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println("Connection closed.");
    }
 
    /**
     * Sends a message through the producer.
     *
     * @param producer Message producer
     * @param session Session
     * @param messageText Text for the message to be sent
     * @throws JMSException
     */
    private static void sendMessage(MessageProducer producer, Session session, String messageText) throws JMSException {
        // Create a text message and send it
        producer.send(session.createTextMessage(messageText));
    }
 
    /**
     * Receives a message through the consumer synchronously with the default timeout (TIME_OUT_SECONDS).
     * If a message is received, the message is printed. If no message is received, "Queue is empty!" is
     * printed.
     *
     * @param consumer Message consumer
     * @param acknowledge If true and a message is received, the received message is acknowledged.
     * @throws JMSException
     */
    private static void receiveMessage(MessageConsumer consumer, boolean acknowledge) throws JMSException {
        // Receive a message
        Message message = consumer.receive(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        if (message == null) {
            System.out.println("Queue is empty!");
        } else {
            // Since this queue has only text messages, cast the message object and print the text
            System.out.println("Received: " + ((TextMessage) message).getText());
 
            // Acknowledge the message if asked
            if (acknowledge) message.acknowledge();
        }
    }
}
```

## SyncMessageReceiverUnorderedAcknowledge.java
<a name="example-synchronous-receiver-unordered-acknowledge-mode"></a>

다음 Java 코드 예제는 정렬되어 있지 않은 승인 모드를 사용하는 비동기식 소비자를 생성합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

/**
 * An example class to demonstrate the behavior of UNORDERED_ACKNOWLEDGE mode for received messages. This example
 * complements the example given in {@link SyncMessageReceiverClientAcknowledge} for CLIENT_ACKNOWLEDGE mode.
 *
 * First, a session, a message producer, and a message consumer are created. Then, two messages are sent. Next, two messages
 * are received but only the second one is acknowledged. After waiting for the visibility time out period, an attempt to
 * receive another message is made. It's shown that the first message received in the prior attempt is returned again
 * for the second attempt. In UNORDERED_ACKNOWLEDGE mode, all the messages must be explicitly acknowledged no matter what
 * the order they're received.
 *
 * This ISN'T the behavior for CLIENT_ACKNOWLEDGE mode. Please see {@link SyncMessageReceiverClientAcknowledge}
 * for an example.
 */
public class SyncMessageReceiverUnorderedAcknowledge {
 
    // Visibility time-out for the queue. It must match to the one set for the queue for this example to work.
    private static final long TIME_OUT_SECONDS = 1;
 
    public static void main(String args[]) throws JMSException, InterruptedException {
        // Create the configuration for the example
        ExampleConfiguration config = ExampleConfiguration.parseConfig("SyncMessageReceiverUnorderedAcknowledge", args);
 
        // Setup logging for the example
        ExampleCommon.setupLogging();
 
        // Create the connection factory based on the config
        SQSConnectionFactory connectionFactory = new SQSConnectionFactory(
                new ProviderConfiguration(),
                AmazonSQSClientBuilder.standard()
                        .withRegion(config.getRegion().getName())
                        .withCredentials(config.getCredentialsProvider())
                );
 
        // Create the connection
        SQSConnection connection = connectionFactory.createConnection();
 
        // Create the queue if needed
        ExampleCommon.ensureQueueExists(connection, config.getQueueName());
 
        // Create the session  with unordered acknowledge mode
        Session session = connection.createSession(false, SQSSession.UNORDERED_ACKNOWLEDGE);
 
        // Create the producer and consume
        MessageProducer producer = session.createProducer(session.createQueue(config.getQueueName()));
        MessageConsumer consumer = session.createConsumer(session.createQueue(config.getQueueName()));
 
        // Open the connection
        connection.start();
 
        // Send two text messages
        sendMessage(producer, session, "Message 1");
        sendMessage(producer, session, "Message 2");
 
        // Receive a message and don't acknowledge it
        receiveMessage(consumer, false);
 
        // Receive another message and acknowledge it
        receiveMessage(consumer, true);
 
        // Wait for the visibility time out, so that unacknowledged messages reappear in the queue
        System.out.println("Waiting for visibility timeout...");
        Thread.sleep(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        // Attempt to receive another message and acknowledge it. This results in receiving the first message since
        // we have acknowledged only the second message. In the UNORDERED_ACKNOWLEDGE mode, all the messages must
        // be explicitly acknowledged.
        receiveMessage(consumer, true);
 
        // Close the connection. This closes the session automatically
        connection.close();
        System.out.println("Connection closed.");
    }
 
    /**
     * Sends a message through the producer.
     *
     * @param producer Message producer
     * @param session Session
     * @param messageText Text for the message to be sent
     * @throws JMSException
     */
    private static void sendMessage(MessageProducer producer, Session session, String messageText) throws JMSException {
        // Create a text message and send it
        producer.send(session.createTextMessage(messageText));
    }
 
    /**
     * Receives a message through the consumer synchronously with the default timeout (TIME_OUT_SECONDS).
     * If a message is received, the message is printed. If no message is received, "Queue is empty!" is
     * printed.
     *
     * @param consumer Message consumer
     * @param acknowledge If true and a message is received, the received message is acknowledged.
     * @throws JMSException
     */
    private static void receiveMessage(MessageConsumer consumer, boolean acknowledge) throws JMSException {
        // Receive a message
        Message message = consumer.receive(TimeUnit.SECONDS.toMillis(TIME_OUT_SECONDS));
 
        if (message == null) {
            System.out.println("Queue is empty!");
        } else {
            // Since this queue has only text messages, cast the message object and print the text
            System.out.println("Received: " + ((TextMessage) message).getText());
 
            // Acknowledge the message if asked
            if (acknowledge) message.acknowledge();
        }
    }
}
```

## SpringExampleConfiguration.xml
<a name="example-spring-configuration"></a>

다음 XML 코드 예제는 [SpringExample.java](#example-spring)의 빈(bean) 구성 파일입니다.

```
<!--
    Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.

    Licensed under the Apache License, Version 2.0 (the "License").
    You may not use this file except in compliance with the License.
    A copy of the License is located at

    https://aws.amazon.com/apache2.0

    or in the "license" file accompanying this file. This file 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.
-->

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:util="http://www.springframework.org/schema/util"
    xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.0.xsd
    ">
    
    <bean id="CredentialsProviderBean" class="com.amazonaws.auth.DefaultAWSCredentialsProviderChain"/>
    
    <bean id="ClientBuilder" class="com.amazonaws.services.sqs.AmazonSQSClientBuilder" factory-method="standard">
        <property name="region" value="us-east-2"/>
        <property name="credentials" ref="CredentialsProviderBean"/>               
    </bean>
    
    <bean id="ProviderConfiguration" class="com.amazon.sqs.javamessaging.ProviderConfiguration">
        <property name="numberOfMessagesToPrefetch" value="5"/>
    </bean>
    
    <bean id="ConnectionFactory" class="com.amazon.sqs.javamessaging.SQSConnectionFactory">
        <constructor-arg ref="ProviderConfiguration" />
        <constructor-arg ref="ClientBuilder" />
    </bean>
    
    <bean id="Connection" class="javax.jms.Connection"
        factory-bean="ConnectionFactory"
        factory-method="createConnection"
        init-method="start"
        destroy-method="close" />
    
    <bean id="QueueName" class="java.lang.String">
        <constructor-arg value="SQSJMSClientExampleQueue"/>
    </bean>
</beans>
```

## SpringExample.java
<a name="example-spring"></a>

다음 Java 코드 예제는 객체를 초기화하는 빈(bean) 구성 파일을 사용합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */
                
public class SpringExample {
    public static void main(String args[]) throws JMSException {
        if( args.length != 1 || !args[0].endsWith(".xml")) {
            System.err.println( "Usage: " + SpringExample.class.getName() + " <spring config.xml>" );
            System.exit(1);
        }
        
        File springFile = new File( args[0] );
        if( !springFile.exists() || !springFile.canRead() ) {
            System.err.println( "File " + args[0] + " doesn't exist or isn't readable.");
            System.exit(2);
        }
        
        ExampleCommon.setupLogging();
        
        FileSystemXmlApplicationContext context = 
            new FileSystemXmlApplicationContext( "file://" + springFile.getAbsolutePath() );
        
        Connection connection;
        try {
            connection = context.getBean(Connection.class);
        } catch( NoSuchBeanDefinitionException e ) {
            System.err.println( "Can't find the JMS connection to use: " + e.getMessage() );
            System.exit(3);
            return;
        }
        
        String queueName;
        try {
            queueName = context.getBean("QueueName", String.class);
        } catch( NoSuchBeanDefinitionException e ) {
            System.err.println( "Can't find the name of the queue to use: " + e.getMessage() );
            System.exit(3);
            return;
        }
        
        if( connection instanceof SQSConnection ) {
            ExampleCommon.ensureQueueExists( (SQSConnection) connection, queueName );
        }
        
        // Create the session
        Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
        MessageConsumer consumer = session.createConsumer( session.createQueue( queueName) );
        
        receiveMessages(session, consumer);
 
        // The context can be setup to close the connection for us
        context.close();
        System.out.println( "Context closed" );
    }
 
    private static void receiveMessages( Session session, MessageConsumer consumer ) {
        try {
            while( true ) {
                System.out.println( "Waiting for messages");
                // Wait 1 minute for a message
                Message message = consumer.receive(TimeUnit.MINUTES.toMillis(1));
                if( message == null ) {
                    System.out.println( "Shutting down after 1 minute of silence" );
                    break;
                }
                ExampleCommon.handleMessage(message);
                message.acknowledge();
                System.out.println( "Acknowledged message" );
            }
        } catch (JMSException e) {
            System.err.println( "Error receiving from SQS: " + e.getMessage() );
            e.printStackTrace();
        }
    }
}
```

## ExampleCommon.java
<a name="example-common"></a>

다음 Java 코드 예제는 Amazon SQS 대기열이 존재하는지 확인하고 나서 존재하지 않으면 대기열 하나를 생성합니다. 또한 예제 로깅 코드를 포함합니다.

```
/*
 * Copyright 2010-2024 Amazon.com, Inc. or its affiliates. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License").
 * You may not use this file except in compliance with the License.
 * A copy of the License is located at
 *
 *  https://aws.amazon.com/apache2.0
 *
 * or in the "license" file accompanying this file. This file 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.
 *
 */

public class ExampleCommon {
    /**
     * A utility function to check the queue exists and create it if needed. For most  
     * use cases this is usually done by an administrator before the application is run. 
     */
    public static void ensureQueueExists(SQSConnection connection, String queueName) throws JMSException {
        AmazonSQSMessagingClientWrapper client = connection.getWrappedAmazonSQSClient();
        
        /**
         * In most cases, you can do this with just a createQueue call, but GetQueueUrl 
         * (called by queueExists) is a faster operation for the common case where the queue 
         * already exists. Also many users and roles have permission to call GetQueueUrl
         * but don't have permission to call CreateQueue.
         */
        if( !client.queueExists(queueName) ) {
            client.createQueue( queueName );
        }
    }
 
    public static void setupLogging() {
        // Setup logging
        BasicConfigurator.configure();
        Logger.getRootLogger().setLevel(Level.WARN);
    }
 
    public static void handleMessage(Message message) throws JMSException {
        System.out.println( "Got message " + message.getJMSMessageID() );
        System.out.println( "Content: ");
        if( message instanceof TextMessage ) {
            TextMessage txtMessage = ( TextMessage ) message;
            System.out.println( "\t" + txtMessage.getText() );
        } else if( message instanceof BytesMessage ){
            BytesMessage byteMessage = ( BytesMessage ) message;
            // Assume the length fits in an int - SQS only supports sizes up to 256k so that
            // should be true
            byte[] bytes = new byte[(int)byteMessage.getBodyLength()];
            byteMessage.readBytes(bytes);
            System.out.println( "\t" +  Base64.encodeAsString( bytes ) );
        } else if( message instanceof ObjectMessage ) {
            ObjectMessage objMessage = (ObjectMessage) message;
            System.out.println( "\t" + objMessage.getObject() );
        }
    }
}
```

# Amazon SQS 지원 JMS 1.1 구현
<a name="supported-implementations"></a>

Amazon SQS 자바 메시징 라이브러리는 다음과 같은 [JMS 1.1 구현](http://docs.oracle.com/javaee/6/api/javax/jms/package-summary.html)을 지원합니다. Amazon SQS Java 메시징 라이브러리의 지원 기능 및 역량에 대한 자세한 내용은 [Amazon SQS FAQ](https://aws.amazon.com/sqs/faqs/)를 참조하세요.

## 지원되는 공통 인터페이스
<a name="supported-common-interfaces"></a>
+ `Connection`
+ `ConnectionFactory`
+ `Destination`
+ `Session`
+ `MessageConsumer`
+ `MessageProducer`

## 지원되는 메시지 유형
<a name="supported-message-types"></a>
+ `ByteMessage`
+ `ObjectMessage`
+ `TextMessage`

## 지원되는 메시지 승인 모드
<a name="supported-message-acknowledgement-modes"></a>
+ `AUTO_ACKNOWLEDGE`
+ `CLIENT_ACKNOWLEDGE`
+ `DUPS_OK_ACKNOWLEDGE`
+ `UNORDERED_ACKNOWLEDGE`

**참고**  
`UNORDERED_ACKNOWLEDGE` 모드는 JMS 1.1 사양의 일부가 아닙니다. 이 모드를 통해 Amazon SQS에서 JMS 클라이언트가 메시지를 명시적으로 승인하도록 허용합니다.

## JMS 정의된 헤더 및 예약된 속성
<a name="jms-defined-headers-reserved-properties"></a>

### 메시지 전송의 경우
<a name="for-sending-messages"></a>

메시지를 전송하는 경우 사용자는 각 메시지에 대해 다음과 같은 헤더 및 속성을 설정할 수 있습니다.
+ `JMSXGroupID`(FIFO 대기열에서 필수, 표준 대기열에서는 허용되지 않음)
+ `JMS_SQS_DeduplicationId`(FIFO 대기열에서 선택 사항, 표준 대기열에서는 허용되지 않음)

사용자가 메시지를 전송한 후 Amazon SQS는 각 메시지에 대해 다음과 같은 헤더 및 속성을 설정합니다.
+ `JMSMessageID`
+ `JMS_SQS_SequenceNumber`(FIFO 대기열에만 해당)

### 메시지 수신의 경우
<a name="for-receiving-messages"></a>

사용자가 메시지를 수신한 후 Amazon SQS는 각 메시지에 대해 다음과 같은 헤더 및 속성을 설정합니다.
+ `JMSDestination`
+ `JMSMessageID`
+ `JMSRedelivered`
+ `JMSXDeliveryCount`
+ `JMSXGroupID`(FIFO 대기열에만 해당)
+ `JMS_SQS_DeduplicationId`(FIFO 대기열에만 해당)
+ `JMS_SQS_SequenceNumber`(FIFO 대기열에만 해당)