diff --git a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
index f7e3bcb5eb317..5f55e13d99146 100755
--- a/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
+++ b/eng/code-quality-reports/src/main/resources/spotbugs/spotbugs-exclude.xml
@@ -439,6 +439,7 @@
+
diff --git a/eng/jacoco-test-coverage/pom.xml b/eng/jacoco-test-coverage/pom.xml
index ea21a08695cb7..cee087f22d298 100644
--- a/eng/jacoco-test-coverage/pom.xml
+++ b/eng/jacoco-test-coverage/pom.xml
@@ -32,6 +32,7 @@
4.0.0-preview.15.0.0-preview.212.0.0-preview.1
+ 12.0.0-preview.1
@@ -93,7 +94,11 @@
-
+
+ com.azure
+ azure-storage-queue
+ ${azure-storage-queue.version}
+
diff --git a/eng/spotbugs-aggregate-report/pom.xml b/eng/spotbugs-aggregate-report/pom.xml
index a8f5addab7e12..f390bb0c7db4c 100644
--- a/eng/spotbugs-aggregate-report/pom.xml
+++ b/eng/spotbugs-aggregate-report/pom.xml
@@ -30,6 +30,7 @@
4.0.0-preview.15.0.0-preview.212.0.0-preview.1
+ 12.0.0-preview.1
@@ -182,7 +183,11 @@
-
+
+ com.azure
+ azure-storage-queue
+ ${azure-storage-queue.version}
+
diff --git a/pom.client.xml b/pom.client.xml
index d4ed7878ba447..e833ab1290e4e 100644
--- a/pom.client.xml
+++ b/pom.client.xml
@@ -393,6 +393,10 @@
Azure Storage - Blobscom.azure.storage.blob*
+
+ Azure Storage - Queues
+ com.azure.storage.queue*
+
https://docs.oracle.com/javase/8/docs/api/
@@ -546,7 +550,8 @@
-snippetpath ${project.basedir}/sdk/eventhubs/azure-eventhubs/src/samples/java
-snippetpath ${project.basedir}/sdk/keyvault/azure-keyvault-keys/src/samples/java
-snippetpath ${project.basedir}/sdk/keyvault/azure-keyvault-secrets/src/samples/java
-
+
+ -snippetpath ${project.basedir}/storage/client/queue/src/samples/java
@@ -748,5 +753,6 @@
./sdk/identity/azure-identity./storage/client/blob
+ ./storage/client/queue
diff --git a/storage/client/queue/README.md b/storage/client/queue/README.md
index 7b4dbbf1afadd..436f7e6f2094a 100644
--- a/storage/client/queue/README.md
+++ b/storage/client/queue/README.md
@@ -26,9 +26,7 @@ A single queue message can be up to 64 KB in size, and a queue can contain milli
To create a Storage Account you can use the Azure Portal or [Azure CLI][azure_cli].
```Powershell
-az group create \
- --name storage-resource-group \
- --location westus
+az group create --name storage-resource-group --location westus
```
### Authenticate the client
@@ -52,7 +50,6 @@ az storage queue generate-sas
```Powershell
CONNECTION_STRING=
-#usage example
az storage queue generate-sas
--name javasdksas
--expiry 2019-06-05
@@ -112,10 +109,10 @@ The queue service do operations on the queues in the storage account and manage
### Queue Service Client
The client performs the interactions with the Queue service, create or delete a queue, getting and setting Queue properties, list queues in account, and get queue statistics. An asynchronous, `QueueServiceAsyncClient`, and synchronous, `QueueClient`, client exists in the SDK allowing for selection of a client based on an application's use case.
-Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${sasToken}`.
+Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${SASToken}`.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName)
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueURL).credential(SASToken).build();
QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue");
```
@@ -123,8 +120,9 @@ QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue");
or
```Java
-String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceAsyncClient queueServiceAsyncClient = QueueServiceAsyncClient.builder().endpoint(queueServiceAsyncURL).build();
+String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/", accountName)
+QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder().endpoint(queueServiceAsyncURL)
+ credential(SASToken).build();
queueServiceAsyncClient.createQueue("newAsyncQueue").subscribe(
result -> {
// do something when new queue created
@@ -142,10 +140,10 @@ Azure Queue storage is a service for storing large numbers of messages that can
A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account.
### QueueClient
-Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${sasToken}`.
+Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${SASToken}`.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueURL = String.format("https://%s.queue.core.windows.net/%s", accountName, queueName);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).credential(SASToken).build();
// metadata is map of key-value pair, timeout is client side timeout
QueueClient newQueueClient = queueClient.create(metadata, timeout);
```
@@ -170,6 +168,7 @@ queueAsyncClient.create(metadata, timeout).subscribe(
## Examples
The following sections provide several code snippets covering some of the most common Configuration Service tasks, including:
+- [Build a client](#build-a-client)
- [Create a Queue](#Create-a-queue)
- [Delete a queue](#Delete-a-queue)
- [List the queues in account](#List-queues-in-account)
@@ -183,32 +182,54 @@ The following sections provide several code snippets covering some of the most c
- [Delete message from a queue](#Delete-message-from-a-queue)
- [Get a Queue properties](#Get-a-queue-properties)
- [Set/Update a Queue metadata](#Set-a-queue-metadata)
+
+### Build a client
+We have two ways of building QueueService or Queue Client. Here will take queueServiceClient as an example. Same things apply to queueClient.
+
+First, build client from full URL/endpoint (e.g. with queueName, with SASToken and etc.)
+
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient();
+```
+
+Or
+
+We can build the queueServiceClient from the builder using `${SASToken}` as credential.
+
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
+```
+
### Create a queue
-Create a queue in the Storage Account. Throws StorageErrorException If the queue fails to be created.
+Create a queue in the Storage Account using `${SASToken}` as credential.
+Throws StorageErrorException If the queue fails to be created.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue");
```
### Delete a queue
-Delete a queue in the Storage Account. Throws StorageErrorException If the queue fails to be deleted.
+Delete a queue in the Storage Account using `${SASToken}` as credential.
+Throws StorageErrorException If the queue fails to be deleted.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
QueueClient newQueueServiceClient = queueServiceClient.deleteQueue("myqueue");
```
### List queues in account
-List all the queues in account.
+List all the queues in account using `${SASToken}` as credential.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
// @param marker: Starting point to list the queues
// @param options: Filter for queue selection
queueServiceClient.listQueuesSegment(marker, options).forEach{
@@ -219,9 +240,11 @@ queueServiceClient.listQueuesSegment(marker, options).forEach{
### Get properties in queue account
Get queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
+
+Use `${SASToken}` as credential.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
Response properties = queueServiceClient.getProperties();
```
@@ -229,9 +252,11 @@ Response properties = queueServiceClient.getProperties
### Set properties in queue account
Set queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
+
+Use `${SASToken}` as credential.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
StorageServiceProperties properties = new StorageServiceProperties() {
// logging: some logging;
@@ -244,30 +269,34 @@ queueServiceClient.setProperties(properties);
```
### Get queue service statistics
-he `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service.
+The `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service.
+
+Use `${SASToken}` as credential.
It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account.
```Java
-String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
-QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+String queueServiceURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).credential(SASToken).buildClient();
Response queueStats = queueServiceClient.getStatistics();
```
### Enqueue message into a queue
The operation adds a new message to the back of the message queue. A visibility timeout can also be specified to make the message invisible until the visibility timeout expires.
+
+Use `${SASToken}` as credential.
A message must be in a format that can be included in an XML request with UTF-8 encoding. The encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size for previous versions.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
queueClient.enqueueMessage("myMessage");
```
### Update messaged from a queue
-The operation updates a message in the message queue.
+The operation updates a message in the message queue. Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
// @param messageId Id of the message
// @param popReceipt Unique identifier that must match the message for it to be updated
// @param visibilityTimeout How long the message will be invisible in the queue in seconds
@@ -275,48 +304,52 @@ queueClient.updateMessage(messageId, "new message", popReceipt, visibilityTimeou
```
### Peek messages from a queue
-The operation retrieves one or more messages from the front of the queue.
+The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
queueClient.peekMessages().forEach(message-> {print message.messageText();});
```
### Dequeue messages from a queue
-The operation retrieves one or more messages from the front of the queue.
+The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
queueClient.dequeueMessage("myMessage").forEach(message-> {print message.messageText();});
```
### Delete message from a queue
-The operation retrieves one or more messages from the front of the queue.
+The operation retrieves one or more messages from the front of the queue. Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
queueClient.deleteMessage(messageId, popReceipt);
```
### Get a queue properties
The operation retrieves user-defined metadata and queue properties on the specified queue. Metadata is associated with the queue as name-values pairs.
+
+Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
Response properties = queueClient.getProperties();
```
### Set a queue metadata
The operation sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs.
+
+Use `${SASToken}` as credential.
```Java
-String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
-QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+String queueSURL = String.format("https://%s.queue.core.windows.net", accountName);
+QueueClient queueClient = new QueueClientBuilder().endpoint(queueURL).credential(SASToken).queueName("myqueue").buildClient();
Map metadata = new HashMap<>() {{
put("key1", "val1");
@@ -335,10 +368,11 @@ When you interact with queue using this Java client library, errors returned by
## Next steps
### More Samples
-- QueueServiceSample
-- MessageSample
-- QueueExceptionSample
-- AsyncSample
+Get started with our [Queue samples][samples]:
+- [QueueServiceSample](src/samples/java/blob/QueueServiceSample.java): Create, list and delete queues
+- [MessageSample](src/samples/java/blob/MessageSample.java): Enqueue, peek dequeue, update, clear and delete messages. Get properties of the queue.
+- [QueueExceptionSample](src/samples/java/blob/QueueExceptionSample.java): Handle the exceptions from storage queue service side.
+- [AsyncSample](src/samples/java/blob/AsyncSample.java): Create queue and enqueue message using async queue client call.
[Quickstart: Create a Java Spring app with App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-java-spring-app)
@@ -375,3 +409,4 @@ If you would like to become an active contributor to this project please follow
[azure_cli]: https://docs.microsoft.com/cli/azure
[sas_token]: https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1
[storage_rest]: https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-error-codes
+[samples]: samples/
diff --git a/storage/client/queue/pom.xml b/storage/client/queue/pom.xml
new file mode 100644
index 0000000000000..c018da31ab260
--- /dev/null
+++ b/storage/client/queue/pom.xml
@@ -0,0 +1,78 @@
+
+
+
+ com.azure
+ azure-client-sdk-parent
+ 1.1.0
+ ../../../pom.client.xml
+
+
+ 4.0.0
+
+ com.azure
+ azure-storage-queue
+ 12.0.0-preview.1
+
+ azure-storage-queue
+ https://github.com/Azure/azure-sdk-for-java
+
+
+
+ azure-java-build-docs
+ ${site.url}/site/${project.artifactId}
+
+
+
+
+ scm:git:https://github.com/Azure/azure-sdk-for-java
+ scm:git:git@github.com:Azure/azure-sdk-for-java.git
+ HEAD
+
+
+
+
+ com.azure
+ azure-core
+ 1.0.0-preview.2
+
+
+ org.slf4j
+ slf4j-api
+
+
+
+ com.azure
+ azure-core-test
+ 1.0.0-preview.2
+ test
+
+
+ com.azure
+ azure-identity
+ 1.0.0-preview.1
+ test
+
+
+ junit
+ junit
+ test
+
+
+ org.slf4j
+ slf4j-simple
+ test
+
+
+ io.projectreactor
+ reactor-test
+ test
+
+
+ com.microsoft.azure
+ adal4j
+ test
+
+
+
diff --git a/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java b/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java
index 19b2b4c307221..db8045e723a1a 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/common/credentials/SharedKeyCredential.java
@@ -4,6 +4,7 @@
package com.azure.storage.common.credentials;
import com.azure.core.implementation.util.ImplUtils;
+import com.azure.core.util.logging.ClientLogger;
import io.netty.handler.codec.http.QueryStringDecoder;
import javax.crypto.Mac;
@@ -26,11 +27,12 @@
* SharedKey credential policy that is put into a header to authorize requests.
*/
public final class SharedKeyCredential {
+ private static final ClientLogger LOGGER = new ClientLogger(SharedKeyCredential.class);
private static final String AUTHORIZATION_HEADER_FORMAT = "SharedKey %s:%s";
// Pieces of the connection string that are needed.
- private static final String ACCOUNT_NAME = "AccountName".toLowerCase();
- private static final String ACCOUNT_KEY = "AccountKey".toLowerCase();
+ private static final String ACCOUNT_NAME = "accountname";
+ private static final String ACCOUNT_KEY = "accountkey";
private final String accountName;
private final byte[] accountKey;
@@ -59,7 +61,7 @@ public static SharedKeyCredential fromConnectionString(String connectionString)
HashMap connectionStringPieces = new HashMap<>();
for (String connectionStringPiece : connectionString.split(";")) {
String[] kvp = connectionStringPiece.split("=", 2);
- connectionStringPieces.put(kvp[0].toLowerCase(), kvp[1]);
+ connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]);
}
String accountName = connectionStringPieces.get(ACCOUNT_NAME);
@@ -98,9 +100,11 @@ public String generateAuthorizationHeader(URL requestURL, String httpMethod, Map
*
* @param stringToSign The UTF-8-encoded string to sign.
* @return A {@code String} that contains the HMAC-SHA256-encoded signature.
- * @throws InvalidKeyException If the accountKey is not a valid Base64-encoded string.
+ * @throws RuntimeException for one of the following cases:
+ * - If the HMAC-SHA256 signature for {@code sharedKeyCredentials} fails to generate.
+ * - If the an invalid key has been given to the client.
*/
- public String computeHmac256(final String stringToSign) throws InvalidKeyException {
+ public String computeHmac256(final String stringToSign) {
try {
/*
We must get a new instance of the Mac calculator for each signature calculated because the instances are
@@ -111,8 +115,12 @@ public String computeHmac256(final String stringToSign) throws InvalidKeyExcepti
hmacSha256.init(new SecretKeySpec(this.accountKey, "HmacSHA256"));
byte[] utf8Bytes = stringToSign.getBytes(StandardCharsets.UTF_8);
return Base64.getEncoder().encodeToString(hmacSha256.doFinal(utf8Bytes));
- } catch (final NoSuchAlgorithmException e) {
- throw new Error(e);
+ } catch (final NoSuchAlgorithmException e) {
+ LOGGER.asError().log(e.getMessage());
+ throw new RuntimeException(e);
+ } catch (InvalidKeyException e) {
+ LOGGER.asError().log("Please double check the account key. Error details: " + e.getMessage());
+ throw new RuntimeException("Please double check the account key. Error details: " + e.getMessage());
}
}
@@ -121,20 +129,20 @@ private String buildStringToSign(URL requestURL, String httpMethod, MapSample Code
View {@link QueueClientBuilder this} for additional ways to construct the client.
+ *
+ * @see QueueClientBuilder
+ * @see QueueClient
+ * @see SharedKeyCredential
+ * @see SASTokenCredential
+ */
+public final class QueueAsyncClient {
+ private static final ClientLogger LOGGER = new ClientLogger(QueueAsyncClient.class);
+ private final AzureQueueStorageImpl client;
+ private final String queueName;
+
+ /**
+ * Creates a QueueAsyncClient that sends requests to the storage queue service at {@code AzureQueueStorageImpl#url() endpoint}.
+ * Each service call goes through the {@link HttpPipeline pipeline} in the {@code AzureQueueStorageImpl client}.
+ *
+ * @param client Client that interacts with the service interfaces
+ * @param queueName Name of the queue
+ */
+ QueueAsyncClient(AzureQueueStorageImpl client, String queueName) {
+ this.queueName = queueName;
+
+ this.client = new AzureQueueStorageBuilder().pipeline(client.httpPipeline())
+ .url(client.url())
+ .version(client.version())
+ .build();
+ }
+
+ /**
+ * Creates a QueueAsyncClient that sends requests to the storage queue service at {@code endpoint}.
+ * Each service call goes through the {@code httpPipeline}.
+ *
+ * @param endpoint URL for the Storage Queue service
+ * @param httpPipeline HttpPipeline that the HTTP requests and response flow through
+ * @param queueName Name of the queue
+ */
+ QueueAsyncClient(URL endpoint, HttpPipeline httpPipeline, String queueName) {
+ this.queueName = queueName;
+
+ this.client = new AzureQueueStorageBuilder().pipeline(httpPipeline)
+ .url(endpoint.toString())
+ .build();
+ }
+
+ /**
+ * @return the URL of the storage queue
+ * @throws RuntimeException If the queue is using a malformed URL.
+ */
+ public URL getQueueUrl() {
+ try {
+ return new URL(client.url());
+ } catch (MalformedURLException ex) {
+ LOGGER.asError().log("Queue URL is malformed");
+ throw new RuntimeException("Queue URL is malformed");
+ }
+ }
+
+ /**
+ * Creates a new queue.
+ *
+ *
Code Samples
+ *
+ *
Create a queue
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.create}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If a queue with the same name already exists in the queue service.
+ */
+ public Mono create() {
+ return create(null);
+ }
+
+ /**
+ * Creates a new queue.
+ *
+ *
Code Samples
+ *
+ *
Create a queue with metadata "queue:metadataMap"
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.create#map}
+ *
+ * @param metadata Metadata to associate with the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists in the queue service.
+ */
+ public Mono create(Map metadata) {
+ return client.queues().createWithRestResponseAsync(queueName, null, metadata, null, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Permanently deletes the queue.
+ *
+ *
Code Samples
+ *
+ *
Delete a queue
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.delete}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono delete() {
+ return client.queues().deleteWithRestResponseAsync(queueName, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Retrieves metadata and approximate message count of the queue.
+ *
+ *
Code Samples
+ *
+ *
Get the properties of the queue
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.getProperties}
+ *
+ * @return A response containing a {@link QueueProperties} value which contains the metadata and approximate
+ * messages count of the queue.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono> getProperties() {
+ return client.queues().getPropertiesWithRestResponseAsync(queueName, Context.NONE)
+ .map(this::getQueuePropertiesResponse);
+ }
+
+ /**
+ * Sets the metadata of the queue.
+ *
+ * Passing in a {@code null} value for metadata will clear the metadata associated with the queue.
+ *
+ *
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.clearMetadata#map}
+ *
+ * @param metadata Metadata to set on the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono setMetadata(Map metadata) {
+ return client.queues().setMetadataWithRestResponseAsync(queueName, null, metadata, null, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Retrieves stored access policies specified on the queue.
+ *
+ *
Code Samples
+ *
+ *
List the stored access policies
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.getAccessPolicy}
+ *
+ * @return The stored access policies specified on the queue.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Flux getAccessPolicy() {
+ return client.queues().getAccessPolicyWithRestResponseAsync(queueName, Context.NONE)
+ .flatMapMany(response -> Flux.fromIterable(response.value()));
+ }
+
+ /**
+ * Sets stored access policies on the queue.
+ *
+ *
Code Samples
+ *
+ *
Set a read only stored access policy
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.setAccessPolicy}
+ *
+ * @param permissions Access policies to set on the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist, a stored access policy doesn't have all fields filled out,
+ * or the queue will have more than five policies.
+ */
+ public Mono setAccessPolicy(List permissions) {
+ return client.queues().setAccessPolicyWithRestResponseAsync(queueName, permissions, null, null, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Deletes all messages in the queue.
+ *
+ *
Code Samples
+ *
+ *
Clear the messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.clearMessages}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono clearMessages() {
+ return client.messages().clearWithRestResponseAsync(queueName, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Enqueues a message that has a time-to-live of 7 days and is instantly visible.
+ *
+ *
Code Samples
+ *
+ *
Enqueue a message of "Hello, Azure"
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.enqueueMessage#string}
+ *
+ * @param messageText Message text
+ * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and
+ * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata
+ * about the enqueued message.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono> enqueueMessage(String messageText) {
+ return enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofDays(7));
+ }
+
+ /**
+ * Enqueues a message with a given time-to-live and a timeout period where the message is invisible in the queue.
+ *
+ *
Code Samples
+ *
+ *
Add a message of "Hello, Azure" that has a timeout of 5 seconds
Add a message of "Goodbye, Azure" that has a time to live of 5 seconds
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration}
+ *
+ * @param messageText Message text
+ * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds.
+ * If unset the value will default to 0 and the message will be instantly visible. The timeout must be between 0
+ * seconds and 7 days.
+ * @param timeToLive Optional. How long the message will stay alive in the queue in seconds. If unset the value will
+ * default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number.
+ * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and
+ * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata
+ * about the enqueued message.
+ * @throws StorageErrorException If the queue doesn't exist or the {@code visibilityTimeout} or {@code timeToLive}
+ * are outside of the allowed limits.
+ */
+ public Mono> enqueueMessage(String messageText, Duration visibilityTimeout, Duration timeToLive) {
+ Integer visibilityTimeoutInSeconds = (visibilityTimeout == null) ? null : (int) visibilityTimeout.getSeconds();
+ Integer timeToLiveInSeconds = (timeToLive == null) ? null : (int) timeToLive.getSeconds();
+ QueueMessage message = new QueueMessage().messageText(messageText);
+
+ return client.messages().enqueueWithRestResponseAsync(queueName, message, visibilityTimeoutInSeconds, timeToLiveInSeconds, null, null, Context.NONE)
+ .map(response -> new SimpleResponse<>(response, response.value().get(0)));
+ }
+
+ /**
+ * Retrieves the first message in the queue and hides it from other operations for 30 seconds.
+ *
+ *
Code Samples
+ *
+ *
Dequeue a message
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages}
+ *
+ * @return The first {@link DequeuedMessage} in the queue, it contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message, additionally it contains other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Flux dequeueMessages() {
+ return dequeueMessages(1, Duration.ofSeconds(30));
+ }
+
+ /**
+ * Retrieves up to the maximum number of messages from the queue and hides them from other operations for 30 seconds.
+ *
+ *
Code Samples
+ *
+ *
Dequeue up to 5 messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer}
+ *
+ * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested
+ * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32
+ * messages.
+ * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DequeuedMessage contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message and other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds
+ */
+ public Flux dequeueMessages(Integer maxMessages) {
+ return dequeueMessages(maxMessages, Duration.ofSeconds(30));
+ }
-public class QueueAsyncClient extends ServiceClient {
- private final String endpoint;
- private final AzureQueueStorageImpl generateClient;
- private final String apiVersion;
+ /**
+ * Retrieves up to the maximum number of messages from the queue and hides them from other operations for the
+ * timeout period.
+ *
+ *
Code Samples
+ *
+ *
Dequeue up to 5 messages and give them a 60 second timeout period
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration}
+ *
+ * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested
+ * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32
+ * messages.
+ * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds.
+ * If left empty the dequeued messages will be invisible for 30 seconds. The timeout must be between 1 second and 7 days.
+ * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DeqeuedMessage contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message and other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} or {@code visibilityTimeout} is
+ * outside of the allowed bounds
+ */
+ public Flux dequeueMessages(Integer maxMessages, Duration visibilityTimeout) {
+ Integer visibilityTimeoutInSeconds = (visibilityTimeout == null) ? null : (int) visibilityTimeout.getSeconds();
+ return client.messages().dequeueWithRestResponseAsync(queueName, maxMessages, visibilityTimeoutInSeconds, null, null, Context.NONE)
+ .flatMapMany(response -> Flux.fromIterable(response.value()));
+ }
- private QueueAsyncClient(URL endpoint, HttpPipeline httpPipeline) {
- super(httpPipeline);
- this.endpoint = endpoint.toString();
- this.generateClient = new AzureQueueStorageBuilder().pipeline(httpPipeline).url(this.endpoint).build();
- this.apiVersion = this.generateClient.version();
+ /**
+ * Peeks the first message in the queue.
+ *
+ * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide
+ * messages from other operations on the queue.
+ *
+ *
Code Samples
+ *
+ *
Peek the first message
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.peekMessages}
+ *
+ * @return A {@link PeekedMessage} that contains metadata about the message.
+ */
+ public Flux peekMessages() {
+ return peekMessages(null);
+ }
+
+ /**
+ * Peek messages from the front of the queue up to the maximum number of messages.
+ *
+ * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide
+ * messages from other operations on the queue.
+ *
+ *
Code Samples
+ *
+ *
Peek up to the first five messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.peekMessages#integer}
+ *
+ * @param maxMessages Optional. Maximum number of messages to peek, if there are less messages exist in the queue than requested
+ * all the messages will be peeked. If left empty only 1 message will be peeked, the allowed range is 1 to 32
+ * messages.
+ * @return Up to {@code maxMessages} {@link PeekedMessage PeekedMessages} from the queue. Each PeekedMessage contains
+ * metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds
+ */
+ public Flux peekMessages(Integer maxMessages) {
+ return client.messages().peekWithRestResponseAsync(queueName, maxMessages, null, null, Context.NONE)
+ .flatMapMany(response -> Flux.fromIterable(response.value()));
}
/**
- * Creates a appendBlobClientBuilder that can configure options for the SecretAsyncClient before creating an instance of it.
- * @return A new appendBlobClientBuilder to create a SecretAsyncClient from.
+ * Updates the specific message in the queue with a new message and resets the visibility timeout.
+ *
+ *
Code Samples
+ *
+ *
Dequeue the first message and update it to "Hello again, Azure" and hide it for 5 seconds
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.updateMessage}
+ *
+ * @param messageText Updated value for the message
+ * @param messageId Id of the message to update
+ * @param popReceipt Unique identifier that must match for the message to be updated
+ * @param visibilityTimeout The timeout period for how long the message is invisible in the queue in seconds. The
+ * timeout period must be between 1 second and 7 days.
+ * @return A {@link UpdatedMessage} that contains the new {@link UpdatedMessage#popReceipt() popReceipt} to interact
+ * with the message, additionally contains the updated metadata about the message.
+ * @throws StorageErrorException If the queue or messageId don't exist, the popReceipt doesn't match on the message,
+ * or the {@code visibilityTimeout} is outside the allowed bounds
+ */
+ public Mono> updateMessage(String messageText, String messageId, String popReceipt, Duration visibilityTimeout) {
+ QueueMessage message = new QueueMessage().messageText(messageText);
+ return client.messageIds().updateWithRestResponseAsync(queueName, messageId, message, popReceipt, (int) visibilityTimeout.getSeconds(), Context.NONE)
+ .map(this::getUpdatedMessageResponse);
+ }
+
+ /**
+ * Deletes the specified message in the queue
+ *
+ *
Code Samples
+ *
+ *
Delete the first message
+ *
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.deleteMessage}
+ *
+ * @param messageId Id of the message to deleted
+ * @param popReceipt Unique identifier that must match for the message to be deleted
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue or messageId don't exist or the popReceipt doesn't match on the message
+ */
+ public Mono deleteMessage(String messageId, String popReceipt) {
+ return client.messageIds().deleteWithRestResponseAsync(queueName, messageId, popReceipt, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /*
+ * Maps the HTTP headers returned from the service to the expected response type
+ * @param response Service response
+ * @return Mapped response
+ */
+ private Response getQueuePropertiesResponse(QueuesGetPropertiesResponse response) {
+ QueueGetPropertiesHeaders propertiesHeaders = response.deserializedHeaders();
+ QueueProperties properties = new QueueProperties(propertiesHeaders.metadata(), propertiesHeaders.approximateMessagesCount());
+ return new SimpleResponse<>(response, properties);
+ }
+
+ /*
+ * Maps the HTTP headers returned from the service to the expected response type
+ * @param response Service response
+ * @return Mapped response
*/
- public static QueueAsyncClientBuilder builder() {
- return new QueueAsyncClientBuilder();
+ private Response getUpdatedMessageResponse(MessageIdsUpdateResponse response) {
+ MessageIdUpdateHeaders headers = response.deserializedHeaders();
+ UpdatedMessage updatedMessage = new UpdatedMessage(headers.popReceipt(), headers.timeNextVisible());
+ return new SimpleResponse<>(response, updatedMessage);
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java
deleted file mode 100644
index b76c9c63e8700..0000000000000
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueAsyncClientBuilder.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.azure.storage.queue;
-
-public class QueueAsyncClientBuilder {
-
-}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java
new file mode 100644
index 0000000000000..763c58560871e
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClient.java
@@ -0,0 +1,389 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.queue.models.DequeuedMessage;
+import com.azure.storage.queue.models.EnqueuedMessage;
+import com.azure.storage.queue.models.PeekedMessage;
+import com.azure.storage.queue.models.QueueProperties;
+import com.azure.storage.queue.models.SignedIdentifier;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.UpdatedMessage;
+import java.net.URL;
+import java.time.Duration;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * This class provides a client that contains all the operations for interacting with a queue in Azure Storage Queue.
+ * Operations allowed by the client are creating and deleting the queue, retrieving and updating metadata and access
+ * policies of the queue, and enqueuing, dequeuing, peeking, updating, and deleting messages.
+ *
+ *
View {@link QueueClientBuilder this} for additional ways to construct the client.
+ *
+ * @see QueueClientBuilder
+ * @see QueueAsyncClient
+ * @see SharedKeyCredential
+ * @see SASTokenCredential
+ */
+public final class QueueClient {
+ private final QueueAsyncClient client;
+
+ /**
+ * Creates a QueueClient that wraps a QueueAsyncClient and blocks requests.
+ *
+ * @param client QueueAsyncClient that is used to send requests
+ */
+ QueueClient(QueueAsyncClient client) {
+ this.client = client;
+ }
+
+ /**
+ * @return the URL of the storage queue.
+ * @throws RuntimeException If the queue is using a malformed URL.
+ */
+ public URL getQueueUrl() {
+ return client.getQueueUrl();
+ }
+
+ /**
+ * Creates a new queue.
+ *
+ *
Code Samples
+ *
+ *
Create a queue
+ *
+ *{@codesnippet com.azure.storage.queue.queueClient.create}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If a queue with the same name already exists in the queue service.
+ */
+ public VoidResponse create() {
+ return create(null);
+ }
+
+ /**
+ * Creates a new queue.
+ *
+ *
Code Samples
+ *
+ *
Create a queue with metadata "queue:metadataMap"
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.create#map}
+ *
+ * @param metadata Metadata to associate with the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists in the queue service.
+ */
+ public VoidResponse create(Map metadata) {
+ return client.create(metadata).block();
+ }
+
+ /**
+ * Permanently deletes the queue.
+ *
+ *
Code Samples
+ *
+ *
Delete a queue
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.delete}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public VoidResponse delete() {
+ return client.delete().block();
+ }
+
+ /**
+ * Retrieves metadata and approximate message count of the queue.
+ *
+ *
Code Samples
+ *
+ *
Get the properties of the queue
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.getProperties}
+ *
+ * @return A response containing a {@link QueueProperties} value which contains the metadata and approximate
+ * messages count of the queue.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Response getProperties() {
+ return client.getProperties().block();
+ }
+
+ /**
+ * Sets the metadata of the queue.
+ *
+ * Passing in a {@code null} value for metadata will clear the metadata associated with the queue.
+ *
+ *
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.clearMetadata#map}
+ *
+ * @param metadata Metadata to set on the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public VoidResponse setMetadata(Map metadata) {
+ return client.setMetadata(metadata).block();
+ }
+
+ /**
+ * Retrieves stored access policies specified on the queue.
+ *
+ *
Code Samples
+ *
+ *
List the stored access policies
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.getAccessPolicy}
+ *
+ * @return The stored access policies specified on the queue.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Iterable getAccessPolicy() {
+ return client.getAccessPolicy().toIterable();
+ }
+
+ /**
+ * Sets stored access policies on the queue.
+ *
+ *
Code Samples
+ *
+ *
Set a read only stored access policy
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.setAccessPolicy}
+ *
+ * @param permissions Access policies to set on the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist, a stored access policy doesn't have all fields filled out,
+ * or the queue will have more than five policies.
+ */
+ public VoidResponse setAccessPolicy(List permissions) {
+ return client.setAccessPolicy(permissions).block();
+ }
+
+ /**
+ * Deletes all messages in the queue.
+ *
+ *
Code Samples
+ *
+ *
Clear the messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.clearMessages}
+ *
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public VoidResponse clearMessages() {
+ return client.clearMessages().block();
+ }
+
+ /**
+ * Enqueues a message that has a time-to-live of 7 days and is instantly visible.
+ *
+ *
Code Samples
+ *
+ *
Enqueue a message of "Hello, Azure"
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.enqueueMessage#string}
+ *
+ * @param messageText Message text
+ * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and
+ * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata
+ * about the enqueued message.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Response enqueueMessage(String messageText) {
+ return enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofDays(7));
+ }
+
+ /**
+ * Enqueues a message with a given time-to-live and a timeout period where the message is invisible in the queue.
+ *
+ *
Code Samples
+ *
+ *
Add a message of "Hello, Azure" that has a timeout of 5 seconds
Add a message of "Goodbye, Azure" that has a time to live of 5 seconds
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration}
+ *
+ * @param messageText Message text
+ * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds.
+ * If unset the value will default to 0 and the message will be instantly visible. The timeout must be between 0
+ * seconds and 7 days.
+ * @param timeToLive Optional. How long the message will stay alive in the queue in seconds. If unset the value will
+ * default to 7 days, if -1 is passed the message will not expire. The time to live must be -1 or any positive number.
+ * @return A {@link EnqueuedMessage} value that contains the {@link EnqueuedMessage#messageId() messageId} and
+ * {@link EnqueuedMessage#popReceipt() popReceipt} that are used to interact with the message and other metadata
+ * about the enqueued message.
+ * @throws StorageErrorException If the queue doesn't exist or the {@code visibilityTimeout} or {@code timeToLive}
+ * are outside of the allowed limits.
+ */
+ public Response enqueueMessage(String messageText, Duration visibilityTimeout, Duration timeToLive) {
+ return client.enqueueMessage(messageText, visibilityTimeout, timeToLive).block();
+ }
+
+ /**
+ * Retrieves the first message in the queue and hides it from other operations for 30 seconds.
+ *
+ *
Code Samples
+ *
+ *
Dequeue a message
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages}
+ *
+ * @return The first {@link DequeuedMessage} in the queue, it contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message, additionally it contains other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Iterable dequeueMessages() {
+ return dequeueMessages(1, Duration.ofSeconds(30));
+ }
+
+ /**
+ * Retrieves up to the maximum number of messages from the queue and hides them from other operations for 30 seconds.
+ *
+ *
Code Samples
+ *
+ *
Dequeue up to 5 messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages#integer}
+ *
+ * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested
+ * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32
+ * messages.
+ * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DequeuedMessage contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message and other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds
+ */
+ public Iterable dequeueMessages(Integer maxMessages) {
+ return dequeueMessages(maxMessages, Duration.ofSeconds(30));
+ }
+
+ /**
+ * Retrieves up to the maximum number of messages from the queue and hides them from other operations for the
+ * timeout period.
+ *
+ *
Code Samples
+ *
+ *
Dequeue up to 5 messages and give them a 60 second timeout period
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.dequeueMessages#integer-duration}
+ *
+ * @param maxMessages Optional. Maximum number of messages to get, if there are less messages exist in the queue than requested
+ * all the messages will be returned. If left empty only 1 message will be retrieved, the allowed range is 1 to 32
+ * messages.
+ * @param visibilityTimeout Optional. The timeout period for how long the message is invisible in the queue in seconds.
+ * If left empty the dequeued messages will be invisible for 30 seconds. The timeout must be between 1 second and 7 days.
+ * @return Up to {@code maxMessages} {@link DequeuedMessage DequeuedMessages} from the queue. Each DeqeuedMessage contains
+ * {@link DequeuedMessage#messageId() messageId} and {@link DequeuedMessage#popReceipt() popReceipt} used to interact
+ * with the message and other metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} or {@code visibilityTimeout} is
+ * outside of the allowed bounds
+ */
+ public Iterable dequeueMessages(Integer maxMessages, Duration visibilityTimeout) {
+ return client.dequeueMessages(maxMessages, visibilityTimeout).toIterable();
+ }
+
+ /**
+ * Peeks the first message in the queue.
+ *
+ * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide
+ * messages from other operations on the queue.
+ *
+ *
Code Samples
+ *
+ *
Peek the first message
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.peekMessages}
+ *
+ * @return A {@link PeekedMessage} that contains metadata about the message.
+ */
+ public Iterable peekMessages() {
+ return peekMessages(null);
+ }
+
+ /**
+ * Peek messages from the front of the queue up to the maximum number of messages.
+ *
+ * Peeked messages don't contain the necessary information needed to interact with the message nor will it hide
+ * messages from other operations on the queue.
+ *
+ *
Code Samples
+ *
+ *
Peek up to the first five messages
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.peekMessages#integer}
+ *
+ * @param maxMessages Optional. Maximum number of messages to peek, if there are less messages exist in the queue than requested
+ * all the messages will be peeked. If left empty only 1 message will be peeked, the allowed range is 1 to 32
+ * messages.
+ * @return Up to {@code maxMessages} {@link PeekedMessage PeekedMessages} from the queue. Each PeekedMessage contains
+ * metadata about the message.
+ * @throws StorageErrorException If the queue doesn't exist or {@code maxMessages} is outside of the allowed bounds
+ */
+ public Iterable peekMessages(Integer maxMessages) {
+ return client.peekMessages(maxMessages).toIterable();
+ }
+
+ /**
+ * Updates the specific message in the queue with a new message and resets the visibility timeout.
+ *
+ *
Code Samples
+ *
+ *
Dequeue the first message and update it to "Hello again, Azure" and hide it for 5 seconds
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.updateMessage}
+ *
+ * @param messageText Updated value for the message
+ * @param messageId Id of the message to update
+ * @param popReceipt Unique identifier that must match for the message to be updated
+ * @param visibilityTimeout The timeout period for how long the message is invisible in the queue in seconds. The
+ * timeout period must be between 1 second and 7 days.
+ * @return A {@link UpdatedMessage} that contains the new {@link UpdatedMessage#popReceipt() popReceipt} to interact
+ * with the message, additionally contains the updated metadata about the message.
+ * @throws StorageErrorException If the queue or messageId don't exist, the popReceipt doesn't match on the message,
+ * or the {@code visibilityTimeout} is outside the allowed bounds
+ */
+ public Response updateMessage(String messageText, String messageId, String popReceipt, Duration visibilityTimeout) {
+ return client.updateMessage(messageText, messageId, popReceipt, visibilityTimeout).block();
+ }
+
+ /**
+ * Deletes the specified message in the queue
+ *
+ *
Code Samples
+ *
+ *
Delete the first message
+ *
+ * {@codesnippet com.azure.storage.queue.queueClient.deleteMessage}
+ *
+ * @param messageId Id of the message to deleted
+ * @param popReceipt Unique identifier that must match for the message to be deleted
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue or messageId don't exist or the popReceipt doesn't match on the message
+ */
+ public VoidResponse deleteMessage(String messageId, String popReceipt) {
+ return client.deleteMessage(messageId, popReceipt).block();
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java
new file mode 100644
index 0000000000000..d272cfc1bbf89
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueClientBuilder.java
@@ -0,0 +1,344 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.policy.AddDatePolicy;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.http.policy.HttpLoggingPolicy;
+import com.azure.core.http.policy.HttpPipelinePolicy;
+import com.azure.core.http.policy.RequestIdPolicy;
+import com.azure.core.http.policy.RetryPolicy;
+import com.azure.core.http.policy.UserAgentPolicy;
+import com.azure.core.implementation.http.policy.spi.HttpPolicyProviders;
+import com.azure.core.implementation.util.ImplUtils;
+import com.azure.core.util.configuration.Configuration;
+import com.azure.core.util.configuration.ConfigurationManager;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.common.policy.SASTokenCredentialPolicy;
+import com.azure.storage.common.policy.SharedKeyCredentialPolicy;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Objects;
+
+/**
+ * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link QueueClient QueueClients}
+ * and {@link QueueAsyncClient QueueAsyncClients}, calling {@link QueueClientBuilder#buildClient() buildClient} constructs an
+ * instance of QueueClient and calling {@link QueueClientBuilder#buildAsyncClient() buildAsyncClient} constructs an instance of
+ * QueueAsyncClient.
+ *
+ *
The client needs the endpoint of the Azure Storage Queue service, name of the queue, and authorization credentials.
+ * {@link QueueClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the
+ * {@link QueueClientBuilder#queueName(String) queueName} and a {@link SASTokenCredential} that authorizes the client.
+ *
+ *
Instantiating a synchronous Queue Client with SAS token
If the {@code endpoint} doesn't contain the queue name or {@code SASTokenCredential} they may be set using
+ * {@link QueueClientBuilder#queueName(String) queueName} and {@link QueueClientBuilder#credential(SASTokenCredential) credential}.
+ *
+ *
Instantiating a synchronous Queue Client with credential
Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential
+ * a connection string from the Storage Queue service must be used. Set the SharedKeyCredential with
+ * {@link QueueClientBuilder#connectionString(String) connectionString}. If the builder has both a SASTokenCredential and
+ * SharedKeyCredential the SharedKeyCredential will be preferred when authorizing requests sent to the service.
+ *
+ *
Instantiating a synchronous Queue Client with connection string.
Instantiating an Asynchronous Queue Client with connection string.
+ * {@codesnippet com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring}
+ *
+ * @see QueueClient
+ * @see QueueAsyncClient
+ * @see SASTokenCredential
+ * @see SharedKeyCredential
+ */
+public final class QueueClientBuilder {
+ private static final ClientLogger LOGGER = new ClientLogger(QueueClientBuilder.class);
+ private static final String ACCOUNT_NAME = "accountname";
+ private final List policies;
+
+ private URL endpoint;
+ private String queueName;
+ private SASTokenCredential sasTokenCredential;
+ private SharedKeyCredential sharedKeyCredential;
+ private HttpClient httpClient;
+ private HttpPipeline pipeline;
+ private HttpLogDetailLevel logLevel;
+ private RetryPolicy retryPolicy;
+ private Configuration configuration;
+
+ /**
+ * Creates a builder instance that is able to configure and construct {@link QueueClient QueueClients}
+ * and {@link QueueAsyncClient QueueAsyncClients}.
+ */
+ public QueueClientBuilder() {
+ retryPolicy = new RetryPolicy();
+ logLevel = HttpLogDetailLevel.NONE;
+ policies = new ArrayList<>();
+
+ configuration = ConfigurationManager.getConfiguration();
+ }
+
+ /**
+ * Creates a {@link QueueClient} based on options set in the builder. Every time {@code buildClient()} is
+ * called a new instance of {@link QueueClient} is created.
+ *
+ *
+ * If {@link QueueClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline},
+ * {@link QueueClientBuilder#endpoint(String) endpoint}, and
+ * {@link QueueClientBuilder#queueName(String) queueName} are used to create the {@link QueueAsyncClient client}.
+ * All other builder settings are ignored.
+ *
+ *
+ * @return A QueueClient with the options set from the builder.
+ * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set.
+ * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set.
+ */
+ public QueueClient buildClient() {
+ return new QueueClient(buildAsyncClient());
+ }
+
+ /**
+ * Creates a {@link QueueAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is
+ * called a new instance of {@link QueueAsyncClient} is created.
+ *
+ *
+ * If {@link QueueClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline},
+ * {@link QueueClientBuilder#endpoint(String) endpoint}, and
+ * {@link QueueClientBuilder#queueName(String) queueName} are used to create the {@link QueueAsyncClient client}.
+ * All other builder settings are ignored.
+ *
+ *
+ * @return A QueueAsyncClient with the options set from the builder.
+ * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set.
+ * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set.
+ */
+ public QueueAsyncClient buildAsyncClient() {
+ Objects.requireNonNull(endpoint);
+ Objects.requireNonNull(queueName);
+
+ if (sasTokenCredential == null && sharedKeyCredential == null) {
+ LOGGER.asError().log("Credentials are required for authorization");
+ throw new IllegalArgumentException("Credentials are required for authorization");
+ }
+
+ if (pipeline != null) {
+ return new QueueAsyncClient(endpoint, pipeline, queueName);
+ }
+ // Closest to API goes first, closest to wire goes last.
+ final List policies = new ArrayList<>();
+
+ policies.add(new UserAgentPolicy(QueueConfiguration.NAME, QueueConfiguration.VERSION, configuration));
+ policies.add(new RequestIdPolicy());
+ policies.add(new AddDatePolicy());
+
+ if (sharedKeyCredential != null) {
+ policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential));
+ } else {
+ policies.add(new SASTokenCredentialPolicy(sasTokenCredential));
+ }
+
+ HttpPolicyProviders.addBeforeRetryPolicies(policies);
+
+ policies.add(retryPolicy);
+
+ policies.addAll(this.policies);
+ HttpPolicyProviders.addAfterRetryPolicies(policies);
+ policies.add(new HttpLoggingPolicy(logLevel));
+
+ HttpPipeline pipeline = HttpPipeline.builder()
+ .policies(policies.toArray(new HttpPipelinePolicy[0]))
+ .httpClient(httpClient)
+ .build();
+
+ return new QueueAsyncClient(endpoint, pipeline, queueName);
+ }
+
+ /**
+ * Sets the endpoint for the Azure Storage Queue instance that the client will interact with.
+ *
+ *
The first path segment, if the endpoint contains path segments, will be assumed to be the name of the queue
+ * that the client will interact with.
+ *
+ *
Query parameters of the endpoint will be parsed using {@link SASTokenCredential#fromQuery(String) fromQuery} in an
+ * attempt to generate a {@link SASTokenCredential} to authenticate requests sent to the service.
+ *
+ * @param endpoint The URL of the Azure Storage Queue instance to send service requests to and receive responses from.
+ * @return the updated QueueClientBuilder object
+ * @throws IllegalArgumentException If {@code endpoint} isn't a proper URL
+ */
+ public QueueClientBuilder endpoint(String endpoint) {
+ Objects.requireNonNull(endpoint);
+ try {
+ URL fullURL = new URL(endpoint);
+ this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost());
+
+ // Attempt to get the queue name from the URL passed
+ String[] pathSegments = fullURL.getPath().split("/", 2);
+ if (pathSegments.length == 2 && !ImplUtils.isNullOrEmpty(pathSegments[1])) {
+ this.queueName = pathSegments[1];
+ }
+
+ // Attempt to get the SAS token from the URL passed
+ SASTokenCredential credential = SASTokenCredential.fromQuery(fullURL.getQuery());
+ if (credential != null) {
+ this.sasTokenCredential = credential;
+ }
+ } catch (MalformedURLException ex) {
+ LOGGER.asError().log("The Azure Storage Queue endpoint url is malformed. Endpoint: " + endpoint);
+ throw new IllegalArgumentException("The Azure Storage Queue endpoint url is malformed. Endpoint: " + endpoint);
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the name of the queue that the client will interact with.
+ *
+ * @param queueName Name of the queue
+ * @return the updated QueueClientBuilder object
+ * @throws NullPointerException If {@code queueName} is {@code null}.
+ */
+ public QueueClientBuilder queueName(String queueName) {
+ this.queueName = Objects.requireNonNull(queueName);
+ return this;
+ }
+
+ /**
+ * Sets the {@link SASTokenCredential} used to authenticate requests sent to the Queue.
+ *
+ * @param credential SAS token credential generated from the Storage account that authorizes requests
+ * @return the updated QueueClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}.
+ */
+ public QueueClientBuilder credential(SASTokenCredential credential) {
+ this.sasTokenCredential = Objects.requireNonNull(credential);
+ return this;
+ }
+
+ /**
+ * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the Queue.
+ *
+ * @param credential Shared key credential can retrieve from the Storage account that authorizes requests
+ * @return the updated QueueServiceClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}.
+ */
+ public QueueClientBuilder credential(SharedKeyCredential credential) {
+ this.sharedKeyCredential = Objects.requireNonNull(credential);
+ return this;
+ }
+
+ /**
+ * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the
+ * Queue service.
+ *
+ * @param connectionString Connection string from the Access Keys section in the Storage account
+ * @return the updated QueueClientBuilder object
+ * @throws NullPointerException If {@code connectionString} is {@code null}.
+ */
+ public QueueClientBuilder connectionString(String connectionString) {
+ Objects.requireNonNull(connectionString);
+ this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString);
+ getEndPointFromConnectionString(connectionString);
+ return this;
+ }
+
+ private void getEndPointFromConnectionString(String connectionString) {
+ HashMap connectionStringPieces = new HashMap<>();
+ for (String connectionStringPiece : connectionString.split(";")) {
+ String[] kvp = connectionStringPiece.split("=", 2);
+ connectionStringPieces.put(kvp[0].toLowerCase(Locale.ROOT), kvp[1]);
+ }
+ String accountName = connectionStringPieces.get(ACCOUNT_NAME);
+ try {
+ this.endpoint = new URL(String.format("https://%s.queue.core.windows.net", accountName));
+ } catch (MalformedURLException e) {
+ LOGGER.asError().log("There is no valid account for the connection string. "
+ + "Connection String: %s", connectionString);
+ throw new IllegalArgumentException(String.format("There is no valid account for the connection string. "
+ + "Connection String: %s", connectionString));
+ }
+ }
+ /**
+ * Sets the HTTP client to use for sending and receiving requests to and from the service.
+ *
+ * @param httpClient The HTTP client to use for requests.
+ * @return The updated QueueClientBuilder object.
+ * @throws NullPointerException If {@code httpClient} is {@code null}.
+ */
+ public QueueClientBuilder httpClient(HttpClient httpClient) {
+ this.httpClient = Objects.requireNonNull(httpClient);
+ return this;
+ }
+
+ /**
+ * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}.
+ *
+ * @param pipelinePolicy The retry policy for service requests.
+ * @return The updated QueueClientBuilder object.
+ * @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
+ */
+ public QueueClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
+ Objects.requireNonNull(pipelinePolicy);
+ this.policies.add(pipelinePolicy);
+ return this;
+ }
+
+ /**
+ * Sets the logging level for HTTP requests and responses.
+ *
+ * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses.
+ * @return The updated QueueClientBuilder object.
+ */
+ public QueueClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) {
+ this.logLevel = logLevel;
+ return this;
+ }
+
+ /**
+ * Sets the HTTP pipeline to use for the service client.
+ *
+ * If {@code pipeline} is set, all other settings are ignored, aside from {@link QueueClientBuilder#endpoint(String) endpoint}
+ * and {@link QueueClientBuilder#queueName(String) queueName} when building clients.
+ *
+ * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses.
+ * @return The updated QueueClientBuilder object.
+ * @throws NullPointerException If {@code pipeline} is {@code null}.
+ */
+ public QueueClientBuilder pipeline(HttpPipeline pipeline) {
+ Objects.requireNonNull(pipeline);
+ this.pipeline = pipeline;
+ return this;
+ }
+
+ /**
+ * Sets the configuration store that is used during construction of the service client.
+ *
+ * The default configuration store is a clone of the {@link ConfigurationManager#getConfiguration() global
+ * configuration store}, use {@link Configuration#NONE} to bypass using configuration settings during construction.
+ *
+ * @param configuration The configuration store used to
+ * @return The updated QueueClientBuilder object.
+ */
+ public QueueClientBuilder configuration(Configuration configuration) {
+ this.configuration = configuration;
+ return this;
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java
new file mode 100644
index 0000000000000..7a794525484f7
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueConfiguration.java
@@ -0,0 +1,12 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+/*
+ * Gets the SDK information for this library component.
+ */
+class QueueConfiguration {
+ //TODO: Eventually remove these hardcoded strings with https://github.com/Azure/azure-sdk-for-java/issues/3141
+ static final String NAME = "azure-storage-queue";
+ static final String VERSION = "12.0.0-preview.1";
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java
new file mode 100644
index 0000000000000..e093f1d34b171
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceAsyncClient.java
@@ -0,0 +1,301 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.SimpleResponse;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.core.util.Context;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.queue.implementation.AzureQueueStorageBuilder;
+import com.azure.storage.queue.implementation.AzureQueueStorageImpl;
+import com.azure.storage.queue.models.CorsRule;
+import com.azure.storage.queue.models.ListQueuesIncludeType;
+import com.azure.storage.queue.models.ListQueuesSegmentResponse;
+import com.azure.storage.queue.models.QueueItem;
+import com.azure.storage.queue.models.QueuesSegmentOptions;
+import com.azure.storage.queue.models.ServicesListQueuesSegmentResponse;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.StorageServiceProperties;
+import com.azure.storage.queue.models.StorageServiceStats;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import reactor.core.publisher.Flux;
+import reactor.core.publisher.Mono;
+
+/**
+ * This class provides a client that contains all the operations for interacting with a queue account in Azure Storage.
+ * Operations allowed by the client are creating, listing, and deleting queues, retrieving and updating properties of the account,
+ * and retrieving statistics of the account.
+ *
+ *
Instantiating an Asynchronous Queue Service Client
View {@link QueueServiceClientBuilder this} for additional ways to construct the client.
+ *
+ * @see QueueServiceClientBuilder
+ * @see QueueServiceClient
+ * @see SharedKeyCredential
+ * @see SASTokenCredential
+ */
+public final class QueueServiceAsyncClient {
+ private static final ClientLogger LOGGER = new ClientLogger(QueueServiceAsyncClient.class);
+ private final AzureQueueStorageImpl client;
+
+ /**
+ * Creates a QueueServiceAsyncClient that sends requests to the storage account at {@code endpoint}.
+ * Each service call goes through the {@code httpPipeline}.
+ *
+ * @param endpoint URL for the Storage Queue service
+ * @param httpPipeline HttpPipeline that the HTTP requests and response flow through
+ */
+ QueueServiceAsyncClient(URL endpoint, HttpPipeline httpPipeline) {
+ this.client = new AzureQueueStorageBuilder().pipeline(httpPipeline)
+ .url(endpoint.toString())
+ .build();
+ }
+
+ /**
+ * @return the URL of the storage queue
+ * @throws RuntimeException If the queue service is using a malformed URL.
+ */
+ public URL getQueueServiceUrl() {
+ try {
+ return new URL(client.url());
+ } catch (MalformedURLException ex) {
+ LOGGER.asError().log("Queue Service URL is malformed");
+ throw new RuntimeException("Storage account URL is malformed");
+ }
+ }
+
+ /**
+ * Constructs a QueueAsyncClient that interacts with the specified queue.
+ *
+ * This will not create the queue in the storage account if it doesn't exist.
+ *
+ * @param queueName Name of the queue
+ * @return QueueAsyncClient that interacts with the specified queue
+ */
+ public QueueAsyncClient getQueueAsyncClient(String queueName) {
+ return new QueueAsyncClient(client, queueName);
+ }
+
+ /**
+ * Creates a queue in the storage account with the specified name and returns a QueueAsyncClient to interact
+ * with it.
+ *
+ *
Code Samples
+ *
+ *
Create the queue "test"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.createQueue#string}
+ *
+ * @param queueName Name of the queue
+ * @return A response containing the QueueAsyncClient and the status of creating the queue
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists
+ */
+ public Mono> createQueue(String queueName) {
+ return createQueue(queueName, null);
+ }
+
+ /**
+ * Creates a queue in the storage account with the specified name and metadata and returns a QueueAsyncClient to
+ * interact with it.
+ *
+ *
Code Samples
+ *
+ *
Create the queue "test" with metadata "queue:metadata"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map}
+ *
+ * @param queueName Name of the queue
+ * @param metadata Metadata to associate with the queue
+ * @return A response containing the QueueAsyncClient and the status of creating the queue
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists
+ */
+ public Mono> createQueue(String queueName, Map metadata) {
+ QueueAsyncClient queueAsyncClient = new QueueAsyncClient(client, queueName);
+
+ return queueAsyncClient.create(metadata)
+ .map(response -> new SimpleResponse<>(response, queueAsyncClient));
+ }
+
+ /**
+ * Deletes a queue in the storage account
+ *
+ *
Code Samples
+ *
+ *
Delete the queue "test"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string}
+ *
+ * @param queueName Name of the queue
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public Mono deleteQueue(String queueName) {
+ return new QueueAsyncClient(client, queueName).delete();
+ }
+
+ /**
+ * Lists all queues in the storage account without their metadata.
+ *
+ *
Code Samples
+ *
+ *
List all queues in the account
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.listQueues}
+ *
+ * @return {@link QueueItem Queues} in the storage account
+ */
+ public Flux listQueues() {
+ return listQueues(null, null);
+ }
+
+ /**
+ * Lists the queues in the storage account that pass the filter.
+ *
+ * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for
+ * the queues.
+ *
+ *
Code Samples
+ *
+ *
List all queues that begin with "azure"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions}
+ *
+ * @param options Options for listing queues
+ * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements
+ */
+ public Flux listQueues(QueuesSegmentOptions options) {
+ return listQueues(null, options);
+ }
+
+ /**
+ * Lists the queues in the storage account that pass the filter starting at the specified marker.
+ *
+ * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for
+ * the queues.
+ *
+ * @param marker Starting point to list the queues
+ * @param options Options for listing queues
+ * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements
+ */
+ Flux listQueues(String marker, QueuesSegmentOptions options) {
+ String prefix = null;
+ Integer maxResults = null;
+ final List include = new ArrayList<>();
+
+ if (options != null) {
+ prefix = options.prefix();
+ maxResults = options.maxResults();
+ if (options.includeMetadata()) {
+ include.add(ListQueuesIncludeType.fromString(ListQueuesIncludeType.METADATA.toString()));
+ }
+ }
+
+ Mono result = client.services()
+ .listQueuesSegmentWithRestResponseAsync(prefix, marker, maxResults, include, null, null, Context.NONE);
+
+ return result.flatMapMany(response -> extractAndFetchQueues(response, include, Context.NONE));
+ }
+
+ /*
+ * Helper function used to auto-enumerate through paged responses
+ */
+ private Flux listQueues(ServicesListQueuesSegmentResponse response, List include, Context context) {
+ ListQueuesSegmentResponse value = response.value();
+ Mono result = client.services()
+ .listQueuesSegmentWithRestResponseAsync(value.prefix(), value.marker(), value.maxResults(), include, null, null, context);
+
+ return result.flatMapMany(r -> extractAndFetchQueues(r, include, context));
+ }
+
+ /*
+ * Helper function used to auto-enumerate though paged responses
+ */
+ private Flux extractAndFetchQueues(ServicesListQueuesSegmentResponse response, List include, Context context) {
+ String nextPageLink = response.value().nextMarker();
+ if (nextPageLink == null) {
+ return Flux.fromIterable(response.value().queueItems());
+ }
+
+ return Flux.fromIterable(response.value().queueItems()).concatWith(listQueues(response, include, context));
+ }
+
+ /**
+ * Retrieves the properties of the storage account's Queue service. The properties range from storage analytics and
+ * metric to CORS (Cross-Origin Resource Sharing).
+ *
+ *
Code Samples
+ *
+ *
Retrieve Queue service properties
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.getProperties}
+ *
+ * @return Storage account Queue service properties
+ */
+ public Mono> getProperties() {
+ return client.services().getPropertiesWithRestResponseAsync(Context.NONE)
+ .map(response -> new SimpleResponse<>(response, response.value()));
+ }
+
+ /**
+ * Sets the properties for the storage account's Queue service. The properties range from storage analytics and
+ * metric to CORS (Cross-Origin Resource Sharing).
+ *
+ * To maintain the CORS in the Queue service pass a {@code null} value for {@link StorageServiceProperties#cors() CORS}.
+ * To disable all CORS in the Queue service pass an empty list for {@link StorageServiceProperties#cors() CORS}.
+ *
+ *
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties}
+ *
+ * @param properties Storage account Queue service properties
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException When one of the following is true
+ *
+ *
A CORS rule is missing one of its fields
+ *
More than five CORS rules will exist for the Queue service
{@link CorsRule#allowedMethods() Allowed methods} isn't DELETE, GET, HEAD, MERGE, POST, OPTIONS, or PUT
+ *
+ */
+ public Mono setProperties(StorageServiceProperties properties) {
+ return client.services().setPropertiesWithRestResponseAsync(properties, Context.NONE)
+ .map(VoidResponse::new);
+ }
+
+ /**
+ * Retrieves the geo replication information about the Queue service.
+ *
+ *
Code Samples
+ *
+ *
Retrieve the geo replication information
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.getStatistics}
+ *
+ * @return The geo replication information about the Queue service
+ */
+ public Mono> getStatistics() {
+ return client.services().getStatisticsWithRestResponseAsync(Context.NONE)
+ .map(response -> new SimpleResponse<>(response, response.value()));
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java
new file mode 100644
index 0000000000000..a002e5b12f872
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClient.java
@@ -0,0 +1,234 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.SimpleResponse;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.queue.models.CorsRule;
+import com.azure.storage.queue.models.QueueItem;
+import com.azure.storage.queue.models.QueuesSegmentOptions;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.StorageServiceProperties;
+import com.azure.storage.queue.models.StorageServiceStats;
+import java.net.URL;
+import java.util.Map;
+
+/**
+ * This class provides a client that contains all the operations for interacting with a queue account in Azure Storage.
+ * Operations allowed by the client are creating, listing, and deleting queues, retrieving and updating properties of the account,
+ * and retrieving statistics of the account.
+ *
+ *
View {@link QueueServiceClientBuilder this} for additional ways to construct the client.
+ *
+ * @see QueueServiceClientBuilder
+ * @see QueueServiceAsyncClient
+ * @see SharedKeyCredential
+ * @see SASTokenCredential
+ */
+public final class QueueServiceClient {
+ private final QueueServiceAsyncClient client;
+
+ /**
+ * Creates a QueueServiceClient that wraps a QueueServiceAsyncClient and blocks requests.
+ *
+ * @param client QueueServiceAsyncClient that is used to send requests
+ */
+ QueueServiceClient(QueueServiceAsyncClient client) {
+ this.client = client;
+ }
+
+ /**
+ * @return the URL of the storage queue
+ */
+ public URL getQueueServiceUrl() {
+ return client.getQueueServiceUrl();
+ }
+
+ /**
+ * Constructs a QueueClient that interacts with the specified queue.
+ *
+ * This will not create the queue in the storage account if it doesn't exist.
+ *
+ * @param queueName Name of the queue
+ * @return QueueClient that interacts with the specified queue
+ */
+ public QueueClient getQueueClient(String queueName) {
+ return new QueueClient(client.getQueueAsyncClient(queueName));
+ }
+
+ /**
+ * Creates a queue in the storage account with the specified name and returns a QueueClient to interact with it.
+ *
+ *
Code Samples
+ *
+ *
Create the queue "test"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.createQueue#string}
+ *
+ * @param queueName Name of the queue
+ * @return A response containing the QueueClient and the status of creating the queue
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists
+ */
+ public Response createQueue(String queueName) {
+ return createQueue(queueName, null);
+ }
+
+ /**
+ * Creates a queue in the storage account with the specified name and metadata and returns a QueueClient to
+ * interact with it.
+ *
+ *
Code Samples
+ *
+ *
Create the queue "test" with metadata "queue:metadata"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.createQueue#string-map}
+ *
+ * @param queueName Name of the queue
+ * @param metadata Metadata to associate with the queue
+ * @return A response containing the QueueClient and the status of creating the queue
+ * @throws StorageErrorException If a queue with the same name and different metadata already exists
+ */
+ public Response createQueue(String queueName, Map metadata) {
+ Response response = client.createQueue(queueName, metadata).block();
+
+ return new SimpleResponse<>(response, new QueueClient(response.value()));
+ }
+
+ /**
+ * Deletes a queue in the storage account
+ *
+ *
Code Samples
+ *
+ *
Delete the queue "test"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.deleteQueue#string}
+ *
+ * @param queueName Name of the queue
+ * @return A response containing the status of deleting the queue
+ * @throws StorageErrorException If the queue doesn't exist
+ */
+ public VoidResponse deleteQueue(String queueName) {
+ return client.deleteQueue(queueName).block();
+ }
+
+ /**
+ * Lists all queues in the storage account without their metadata.
+ *
+ *
Code Samples
+ *
+ *
List all queues in the account
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues}
+ *
+ * @return {@link QueueItem Queues} in the storage account
+ */
+ public Iterable listQueues() {
+ return listQueues(null, null);
+ }
+
+ /**
+ * Lists the queues in the storage account that pass the filter.
+ *
+ * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for
+ * the queues.
+ *
+ *
Code Samples
+ *
+ *
List all queues that begin with "azure"
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions}
+ *
+ * @param options Options for listing queues
+ * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements
+ */
+ public Iterable listQueues(QueuesSegmentOptions options) {
+ return listQueues(null, options);
+ }
+
+ /**
+ * Lists the queues in the storage account that pass the filter starting at the specified marker.
+ *
+ * Pass true to {@link QueuesSegmentOptions#includeMetadata(boolean) includeMetadata} to have metadata returned for
+ * the queues.
+ *
+ * @param marker Starting point to list the queues
+ * @param options Options for listing queues
+ * @return {@link QueueItem Queues} in the storage account that satisfy the filter requirements
+ */
+ Iterable listQueues(String marker, QueuesSegmentOptions options) {
+ return client.listQueues(marker, options).toIterable();
+ }
+
+ /**
+ * Retrieves the properties of the storage account's Queue service. The properties range from storage analytics and
+ * metric to CORS (Cross-Origin Resource Sharing).
+ *
+ *
Code Samples
+ *
+ *
Retrieve Queue service properties
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.getProperties}
+ *
+ * @return Storage account Queue service properties
+ */
+ public Response getProperties() {
+ return client.getProperties().block();
+ }
+
+ /**
+ * Sets the properties for the storage account's Queue service. The properties range from storage analytics and
+ * metric to CORS (Cross-Origin Resource Sharing).
+ *
+ * To maintain the CORS in the Queue service pass a {@code null} value for {@link StorageServiceProperties#cors() CORS}.
+ * To disable all CORS in the Queue service pass an empty list for {@link StorageServiceProperties#cors() CORS}.
+ *
+ *
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties}
+ *
+ * @param properties Storage account Queue service properties
+ * @return A response that only contains headers and response status code
+ * @throws StorageErrorException When one of the following is true
+ *
+ *
A CORS rule is missing one of its fields
+ *
More than five CORS rules will exist for the Queue service
{@link CorsRule#allowedMethods() Allowed methods} isn't DELETE, GET, HEAD, MERGE, POST, OPTIONS, or PUT
+ *
+ */
+ public VoidResponse setProperties(StorageServiceProperties properties) {
+ return client.setProperties(properties).block();
+ }
+
+ /**
+ * Retrieves the geo replication information about the Queue service.
+ *
+ *
Code Samples
+ *
+ *
Retrieve the geo replication information
+ *
+ * {@codesnippet com.azure.storage.queue.queueServiceClient.getStatistics}
+ *
+ * @return The geo replication information about the Queue service
+ */
+ public Response getStatistics() {
+ return client.getStatistics().block();
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java
new file mode 100644
index 0000000000000..63b191256f5dd
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/QueueServiceClientBuilder.java
@@ -0,0 +1,301 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.HttpPipeline;
+import com.azure.core.http.policy.AddDatePolicy;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.http.policy.HttpLoggingPolicy;
+import com.azure.core.http.policy.HttpPipelinePolicy;
+import com.azure.core.http.policy.RequestIdPolicy;
+import com.azure.core.http.policy.RetryPolicy;
+import com.azure.core.http.policy.UserAgentPolicy;
+import com.azure.core.implementation.http.policy.spi.HttpPolicyProviders;
+import com.azure.core.util.configuration.Configuration;
+import com.azure.core.util.configuration.ConfigurationManager;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.common.policy.SASTokenCredentialPolicy;
+import com.azure.storage.common.policy.SharedKeyCredentialPolicy;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * This class provides a fluent builder API to help aid the configuration and instantiation of the {@link QueueServiceClient queueServiceClients}
+ * and {@link QueueServiceAsyncClient queueServiceAsyncClients}, calling {@link QueueServiceClientBuilder#buildClient() buildClient}
+ * constructs an instance of QueueServiceClient and calling {@link QueueServiceClientBuilder#buildAsyncClient() buildAsyncClient}
+ * constructs an instance of QueueServiceAsyncClient.
+ *
+ *
The client needs the endpoint of the Azure Storage Queue service, name of the share, and authorization credential.
+ * {@link QueueServiceClientBuilder#endpoint(String) endpoint} gives the builder the endpoint and may give the builder the
+ * A {@link SASTokenCredential} that authorizes the client.
+ *
+ *
Instantiating a synchronous Queue Service Client with SAS token
If the {@code endpoint} doesn't contain {@code SASTokenCredential} they may be set using
+ * {@link QueueClientBuilder#credential(SASTokenCredential) credential}.
+ *
+ *
Instantiating a synchronous Queue Service Client with SAS token
If the {@code endpoint} doesn't contain the query parameters to construct a {@code SASTokenCredential} they may
+ * be set using {@link QueueServiceClientBuilder#credential(SASTokenCredential) credential}.
+ *
+ *
Another way to authenticate the client is using a {@link SharedKeyCredential}. To create a SharedKeyCredential
+ * a connection string from the Storage Queue service must be used. Set the SharedKeyCredential with
+ * {@link QueueServiceClientBuilder#connectionString(String) connectionString}. If the builder has both a SASTokenCredential and
+ * SharedKeyCredential the SharedKeyCredential will be preferred when authorizing requests sent to the service.
+ *
+ *
Instantiating a synchronous Queue Service Client with connection string.
Instantiating an Asynchronous Queue Service Client with connection string.
+ * {@codesnippet com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring}
+ *
+ * @see QueueServiceClient
+ * @see QueueServiceAsyncClient
+ * @see SASTokenCredential
+ * @see SharedKeyCredential
+ */
+public final class QueueServiceClientBuilder {
+ private static final ClientLogger LOGGER = new ClientLogger(QueueServiceClientBuilder.class);
+ private final List policies;
+
+ private URL endpoint;
+ private SASTokenCredential sasTokenCredential;
+ private SharedKeyCredential sharedKeyCredential;
+ private HttpClient httpClient;
+ private HttpPipeline pipeline;
+ private HttpLogDetailLevel logLevel;
+ private RetryPolicy retryPolicy;
+ private Configuration configuration;
+
+ /**
+ * Creates a builder instance that is able to configure and construct {@link QueueServiceClient QueueServiceClients}
+ * and {@link QueueServiceAsyncClient QueueServiceAsyncClients}.
+ */
+ public QueueServiceClientBuilder() {
+ retryPolicy = new RetryPolicy();
+ logLevel = HttpLogDetailLevel.NONE;
+ policies = new ArrayList<>();
+ configuration = ConfigurationManager.getConfiguration();
+ }
+
+ /**
+ * Creates a {@link QueueServiceAsyncClient} based on options set in the builder. Every time {@code buildAsyncClient()} is
+ * called a new instance of {@link QueueServiceAsyncClient} is created.
+ *
+ *
+ * If {@link QueueServiceClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and
+ * {@link QueueServiceClientBuilder#endpoint(String) endpoint} are used to create the
+ * {@link QueueServiceAsyncClient client}. All other builder settings are ignored.
+ *
+ *
+ * @return A QueueServiceAsyncClient with the options set from the builder.
+ * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set.
+ * @throws IllegalArgumentException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set.
+ */
+ public QueueServiceAsyncClient buildAsyncClient() {
+ Objects.requireNonNull(endpoint);
+
+ if (sasTokenCredential == null && sharedKeyCredential == null) {
+ LOGGER.asError().log("Credentials are required for authorization");
+ throw new IllegalArgumentException("Credentials are required for authorization");
+ }
+
+ if (pipeline != null) {
+ return new QueueServiceAsyncClient(endpoint, pipeline);
+ }
+ // Closest to API goes first, closest to wire goes last.
+ final List policies = new ArrayList<>();
+
+ policies.add(new UserAgentPolicy(QueueConfiguration.NAME, QueueConfiguration.VERSION, configuration));
+ policies.add(new RequestIdPolicy());
+ policies.add(new AddDatePolicy());
+
+ if (sharedKeyCredential != null) {
+ policies.add(new SharedKeyCredentialPolicy(sharedKeyCredential));
+ } else {
+ policies.add(new SASTokenCredentialPolicy(sasTokenCredential));
+ }
+
+ HttpPolicyProviders.addBeforeRetryPolicies(policies);
+
+ policies.add(retryPolicy);
+
+ policies.addAll(this.policies);
+ HttpPolicyProviders.addAfterRetryPolicies(policies);
+ policies.add(new HttpLoggingPolicy(logLevel));
+
+ HttpPipeline pipeline = HttpPipeline.builder()
+ .policies(policies.toArray(new HttpPipelinePolicy[0]))
+ .httpClient(httpClient)
+ .build();
+
+ return new QueueServiceAsyncClient(endpoint, pipeline);
+ }
+
+ /**
+ * Creates a {@link QueueServiceClient} based on options set in the builder. Every time {@code buildClient()} is
+ * called a new instance of {@link QueueServiceClient} is created.
+ *
+ *
+ * If {@link QueueServiceClientBuilder#pipeline(HttpPipeline) pipeline} is set, then the {@code pipeline} and
+ * {@link QueueServiceClientBuilder#endpoint(String) endpoint} are used to create the
+ * {@link QueueServiceClient client}. All other builder settings are ignored.
+ *
+ *
+ * @return A QueueServiceClient with the options set from the builder.
+ * @throws NullPointerException If {@code endpoint} or {@code queueName} have not been set.
+ * @throws IllegalStateException If neither a {@link SharedKeyCredential} or {@link SASTokenCredential} has been set.
+ */
+ public QueueServiceClient buildClient() {
+ return new QueueServiceClient(buildAsyncClient());
+ }
+
+
+ /**
+ * Sets the endpoint for the Azure Storage Queue instance that the client will interact with.
+ *
+ *
Query parameters of the endpoint will be parsed using {@link SASTokenCredential#fromQuery(String) fromQuery} in an
+ * attempt to generate a {@link SASTokenCredential} to authenticate requests sent to the service.
+ *
+ * @param endpoint The URL of the Azure Storage Queue instance to send service requests to and receive responses from.
+ * @return the updated QueueServiceClientBuilder object
+ * @throws IllegalArgumentException If {@code endpoint} isn't a proper URL
+ */
+ public QueueServiceClientBuilder endpoint(String endpoint) {
+ Objects.requireNonNull(endpoint);
+ try {
+ URL fullURL = new URL(endpoint);
+ this.endpoint = new URL(fullURL.getProtocol() + "://" + fullURL.getHost());
+
+ // Attempt to get the SAS token from the URL passed
+ SASTokenCredential credential = SASTokenCredential.fromQuery(fullURL.getQuery());
+ if (credential != null) {
+ this.sasTokenCredential = credential;
+ }
+ } catch (MalformedURLException ex) {
+ LOGGER.asError().log("The Azure Storage Queue endpoint url is malformed.");
+ throw new IllegalArgumentException("The Azure Storage Queue endpoint url is malformed.");
+ }
+
+ return this;
+ }
+
+ /**
+ * Sets the {@link SASTokenCredential} used to authenticate requests sent to the Queue service.
+ *
+ * @param credential SAS token credential generated from the Storage account that authorizes requests
+ * @return the updated QueueServiceClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}.
+ */
+ public QueueServiceClientBuilder credential(SASTokenCredential credential) {
+ this.sasTokenCredential = Objects.requireNonNull(credential);
+ return this;
+ }
+
+ /**
+ * Sets the {@link SharedKeyCredential} used to authenticate requests sent to the Queue service.
+ *
+ * @param credential Shared key credential can retrieve from the Storage account that authorizes requests
+ * @return the updated QueueServiceClientBuilder object
+ * @throws NullPointerException If {@code credential} is {@code null}.
+ */
+ public QueueServiceClientBuilder credential(SharedKeyCredential credential) {
+ this.sharedKeyCredential = Objects.requireNonNull(credential);
+ return this;
+ }
+
+
+ /**
+ * Creates a {@link SharedKeyCredential} from the {@code connectionString} used to authenticate requests sent to the
+ * Queue service.
+ *
+ * @param connectionString Connection string from the Access Keys section in the Storage account
+ * @return the updated QueueServiceClientBuilder object
+ * @throws NullPointerException If {@code connectionString} is {@code null}.
+ */
+ public QueueServiceClientBuilder connectionString(String connectionString) {
+ Objects.requireNonNull(connectionString);
+ this.sharedKeyCredential = SharedKeyCredential.fromConnectionString(connectionString);
+ return this;
+ }
+
+ /**
+ * Sets the HTTP client to use for sending and receiving requests to and from the service.
+ *
+ * @param httpClient The HTTP client to use for requests.
+ * @return The updated QueueServiceClientBuilder object.
+ * @throws NullPointerException If {@code httpClient} is {@code null}.
+ */
+ public QueueServiceClientBuilder httpClient(HttpClient httpClient) {
+ this.httpClient = httpClient;
+ return this;
+ }
+
+ /**
+ * Adds a policy to the set of existing policies that are executed after the {@link RetryPolicy}.
+ *
+ * @param pipelinePolicy The retry policy for service requests.
+ * @return The updated QueueServiceClientBuilder object.
+ * @throws NullPointerException If {@code pipelinePolicy} is {@code null}.
+ */
+ public QueueServiceClientBuilder addPolicy(HttpPipelinePolicy pipelinePolicy) {
+ this.policies.add(pipelinePolicy);
+ return this;
+ }
+
+ /**
+ * Sets the logging level for HTTP requests and responses.
+ *
+ * @param logLevel The amount of logging output when sending and receiving HTTP requests/responses.
+ * @return The updated QueueServiceClientBuilder object.
+ */
+ public QueueServiceClientBuilder httpLogDetailLevel(HttpLogDetailLevel logLevel) {
+ this.logLevel = logLevel;
+ return this;
+ }
+
+ /**
+ * Sets the HTTP pipeline to use for the service client.
+ *
+ * If {@code pipeline} is set, all other settings are ignored, aside from {@link QueueServiceClientBuilder#endpoint(String) endpoint}
+ * when building clients.
+ *
+ * @param pipeline The HTTP pipeline to use for sending service requests and receiving responses.
+ * @return The updated QueueServiceClientBuilder object.
+ * @throws NullPointerException If {@code pipeline} is {@code null}.
+ */
+ public QueueServiceClientBuilder pipeline(HttpPipeline pipeline) {
+ Objects.requireNonNull(pipeline);
+ this.pipeline = pipeline;
+ return this;
+ }
+
+ /**
+ * Sets the configuration store that is used during construction of the service client.
+ *
+ * The default configuration store is a clone of the {@link ConfigurationManager#getConfiguration() global
+ * configuration store}, use {@link Configuration#NONE} to bypass using configuration settings during construction.
+ *
+ * @param configuration The configuration store used to
+ * @return The updated QueueServiceClientBuilder object.
+ */
+ public QueueServiceClientBuilder configuration(Configuration configuration) {
+ this.configuration = configuration;
+ return this;
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/README.md b/storage/client/queue/src/main/java/com/azure/storage/queue/README.md
new file mode 100644
index 0000000000000..86ffe940daf0c
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/README.md
@@ -0,0 +1,377 @@
+# Azure Storage Queue client library for Java
+Azure Queue storage is a service for storing large numbers of messages that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS.
+A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account.
+
+[Source code][source_code] | [Package (Maven)][package] | [API reference documentation][api_documentation] | [Product documentation][storage_docs]
+
+## Getting started
+
+### Prerequisites
+
+- [Java Development Kit (JDK)][jdk] with version 8 or above
+- [Azure Subscription][azure_subscription]
+- [Create Strorage Account][storage_account]
+
+### Adding the package to your product
+
+```xml
+
+ com.azure
+ azure-storage
+ 12.0.0
+
+```
+
+### Create a Storage Account
+To create a Storage Account you can use the Azure Portal or [Azure CLI][azure_cli].
+
+```Powershell
+az group create \
+ --name storage-resource-group \
+ --location westus
+```
+
+### Authenticate the client
+
+In order to interact with the Storage service (Blob, Queue, Message, MessageId, File) you'll need to create an instance of the Service Client class.
+To make this possible you'll need the Account SAS (shared access signature) string of Storage account. Learn more at [SAS Token][sas_token]
+
+#### Get Credentials
+
+- **SAS Token**
+
+a. Use the [Azure CLI][azure_cli] snippet below to get the SAS token from the Storage account.
+
+```Powershell
+az storage queue generate-sas
+ --name {queue name}
+ --expiry {date/time to expire SAS token}
+ --permission {permission to grant}
+ --connection-string {connection string of the storage account}
+```
+
+```Powershell
+CONNECTION_STRING=
+
+az storage queue generate-sas
+ --name javasdksas
+ --expiry 2019-06-05
+ --permission rpau
+ --connection-string $CONNECTION_STRING
+```
+b. Alternatively, get the Account SAS Token from the Azure Portal.
+```
+Go to your storage account -> Shared access signature -> Click on Generate SAS and connection string (after setup)
+```
+
+- **Shared Key Credential**
+
+a. Use account name and account key. Account name is your storage account name.
+```
+// Here is where we get the key
+Go to your storage account -> Access keys -> Key 1/ Key 2 -> Key
+```
+b. Use the connection string
+```
+// Here is where we get the key
+Go to your storage account -> Access Keys -> Keys 1/ Key 2 -> Connection string
+```
+## Key concepts
+### URL format
+Queues are addressable using the following URL format:
+https://.queue.core.windows.net/
+The following URL addresses a queue in the diagram:
+https://myaccount.queue.core.windows.net/images-to-download
+
+#### Resource URI Syntax
+For the storage account, the base URI for queue operations includes the name of the account only:
+```$xslt
+https://myaccount.queue.core.windows.net
+```
+For a queue, the base URI includes the name of the account and the name of the queue:
+```$xslt
+https://myaccount.queue.core.windows.net/myqueue
+```
+
+### Handling Exceptions
+
+```java
+TODO
+```
+
+### Queue Names
+Every queue within an account must have a unique name. The queue name must be a valid DNS name, and cannot be changed once created. Queue names must confirm to the following rules:
+1. A queue name must start with a letter or number, and can only contain letters, numbers, and the dash (-) character.
+1. The first and last letters in the queue name must be alphanumeric. The dash (-) character cannot be the first or last character. Consecutive dash characters are not permitted in the queue name.
+1. All letters in a queue name must be lowercase.
+1. A queue name must be from 3 through 63 characters long.
+
+### Queue Services
+The queue service do operations on the queues in the storage account and manage the queue properties.
+
+### Queue Service Client
+
+The client performs the interactions with the Queue service, create or delete a queue, getting and setting Queue properties, list queues in account, and get queue statistics. An asynchronous, `QueueServiceAsyncClient`, and synchronous, `QueueClient`, client exists in the SDK allowing for selection of a client based on an application's use case.
+Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${sasToken}`.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue");
+```
+
+or
+
+```Java
+String queueServiceAsyncURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceAsyncClient queueServiceAsyncClient = QueueServiceAsyncClient.builder().endpoint(queueServiceAsyncURL).build();
+queueServiceAsyncClient.createQueue("newAsyncQueue").subscribe(
+ result -> {
+ // do something when new queue created
+ },
+ error -> {
+ // do something if something wrong happened
+ },
+ () -> {
+ // completed, do something
+ });
+```
+
+### Queue
+Azure Queue storage is a service for storing large numbers of messages that can be accessed from anywhere in the world via authenticated calls using HTTP or HTTPS.
+A single queue message can be up to 64 KB in size, and a queue can contain millions of messages, up to the total capacity limit of a storage account.
+
+### QueueClient
+Once you have the value of the SASToken you can create the queue service client with `${accountName}`, `${queueName}`, `${sasToken}`.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+// metadata is map of key-value pair, timeout is client side timeout
+QueueClient newQueueClient = queueClient.create(metadata, timeout);
+```
+
+or
+
+```Java
+String queueAsyncURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueAsyncName, sasToken)
+QueueAsyncClient queueAsyncClient = QueueAsyncClient.builder().endpoint(queueAsyncURL).build();
+queueAsyncClient.create(metadata, timeout).subscribe(
+ result -> {
+ // do something when new queue created
+ },
+ error -> {
+ // do something if something wrong happened
+ },
+ () -> {
+ // completed, do something
+ });
+```
+
+## Examples
+
+The following sections provide several code snippets covering some of the most common Configuration Service tasks, including:
+- [Create a Queue](#Create-a-queue)
+- [Delete a queue](#Delete-a-queue)
+- [List the queues in account](#List-queues-in-account)
+- [Get propertiesin Queue account](#Get-properties-in-queue-account)
+- [Set propertiesin Queue account](#Set-properties-in-queue-account)
+- [Get statistcs of queue](#Get-queue-service-statistics)
+- [Enqueue message into a queue](#Enqueue-message-into-a-queue)
+- [Update message into a queue](#Update-message-into-a-queue)
+- [Peek messages into a queue](#Peek-messages-into-a-queue)
+- [Dequeue messages from a queue](#Dequeue-messages-from-a-queue)
+- [Delete message from a queue](#Delete-message-from-a-queue)
+- [Get a Queue properties](#Get-a-queue-properties)
+- [Set/Update a Queue metadata](#Set-a-queue-metadata)
+### Create a queue
+
+Create a queue in the Storage Account. Throws StorageErrorException If the queue fails to be created.
+
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+QueueClient newQueueServiceClient = queueServiceClient.createQueue("myqueue");
+```
+### Delete a queue
+
+Delete a queue in the Storage Account. Throws StorageErrorException If the queue fails to be deleted.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+QueueClient newQueueServiceClient = queueServiceClient.deleteQueue("myqueue");
+```
+
+### List queues in account
+
+List all the queues in account.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+// @param marker: Starting point to list the queues
+// @param options: Filter for queue selection
+queueServiceClient.listQueuesSegment(marker, options).forEach{
+ queueItem -> {//do something}
+};
+```
+
+### Get properties in queue account
+
+Get queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+Response properties = queueServiceClient.getProperties();
+```
+
+### Set properties in queue account
+
+Set queue properties in account, including properties for Storage Analytics and CORS (Cross-Origin Resource Sharing) rules.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+StorageServiceProperties properties = new StorageServiceProperties() {
+ // logging: some logging;
+ // HourMetrics: some metrics
+ // MinuteMetrics: some metrics
+ // Cors: some cors
+}
+
+queueServiceClient.setProperties(properties);
+```
+
+### Get queue service statistics
+he `Get Queue Service Stats` operation retrieves statistics related to replication for the Queue service.
+It is only available on the secondary location endpoint when read-access geo-redundant replication is enabled for the storage account.
+```Java
+String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", accountName, sasToken)
+QueueServiceClient queueServiceClient = QueueServiceClient.builder().endpoint(queueURL).build();
+
+Response queueStats = queueServiceClient.getStatistics();
+```
+
+### Enqueue message into a queue
+The operation adds a new message to the back of the message queue. A visibility timeout can also be specified to make the message invisible until the visibility timeout expires.
+A message must be in a format that can be included in an XML request with UTF-8 encoding. The encoded message can be up to 64 KB in size for versions 2011-08-18 and newer, or 8 KB in size for previous versions.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+queueClient.enqueueMessage("myMessage");
+```
+
+### Update messaged from a queue
+The operation updates a message in the message queue.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+// @param messageId Id of the message
+// @param popReceipt Unique identifier that must match the message for it to be updated
+// @param visibilityTimeout How long the message will be invisible in the queue in seconds
+queueClient.updateMessage(messageId, "new message", popReceipt, visibilityTimeout);
+```
+
+### Peek messages from a queue
+The operation retrieves one or more messages from the front of the queue.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+queueClient.peekMessages().forEach(message-> {print message.messageText();});
+```
+
+
+### Dequeue messages from a queue
+The operation retrieves one or more messages from the front of the queue.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+queueClient.dequeueMessage("myMessage").forEach(message-> {print message.messageText();});
+```
+
+
+### Delete message from a queue
+The operation retrieves one or more messages from the front of the queue.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+queueClient.deleteMessage(messageId, popReceipt);
+```
+
+### Get a queue properties
+The operation retrieves user-defined metadata and queue properties on the specified queue. Metadata is associated with the queue as name-values pairs.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+Response properties = queueClient.getProperties();
+```
+
+### Set a queue metadata
+The operation sets user-defined metadata on the specified queue. Metadata is associated with the queue as name-value pairs.
+```Java
+String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", accountName, queueName, sasToken);
+QueueClient queueClient = QueueClient.builder().endpoint(queueURL).build();
+
+Map metadata = new HashMap<>() {{
+ put("key1", "val1");
+ put("key2", "val2");
+}};
+queueClient.setMetadata(metadata);
+```
+
+
+## Troubleshooting
+
+## General
+
+When you interact with queue using this Java client library, errors returned by the service correspond to the same HTTP status codes returned for [REST API][storage_rest] requests. For example, if you try to retrieve a queue that doesn't exist in your Storage Account, a `404` error is returned, indicating `Not Found`.
+
+## Next steps
+
+### More Samples
+- QueueServiceSample
+- MessageSample
+- QueueExceptionSample
+- AsyncSample
+
+[Quickstart: Create a Java Spring app with App Configuration](https://docs.microsoft.com/en-us/azure/azure-app-configuration/quickstart-java-spring-app)
+
+## Contributing
+This project welcomes contributions and suggestions. Most contributions require you to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
+the rights to use your contribution. For details, visit https://cla.microsoft.com.
+
+When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
+a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
+provided by the bot. You will only need to do this once across all repos using our CLA.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
+contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
+
+If you would like to become an active contributor to this project please follow the instructions provided in [Microsoft Azure Projects Contribution Guidelines](http://azure.github.io/guidelines.html).
+
+1. Fork it
+2. Create your feature branch (`git checkout -b my-new-feature`)
+3. Commit your changes (`git commit -am 'Add some feature'`)
+4. Push to the branch (`git push origin my-new-feature`)
+5. Create new Pull Request
+
+
+[source_code]: to-be-continue
+[package]: to-be-continue
+[api_documentation]: https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-rest-api
+[storage_docs]: https://docs.microsoft.com/en-us/azure/storage/queues/storage-queues-introduction
+[jdk]: https://docs.microsoft.com/en-us/java/azure/java-supported-jdk-runtime?view=azure-java-stable
+[maven]: https://maven.apache.org/
+[azure_subscription]: https://azure.microsoft.com/en-us/free/
+[storage_account]: https://docs.microsoft.com/en-us/azure/storage/common/storage-quickstart-create-account?tabs=azure-portal
+[azure_cli]: https://docs.microsoft.com/cli/azure
+[sas_token]: https://docs.microsoft.com/en-us/azure/storage/common/storage-dotnet-shared-access-signature-part-1
+[storage_rest]: https://docs.microsoft.com/en-us/rest/api/storageservices/queue-service-error-codes
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java
index 4f678dfe10832..f3582e10e1a44 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/AzureQueueStorageBuilder.java
@@ -75,9 +75,7 @@ public AzureQueueStorageImpl build() {
if (this.url != null) {
client.url(this.url);
}
- if (this.version != null) {
- client.version(this.version);
- }
+ client.version(this.version);
return client;
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java
index 8a705fe7e4af7..f5e6c952f5de1 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessageIdsImpl.java
@@ -10,6 +10,7 @@
import com.azure.core.annotations.HeaderParam;
import com.azure.core.annotations.Host;
import com.azure.core.annotations.HostParam;
+import com.azure.core.annotations.PathParam;
import com.azure.core.annotations.PUT;
import com.azure.core.annotations.QueryParam;
import com.azure.core.annotations.Service;
@@ -57,12 +58,12 @@ private interface MessageIdsService {
@PUT("{queueName}/messages/{messageid}")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono update(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono update(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("popreceipt") String popReceipt, @QueryParam("visibilitytimeout") int visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@DELETE("{queueName}/messages/{messageid}")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono delete(@HostParam("url") String url, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @PathParam("messageid") String messageId, @QueryParam("popreceipt") String popReceipt, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
}
/**
@@ -75,10 +76,10 @@ private interface MessageIdsService {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) {
+ public Mono updateWithRestResponseAsync(String queueName, String messageId, QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Context context) {
final Integer timeout = null;
final String requestId = null;
- return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context);
+ return service.update(this.client.url(), queueName, messageId, queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context);
}
/**
@@ -93,8 +94,8 @@ public Mono updateWithRestResponseAsync(QueueMessage q
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono updateWithRestResponseAsync(QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Integer timeout, String requestId, Context context) {
- return service.update(this.client.url(), queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context);
+ public Mono updateWithRestResponseAsync(String queueName, String messageId, QueueMessage queueMessage, String popReceipt, int visibilitytimeout, Integer timeout, String requestId, Context context) {
+ return service.update(this.client.url(), queueName, messageId, queueMessage, popReceipt, visibilitytimeout, timeout, this.client.version(), requestId, context);
}
/**
@@ -105,10 +106,10 @@ public Mono updateWithRestResponseAsync(QueueMessage q
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono deleteWithRestResponseAsync(String popReceipt, Context context) {
+ public Mono deleteWithRestResponseAsync(String queueName, String messageId, String popReceipt, Context context) {
final Integer timeout = null;
final String requestId = null;
- return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context);
+ return service.delete(this.client.url(), queueName, messageId, popReceipt, timeout, this.client.version(), requestId, context);
}
/**
@@ -121,7 +122,7 @@ public Mono deleteWithRestResponseAsync(String popRece
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono deleteWithRestResponseAsync(String popReceipt, Integer timeout, String requestId, Context context) {
- return service.delete(this.client.url(), popReceipt, timeout, this.client.version(), requestId, context);
+ public Mono deleteWithRestResponseAsync(String queueName, String messageId, String popReceipt, Integer timeout, String requestId, Context context) {
+ return service.delete(this.client.url(), queueName, messageId, popReceipt, timeout, this.client.version(), requestId, context);
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java
index ee59aae16b63f..84f680cad1dba 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/MessagesImpl.java
@@ -11,6 +11,7 @@
import com.azure.core.annotations.HeaderParam;
import com.azure.core.annotations.Host;
import com.azure.core.annotations.HostParam;
+import com.azure.core.annotations.PathParam;
import com.azure.core.annotations.POST;
import com.azure.core.annotations.QueryParam;
import com.azure.core.annotations.Service;
@@ -60,22 +61,22 @@ private interface MessagesService {
@GET("{queueName}/messages")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono dequeue(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono dequeue(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@DELETE("{queueName}/messages")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono clear(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono clear(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@POST("{queueName}/messages")
@ExpectedResponses({201})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono enqueue(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono enqueue(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") QueueMessage queueMessage, @QueryParam("visibilitytimeout") Integer visibilitytimeout, @QueryParam("messagettl") Integer messageTimeToLive, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@GET("{queueName}/messages")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono peek(@HostParam("url") String url, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context);
+ Mono peek(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("numofmessages") Integer numberOfMessages, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("peekonly") String peekonly, Context context);
}
/**
@@ -85,12 +86,12 @@ private interface MessagesService {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono dequeueWithRestResponseAsync(Context context) {
+ public Mono dequeueWithRestResponseAsync(String queueName, Context context) {
final Integer numberOfMessages = null;
final Integer visibilitytimeout = null;
final Integer timeout = null;
final String requestId = null;
- return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context);
+ return service.dequeue(this.client.url(), queueName, numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context);
}
/**
@@ -104,8 +105,8 @@ public Mono dequeueWithRestResponseAsync(Context contex
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono dequeueWithRestResponseAsync(Integer numberOfMessages, Integer visibilitytimeout, Integer timeout, String requestId, Context context) {
- return service.dequeue(this.client.url(), numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context);
+ public Mono dequeueWithRestResponseAsync(String queueName, Integer numberOfMessages, Integer visibilitytimeout, Integer timeout, String requestId, Context context) {
+ return service.dequeue(this.client.url(), queueName, numberOfMessages, visibilitytimeout, timeout, this.client.version(), requestId, context);
}
/**
@@ -115,10 +116,10 @@ public Mono dequeueWithRestResponseAsync(Integer number
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono clearWithRestResponseAsync(Context context) {
+ public Mono clearWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final String requestId = null;
- return service.clear(this.client.url(), timeout, this.client.version(), requestId, context);
+ return service.clear(this.client.url(), queueName, timeout, this.client.version(), requestId, context);
}
/**
@@ -130,8 +131,8 @@ public Mono clearWithRestResponseAsync(Context context) {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono clearWithRestResponseAsync(Integer timeout, String requestId, Context context) {
- return service.clear(this.client.url(), timeout, this.client.version(), requestId, context);
+ public Mono clearWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) {
+ return service.clear(this.client.url(), queueName, timeout, this.client.version(), requestId, context);
}
/**
@@ -142,12 +143,12 @@ public Mono clearWithRestResponseAsync(Integer timeout, S
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Context context) {
+ public Mono enqueueWithRestResponseAsync(String queueName, QueueMessage queueMessage, Context context) {
final Integer visibilitytimeout = null;
final Integer messageTimeToLive = null;
final Integer timeout = null;
final String requestId = null;
- return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context);
+ return service.enqueue(this.client.url(), queueName, queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context);
}
/**
@@ -162,8 +163,8 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono enqueueWithRestResponseAsync(QueueMessage queueMessage, Integer visibilitytimeout, Integer messageTimeToLive, Integer timeout, String requestId, Context context) {
- return service.enqueue(this.client.url(), queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context);
+ public Mono enqueueWithRestResponseAsync(String queueName, QueueMessage queueMessage, Integer visibilitytimeout, Integer messageTimeToLive, Integer timeout, String requestId, Context context) {
+ return service.enqueue(this.client.url(), queueName, queueMessage, visibilitytimeout, messageTimeToLive, timeout, this.client.version(), requestId, context);
}
/**
@@ -173,12 +174,12 @@ public Mono enqueueWithRestResponseAsync(QueueMessage q
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono peekWithRestResponseAsync(Context context) {
+ public Mono peekWithRestResponseAsync(String queueName, Context context) {
final Integer numberOfMessages = null;
final Integer timeout = null;
final String requestId = null;
final String peekonly = "true";
- return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context);
+ return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context);
}
/**
@@ -191,8 +192,8 @@ public Mono peekWithRestResponseAsync(Context context) {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono peekWithRestResponseAsync(Integer numberOfMessages, Integer timeout, String requestId, Context context) {
+ public Mono peekWithRestResponseAsync(String queueName, Integer numberOfMessages, Integer timeout, String requestId, Context context) {
final String peekonly = "true";
- return service.peek(this.client.url(), numberOfMessages, timeout, this.client.version(), requestId, peekonly, context);
+ return service.peek(this.client.url(), queueName, numberOfMessages, timeout, this.client.version(), requestId, peekonly, context);
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java
index 2eb2d4d1ec2e2..db933d31e4238 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/QueuesImpl.java
@@ -11,6 +11,7 @@
import com.azure.core.annotations.HeaderParam;
import com.azure.core.annotations.Host;
import com.azure.core.annotations.HostParam;
+import com.azure.core.annotations.PathParam;
import com.azure.core.annotations.PUT;
import com.azure.core.annotations.QueryParam;
import com.azure.core.annotations.Service;
@@ -25,10 +26,9 @@
import com.azure.storage.queue.models.QueuesSetMetadataResponse;
import com.azure.storage.queue.models.SignedIdentifier;
import com.azure.storage.queue.models.StorageErrorException;
-import reactor.core.publisher.Mono;
-
import java.util.List;
import java.util.Map;
+import reactor.core.publisher.Mono;
/**
* An instance of this class provides access to all the operations defined in
@@ -65,32 +65,32 @@ private interface QueuesService {
@PUT("{queueName}")
@ExpectedResponses({201, 204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono create(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono create(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@DELETE("{queueName}")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono delete(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
+ Mono delete(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, Context context);
@GET("{queueName}")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono getProperties(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
+ Mono getProperties(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
@PUT("{queueName}")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono setMetadata(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
+ Mono setMetadata(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-meta-") Map metadata, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
@GET("{queueName}")
@ExpectedResponses({200})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono getAccessPolicy(@HostParam("url") String url, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
+ Mono getAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
@PUT("{queueName}")
@ExpectedResponses({204})
@UnexpectedResponseExceptionType(StorageErrorException.class)
- Mono setAccessPolicy(@HostParam("url") String url, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
+ Mono setAccessPolicy(@HostParam("url") String url, @PathParam("queueName") String queueName, @BodyParam("application/xml; charset=utf-8") SignedIdentifiersWrapper queueAcl, @QueryParam("timeout") Integer timeout, @HeaderParam("x-ms-version") String version, @HeaderParam("x-ms-client-request-id") String requestId, @QueryParam("comp") String comp, Context context);
}
/**
@@ -100,11 +100,11 @@ private interface QueuesService {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono createWithRestResponseAsync(Context context) {
+ public Mono createWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final Map metadata = null;
final String requestId = null;
- return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context);
+ return service.create(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, context);
}
/**
@@ -117,8 +117,8 @@ public Mono createWithRestResponseAsync(Context context) {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono createWithRestResponseAsync(Integer timeout, Map metadata, String requestId, Context context) {
- return service.create(this.client.url(), timeout, metadata, this.client.version(), requestId, context);
+ public Mono createWithRestResponseAsync(String queueName, Integer timeout, Map metadata, String requestId, Context context) {
+ return service.create(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, context);
}
/**
@@ -128,10 +128,10 @@ public Mono createWithRestResponseAsync(Integer timeout, M
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono deleteWithRestResponseAsync(Context context) {
+ public Mono deleteWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final String requestId = null;
- return service.delete(this.client.url(), timeout, this.client.version(), requestId, context);
+ return service.delete(this.client.url(), queueName, timeout, this.client.version(), requestId, context);
}
/**
@@ -143,8 +143,8 @@ public Mono deleteWithRestResponseAsync(Context context) {
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono deleteWithRestResponseAsync(Integer timeout, String requestId, Context context) {
- return service.delete(this.client.url(), timeout, this.client.version(), requestId, context);
+ public Mono deleteWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) {
+ return service.delete(this.client.url(), queueName, timeout, this.client.version(), requestId, context);
}
/**
@@ -154,11 +154,11 @@ public Mono deleteWithRestResponseAsync(Integer timeout, S
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono getPropertiesWithRestResponseAsync(Context context) {
+ public Mono getPropertiesWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final String requestId = null;
final String comp = "metadata";
- return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context);
+ return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context);
}
/**
@@ -170,9 +170,9 @@ public Mono getPropertiesWithRestResponseAsync(Cont
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono getPropertiesWithRestResponseAsync(Integer timeout, String requestId, Context context) {
+ public Mono getPropertiesWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) {
final String comp = "metadata";
- return service.getProperties(this.client.url(), timeout, this.client.version(), requestId, comp, context);
+ return service.getProperties(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context);
}
/**
@@ -182,12 +182,12 @@ public Mono getPropertiesWithRestResponseAsync(Inte
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono setMetadataWithRestResponseAsync(Context context) {
+ public Mono setMetadataWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final Map metadata = null;
final String requestId = null;
final String comp = "metadata";
- return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context);
+ return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context);
}
/**
@@ -200,9 +200,9 @@ public Mono setMetadataWithRestResponseAsync(Context
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono setMetadataWithRestResponseAsync(Integer timeout, Map metadata, String requestId, Context context) {
+ public Mono setMetadataWithRestResponseAsync(String queueName, Integer timeout, Map metadata, String requestId, Context context) {
final String comp = "metadata";
- return service.setMetadata(this.client.url(), timeout, metadata, this.client.version(), requestId, comp, context);
+ return service.setMetadata(this.client.url(), queueName, timeout, metadata, this.client.version(), requestId, comp, context);
}
/**
@@ -212,11 +212,11 @@ public Mono setMetadataWithRestResponseAsync(Integer
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono getAccessPolicyWithRestResponseAsync(Context context) {
+ public Mono getAccessPolicyWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final String requestId = null;
final String comp = "acl";
- return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context);
+ return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context);
}
/**
@@ -228,9 +228,9 @@ public Mono getAccessPolicyWithRestResponseAsync(
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono getAccessPolicyWithRestResponseAsync(Integer timeout, String requestId, Context context) {
+ public Mono getAccessPolicyWithRestResponseAsync(String queueName, Integer timeout, String requestId, Context context) {
final String comp = "acl";
- return service.getAccessPolicy(this.client.url(), timeout, this.client.version(), requestId, comp, context);
+ return service.getAccessPolicy(this.client.url(), queueName, timeout, this.client.version(), requestId, comp, context);
}
/**
@@ -240,12 +240,12 @@ public Mono getAccessPolicyWithRestResponseAsync(
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono setAccessPolicyWithRestResponseAsync(Context context) {
+ public Mono setAccessPolicyWithRestResponseAsync(String queueName, Context context) {
final Integer timeout = null;
final String requestId = null;
final String comp = "acl";
SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(null);
- return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context);
+ return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context);
}
/**
@@ -258,9 +258,9 @@ public Mono setAccessPolicyWithRestResponseAsync(
* @throws IllegalArgumentException thrown if parameters fail the validation.
* @return a Mono which performs the network request upon subscription.
*/
- public Mono setAccessPolicyWithRestResponseAsync(List queueAcl, Integer timeout, String requestId, Context context) {
+ public Mono setAccessPolicyWithRestResponseAsync(String queueName, List queueAcl, Integer timeout, String requestId, Context context) {
final String comp = "acl";
SignedIdentifiersWrapper queueAclConverted = new SignedIdentifiersWrapper(queueAcl);
- return service.setAccessPolicy(this.client.url(), queueAclConverted, timeout, this.client.version(), requestId, comp, context);
+ return service.setAccessPolicy(this.client.url(), queueName, queueAclConverted, timeout, this.client.version(), requestId, comp, context);
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java
index dc353d45f5243..1dc20d2b42fa8 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/implementation/ServicesImpl.java
@@ -25,9 +25,8 @@
import com.azure.storage.queue.models.ServicesSetPropertiesResponse;
import com.azure.storage.queue.models.StorageErrorException;
import com.azure.storage.queue.models.StorageServiceProperties;
-import reactor.core.publisher.Mono;
-
import java.util.List;
+import reactor.core.publisher.Mono;
/**
* An instance of this class provides access to all the operations defined in
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java
similarity index 85%
rename from storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java
rename to storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java
index 7febd2c02758d..65e6e941c717a 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessageItem.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/DequeuedMessage.java
@@ -1,6 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-// Code generated by Microsoft (R) AutoRest Code Generator.
package com.azure.storage.queue.models;
@@ -14,7 +13,7 @@
* on a Queue.
*/
@JacksonXmlRootElement(localName = "QueueMessage")
-public final class DequeuedMessageItem {
+public final class DequeuedMessage {
/*
* The Id of the Message.
*/
@@ -71,9 +70,9 @@ public String messageId() {
* Set the messageId property: The Id of the Message.
*
* @param messageId the messageId value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem messageId(String messageId) {
+ public DequeuedMessage messageId(String messageId) {
this.messageId = messageId;
return this;
}
@@ -96,9 +95,9 @@ public OffsetDateTime insertionTime() {
* the Queue.
*
* @param insertionTime the insertionTime value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem insertionTime(OffsetDateTime insertionTime) {
+ public DequeuedMessage insertionTime(OffsetDateTime insertionTime) {
if (insertionTime == null) {
this.insertionTime = null;
} else {
@@ -125,9 +124,9 @@ public OffsetDateTime expirationTime() {
* and be automatically deleted.
*
* @param expirationTime the expirationTime value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem expirationTime(OffsetDateTime expirationTime) {
+ public DequeuedMessage expirationTime(OffsetDateTime expirationTime) {
if (expirationTime == null) {
this.expirationTime = null;
} else {
@@ -153,9 +152,9 @@ public String popReceipt() {
* been dequeued by another client.
*
* @param popReceipt the popReceipt value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem popReceipt(String popReceipt) {
+ public DequeuedMessage popReceipt(String popReceipt) {
this.popReceipt = popReceipt;
return this;
}
@@ -178,9 +177,9 @@ public OffsetDateTime timeNextVisible() {
* become visible in the Queue.
*
* @param timeNextVisible the timeNextVisible value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem timeNextVisible(OffsetDateTime timeNextVisible) {
+ public DequeuedMessage timeNextVisible(OffsetDateTime timeNextVisible) {
if (timeNextVisible == null) {
this.timeNextVisible = null;
} else {
@@ -204,9 +203,9 @@ public long dequeueCount() {
* dequeued.
*
* @param dequeueCount the dequeueCount value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem dequeueCount(long dequeueCount) {
+ public DequeuedMessage dequeueCount(long dequeueCount) {
this.dequeueCount = dequeueCount;
return this;
}
@@ -224,9 +223,9 @@ public String messageText() {
* Set the messageText property: The content of the Message.
*
* @param messageText the messageText value to set.
- * @return the DequeuedMessageItem object itself.
+ * @return the DequeuedMessage object itself.
*/
- public DequeuedMessageItem messageText(String messageText) {
+ public DequeuedMessage messageText(String messageText) {
this.messageText = messageText;
return this;
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java
index 4ab4b09a4a620..c08c7ccc025c7 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesDequeueResponse.java
@@ -12,7 +12,7 @@
/**
* Contains all response data for the dequeue operation.
*/
-public final class MessagesDequeueResponse extends ResponseBase> {
+public final class MessagesDequeueResponse extends ResponseBase> {
/**
* Creates an instance of MessagesDequeueResponse.
*
@@ -22,7 +22,7 @@ public final class MessagesDequeueResponse extends ResponseBase value, MessagesDequeueHeaders headers) {
+ public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesDequeueHeaders headers) {
super(request, statusCode, rawHeaders, value, headers);
}
@@ -30,7 +30,7 @@ public MessagesDequeueResponse(HttpRequest request, int statusCode, HttpHeaders
* @return the deserialized response body.
*/
@Override
- public List value() {
+ public List value() {
return super.value();
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java
index 8ca8ed06fd99c..27ac646138908 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/MessagesPeekResponse.java
@@ -12,7 +12,7 @@
/**
* Contains all response data for the peek operation.
*/
-public final class MessagesPeekResponse extends ResponseBase> {
+public final class MessagesPeekResponse extends ResponseBase> {
/**
* Creates an instance of MessagesPeekResponse.
*
@@ -22,7 +22,7 @@ public final class MessagesPeekResponse extends ResponseBase value, MessagesPeekHeaders headers) {
+ public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders rawHeaders, List value, MessagesPeekHeaders headers) {
super(request, statusCode, rawHeaders, value, headers);
}
@@ -30,7 +30,7 @@ public MessagesPeekResponse(HttpRequest request, int statusCode, HttpHeaders raw
* @return the deserialized response body.
*/
@Override
- public List value() {
+ public List value() {
return super.value();
}
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java
similarity index 85%
rename from storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java
rename to storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java
index d86bdab8c2305..edc9960d2d747 100644
--- a/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessageItem.java
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/PeekedMessage.java
@@ -1,6 +1,5 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.
-// Code generated by Microsoft (R) AutoRest Code Generator.
package com.azure.storage.queue.models;
@@ -14,7 +13,7 @@
* on a Queue.
*/
@JacksonXmlRootElement(localName = "QueueMessage")
-public final class PeekedMessageItem {
+public final class PeekedMessage {
/*
* The Id of the Message.
*/
@@ -58,9 +57,9 @@ public String messageId() {
* Set the messageId property: The Id of the Message.
*
* @param messageId the messageId value to set.
- * @return the PeekedMessageItem object itself.
+ * @return the PeekedMessage object itself.
*/
- public PeekedMessageItem messageId(String messageId) {
+ public PeekedMessage messageId(String messageId) {
this.messageId = messageId;
return this;
}
@@ -83,9 +82,9 @@ public OffsetDateTime insertionTime() {
* the Queue.
*
* @param insertionTime the insertionTime value to set.
- * @return the PeekedMessageItem object itself.
+ * @return the PeekedMessage object itself.
*/
- public PeekedMessageItem insertionTime(OffsetDateTime insertionTime) {
+ public PeekedMessage insertionTime(OffsetDateTime insertionTime) {
if (insertionTime == null) {
this.insertionTime = null;
} else {
@@ -112,9 +111,9 @@ public OffsetDateTime expirationTime() {
* and be automatically deleted.
*
* @param expirationTime the expirationTime value to set.
- * @return the PeekedMessageItem object itself.
+ * @return the PeekedMessage object itself.
*/
- public PeekedMessageItem expirationTime(OffsetDateTime expirationTime) {
+ public PeekedMessage expirationTime(OffsetDateTime expirationTime) {
if (expirationTime == null) {
this.expirationTime = null;
} else {
@@ -138,9 +137,9 @@ public long dequeueCount() {
* dequeued.
*
* @param dequeueCount the dequeueCount value to set.
- * @return the PeekedMessageItem object itself.
+ * @return the PeekedMessage object itself.
*/
- public PeekedMessageItem dequeueCount(long dequeueCount) {
+ public PeekedMessage dequeueCount(long dequeueCount) {
this.dequeueCount = dequeueCount;
return this;
}
@@ -158,9 +157,9 @@ public String messageText() {
* Set the messageText property: The content of the Message.
*
* @param messageText the messageText value to set.
- * @return the PeekedMessageItem object itself.
+ * @return the PeekedMessage object itself.
*/
- public PeekedMessageItem messageText(String messageText) {
+ public PeekedMessage messageText(String messageText) {
this.messageText = messageText;
return this;
}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java
new file mode 100644
index 0000000000000..bb343ea96bd24
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueueProperties.java
@@ -0,0 +1,38 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue.models;
+
+import java.util.Map;
+
+/**
+ * Model class containing properties of a specific queue in the storage Queue service.
+ */
+public final class QueueProperties {
+ private final Map metadata;
+ private final int approximateMessagesCount;
+
+ /**
+ * Creates an instance that contains properties of a queue.
+ *
+ * @param metadata Metadata associated with the queue
+ * @param approximateMessagesCount Approximate number of messages contained in the queue
+ */
+ public QueueProperties(Map metadata, int approximateMessagesCount) {
+ this.metadata = metadata;
+ this.approximateMessagesCount = approximateMessagesCount;
+ }
+
+ /**
+ * @return the user-defined metadata associated with the queue
+ */
+ public Map metadata() {
+ return this.metadata;
+ }
+
+ /**
+ * @return the approximate number of messages contained in the queue at the time of properties retrieval
+ */
+ public int approximateMessagesCount() {
+ return approximateMessagesCount;
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java
new file mode 100644
index 0000000000000..d58b2f71b8d05
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/QueuesSegmentOptions.java
@@ -0,0 +1,89 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue.models;
+
+import com.azure.storage.queue.QueueServiceAsyncClient;
+import com.azure.storage.queue.QueueServiceClient;
+
+/**
+ * A set of options for selecting queues from Storage Queue service.
+ *
+ *
+ *
+ * Providing {@link QueuesSegmentOptions#prefix() prefix} will filter {@link QueueItem queues} that begin
+ * with the prefix.
+ *
+ *
+ * Providing {@link QueuesSegmentOptions#maxResults() maxResults} will limit the number of {@link QueueItem queues}
+ * returned in a single page.
+ *
+ *
+ * Setting {@link QueuesSegmentOptions#includeMetadata() includeMetadata} to true will include the metadata of
+ * each {@link QueueItem queue}, if false {@link QueueItem#metadata() metadata} for each queue will be {@code null}.
+ *
+ *
+ *
+ * @see QueueServiceClient
+ * @see QueueServiceAsyncClient
+ */
+public final class QueuesSegmentOptions {
+ private boolean includeMetadata;
+
+ private String prefix;
+
+ private Integer maxResults;
+
+ /**
+ * @return the status of including metadata when listing queues
+ */
+ public boolean includeMetadata() {
+ return includeMetadata;
+ }
+
+ /**
+ * Sets the status of including queue metadata when listing queues
+ *
+ * @param includeMetadata Flag indicating if metadata should be included in the listing
+ * @return An updated QueuesSegmentOptions object
+ */
+ public QueuesSegmentOptions includeMetadata(boolean includeMetadata) {
+ this.includeMetadata = includeMetadata;
+ return this;
+ }
+
+ /**
+ * @return the prefix the queue name must match to be included in the listing
+ */
+ public String prefix() {
+ return prefix;
+ }
+
+ /**
+ * Sets the prefix that a queue must match to be included in the listing
+ *
+ * @param prefix The prefix that queues must start with to pass the filter
+ * @return An updated QueuesSegmentOptions object
+ */
+ public QueuesSegmentOptions prefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ /**
+ * @return the maximum number of queues to include in a single response
+ */
+ public Integer maxResults() {
+ return maxResults;
+ }
+
+ /**
+ * Sets the maximum number of queues to include in a single response
+ *
+ * @param maxResults Maximum number of results to include in a single response
+ * @return An updated QueuesSegmentOptions object
+ */
+ public QueuesSegmentOptions maxResults(Integer maxResults) {
+ this.maxResults = maxResults;
+ return this;
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java b/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java
new file mode 100644
index 0000000000000..fa6a4d5970153
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/models/UpdatedMessage.java
@@ -0,0 +1,39 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue.models;
+
+import java.time.OffsetDateTime;
+
+/**
+ * Response from the service when updating a message. Contains the information needed to continue working with
+ * the specific message.
+ */
+public final class UpdatedMessage {
+ private final String popReceipt;
+ private final OffsetDateTime timeNextVisible;
+
+ /**
+ * Creates an instance of updated message information.
+ *
+ * @param popReceipt Unique identifier that verifies the operation on a message is valid
+ * @param timeNextVisible The next time the message will be visible to other operations in the queue
+ */
+ public UpdatedMessage(String popReceipt, OffsetDateTime timeNextVisible) {
+ this.popReceipt = popReceipt;
+ this.timeNextVisible = timeNextVisible;
+ }
+
+ /**
+ * @return the unique identifier used to verify that the operation is allowed on the message
+ */
+ public String popReceipt() {
+ return popReceipt;
+ }
+
+ /**
+ * @return the next time the message will be visible to other operations in the queue
+ */
+ public OffsetDateTime timeNextVisible() {
+ return timeNextVisible;
+ }
+}
diff --git a/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java b/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java
new file mode 100644
index 0000000000000..e6671d8292fac
--- /dev/null
+++ b/storage/client/queue/src/main/java/com/azure/storage/queue/package-info.java
@@ -0,0 +1,7 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+/**
+ * This package contains the classes to perform actions on Azure Storage Queue.
+ */
+package com.azure.storage.queue;
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java
new file mode 100644
index 0000000000000..39cc17db37ca2
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/AsyncSamples.java
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.storage.queue;
+
+import static com.azure.storage.queue.SampleHelper.generateRandomName;
+
+/*
+ * This example mimics some arbitrary number of clients continuously sending messages up to a queue in a parallel and
+ * a server dequeuing the messages and processing them.
+ */
+public class AsyncSamples {
+ private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME");
+ private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN");
+ private static final String QUEUE_NAME = generateRandomName("async-call", 16);
+
+ /**
+ * The main method shows how we do the basic operations of enqueueing and dequeueing messages on async queue client.
+ * @param args No args needed for main method.
+ */
+ public static void main(String[] args) {
+ // Create an async queue client.
+ String queueURL = String.format("https://%s.queue.core.windows.net/%s%s", ACCOUNT_NAME, QUEUE_NAME, SAS_TOKEN);
+ QueueAsyncClient queueAsyncClient = new QueueClientBuilder().endpoint(queueURL).buildAsyncClient();
+
+ // Create a queue, enqueue two messages.
+ queueAsyncClient.create()
+ .doOnSuccess(response -> queueAsyncClient.enqueueMessage("This is message 1"))
+ .then(queueAsyncClient.enqueueMessage("This is message 2"))
+ .subscribe(
+ response -> {
+ System.out.println("Message successfully equeueed by queueAsyncClient. Message id:" + response.value().messageId());
+ },
+ err -> {
+ System.out.println("Error thrown when enqueue the message. Error message: " + err.getMessage());
+ },
+ () -> {
+ System.out.println("The enqueue has been completed.");
+ }
+ );
+ }
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java
new file mode 100644
index 0000000000000..1372d45b9e808
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/MessageSamples.java
@@ -0,0 +1,73 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.storage.queue;
+
+import com.azure.core.http.rest.Response;
+import com.azure.storage.queue.models.DequeuedMessage;
+
+import java.time.Duration;
+
+import static com.azure.storage.queue.SampleHelper.generateRandomName;
+
+public class MessageSamples {
+ private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME");
+ private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN");
+
+ /**
+ * The main method illustrate the basic operations for enqueue and dequeue messages using sync client.
+ * @param args No args needed for main method.
+ * @throws InterruptedException If the Thread.sleep operation gets interrupted.
+ */
+ public static void main(String[] args) throws InterruptedException {
+ // Build Queue Client using SAS Token
+ String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN);
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient();
+
+ // Create a queue client
+ Response queueClientResponse = queueServiceClient.createQueue(generateRandomName("enqueue", 16));
+ QueueClient queueClient = queueClientResponse.value();
+ // Using queue client to enqueue several "Hello World" messages into queue.
+ for (int i = 0; i < 3; i++) {
+ queueClient.enqueueMessage("Hello World");
+ }
+
+ // Enqueue json file into message.
+ // TODO
+
+ // Get the total count of msg in the queue
+ int count = queueClient.getProperties().value().approximateMessagesCount();
+
+ // Peek all messages in queue. It is supposed to print "Hello World" 3 times.
+ queueClient.peekMessages(count).forEach(
+ peekedMessage -> {
+ System.out.println("Here is the msg: " + peekedMessage.messageText());
+ }
+ );
+
+ // Dequeue all messages in queue and update the message "Hello World" to Hello, world!"
+ queueClient.dequeueMessages(count, Duration.ZERO).forEach(
+ queueMessage -> {
+ String msgToReplace = String.format("Hello, world!");
+ queueClient.updateMessage(queueMessage.messageId(), msgToReplace, queueMessage.popReceipt(), Duration.ZERO);
+ }
+ );
+
+ // Delete the first available msg.
+ // Since there is no invisible time for above dequeue, the following if condition should be true.
+ if (queueClient.dequeueMessages().iterator().hasNext()) {
+ DequeuedMessage queueMessage = queueClient.dequeueMessages().iterator().next();
+ queueClient.deleteMessage(queueMessage.messageId(), queueMessage.popReceipt());
+ } else {
+ System.out.println("OOps, the messages disappear!");
+ }
+
+ // Clear all messages in the queue
+ // Sleep to guarantee we skip the default invisible time.
+ Thread.sleep(500);
+ queueClient.clearMessages();
+
+ // Finally, we delete the queue.
+ queueClient.delete();
+ }
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java
new file mode 100644
index 0000000000000..d0ee4c8f2aed4
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueExceptionSamples.java
@@ -0,0 +1,69 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.storage.queue;
+
+import com.azure.core.http.rest.Response;
+import com.azure.storage.queue.models.StorageErrorCode;
+import com.azure.storage.queue.models.StorageErrorException;
+
+import static com.azure.storage.queue.SampleHelper.generateRandomName;
+
+public class QueueExceptionSamples {
+ private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME");
+ private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN");
+
+ /**
+ * The main method shows how to handle the storage exception.
+ * @param args No args needed for the main method.
+ * @throws RuntimeException If queueServiceClient failed to create a queue.
+ */
+ public static void main(String[] args) {
+ // Create a queue service client.
+ String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN);
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient();
+
+ // Create queue client.
+ Response queueClientResponse;
+ try {
+ queueClientResponse = queueServiceClient.createQueue(generateRandomName("delete-not-exist", 16));
+ System.out.println("Successfully create the queue! Status code: " + String.valueOf(queueClientResponse.statusCode()));
+ } catch (StorageErrorException e) {
+ System.out.println(String.format("Error creating a queue. Error message: %s", e.value().message()));
+ throw new RuntimeException(e);
+ }
+ QueueClient queueClient = queueClientResponse.value();
+ queueClient.enqueueMessage("Hello, message 1!");
+ queueClient.enqueueMessage("Hello, message 2!");
+
+ // Delete message with wrong message id.
+ try {
+ queueClientResponse.value().dequeueMessages().forEach(
+ msg -> {
+ queueClient.deleteMessage("wrong id", msg.popReceipt());
+ }
+ );
+ } catch (StorageErrorException e) {
+ if (e.getMessage().contains(StorageErrorCode.MESSAGE_NOT_FOUND.toString())) {
+ System.out.println("This is the error expected to throw");
+ } else {
+ System.out.println("This is not the error we expect!");
+ }
+ }
+
+ // Delete message with wrong pop receipt.
+ try {
+ queueClient.dequeueMessages().forEach(
+ msg -> {
+ queueClient.deleteMessage(msg.messageId(), "Wrong Pop Receipt");
+ }
+ );
+ } catch (StorageErrorException e) {
+ if (e.getMessage().contains(StorageErrorCode.INVALID_QUERY_PARAMETER_VALUE.toString())) {
+ System.out.println("This is the error expected to throw");
+ } else {
+ System.out.println("This is not the error we expect!");
+ }
+ }
+ }
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java
new file mode 100644
index 0000000000000..ed1a9875a3d03
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/QueueServiceSamples.java
@@ -0,0 +1,31 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.storage.queue;
+
+import static com.azure.storage.queue.SampleHelper.generateRandomName;
+
+public class QueueServiceSamples {
+ private static final String ACCOUNT_NAME = System.getenv("AZURE_STORAGE_ACCOUNT_NAME");
+ private static final String SAS_TOKEN = System.getenv("PRIMARY_SAS_TOKEN");
+
+ /**
+ * The main method illustrated the basic operations of creating and deleting queues using queue service sync client.
+ * @param args No args needed for main method.
+ */
+ public static void main(String[] args) {
+ // Build Queue Service Client using SAS Token
+ String queueServiceURL = String.format("https://%s.queue.core.windows.net/%s", ACCOUNT_NAME, SAS_TOKEN);
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder().endpoint(queueServiceURL).buildClient();
+ queueServiceClient.createQueue(generateRandomName("create-queue", 16));
+
+ // Create another queue and list all queues, print the name and then delete the queue.
+ queueServiceClient.createQueue(generateRandomName("create-extra", 16));
+ queueServiceClient.listQueues().forEach(
+ queueItem -> {
+ System.out.println("The queue name is: " + queueItem.name());
+ queueServiceClient.deleteQueue(queueItem.name());
+ }
+ );
+ }
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java
new file mode 100644
index 0000000000000..094a52026ffe6
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/SampleHelper.java
@@ -0,0 +1,13 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+
+package com.azure.storage.queue;
+
+import java.util.UUID;
+
+class SampleHelper {
+ static String generateRandomName(String prefix, int length) {
+ int len = length > prefix.length() ? length - prefix.length() : 0;
+ return prefix + UUID.randomUUID().toString().substring(0, len);
+ }
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java
new file mode 100644
index 0000000000000..24b0405a49350
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueJavaDocCodeSamples.java
@@ -0,0 +1,668 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue.javadoc;
+
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.queue.QueueAsyncClient;
+import com.azure.storage.queue.QueueClient;
+import com.azure.storage.queue.QueueClientBuilder;
+import com.azure.storage.queue.models.AccessPolicy;
+import com.azure.storage.queue.models.DequeuedMessage;
+import com.azure.storage.queue.models.EnqueuedMessage;
+import com.azure.storage.queue.models.QueueProperties;
+import com.azure.storage.queue.models.SignedIdentifier;
+import com.azure.storage.queue.models.UpdatedMessage;
+import java.time.Duration;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Contains code snippets when generating javadocs through doclets for {@link QueueClient} and {@link QueueAsyncClient}.
+ */
+
+public class QueueJavaDocCodeSamples {
+ /**
+ * Generates code sample for creating a {@link QueueClient}.
+ */
+ public void buildQueueClient() {
+ // BEGIN: com.azure.storage.queue.queueClient.instantiation
+ QueueClient client = new QueueClientBuilder()
+ .connectionString("connectionstring")
+ .endpoint("endpoint")
+ .buildClient();
+ // END: com.azure.storage.queue.queueClient.instantiation
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueAsyncClient}.
+ */
+ public void buildQueueAsyncClient() {
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation
+ QueueAsyncClient client = new QueueClientBuilder()
+ .connectionString("connectionstring")
+ .endpoint("endpoint")
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueAsyncClient.instantiation
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueClient} with {@link QueueClient}
+ * @return An instance of {@link QueueClient}
+ */
+ public QueueClient createClientWithSASToken() {
+ // BEGIN: com.azure.storage.queue.queueClient.instantiation.sastoken
+ QueueClient queueClient = new QueueClientBuilder()
+ .endpoint("https://${accountName}.queue.core.windows.net?${SASToken}")
+ .buildClient();
+ // END: com.azure.storage.queue.queueClient.instantiation.sastoken
+ return queueClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueAsyncClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueAsyncClient}
+ */
+ public QueueAsyncClient createAsyncClientWithSASToken() {
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.sastoken
+ QueueAsyncClient queueAsyncClient = new QueueClientBuilder()
+ .endpoint("https://{accountName}.queue.core.windows.net?{SASToken}")
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueAsyncClient.instantiation.sastoken
+ return queueAsyncClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueClient}
+ */
+ public QueueClient createClientWithCredential() {
+ // BEGIN: com.azure.storage.queue.queueClient.instantiation.credential
+ QueueClient queueClient = new QueueClientBuilder()
+ .endpoint("https://${accountName}.queue.core.windows.net")
+ .queueName("myqueue")
+ .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}"))
+ .buildClient();
+ // END: com.azure.storage.queue.queueClient.instantiation.credential
+ return queueClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueAsyncClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueAsyncClient}
+ */
+ public QueueAsyncClient createAsyncClientWithCredential() {
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.credential
+ QueueAsyncClient queueAsyncClient = new QueueClientBuilder()
+ .endpoint("https://{accountName}.queue.core.windows.net")
+ .queueName("myqueue")
+ .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}"))
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueAsyncClient.instantiation.credential
+ return queueAsyncClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueClient} with {@code connectionString} which turns into {@link SharedKeyCredential}
+ * @return An instance of {@link QueueClient}
+ */
+ public QueueClient createClientWithConnectionString() {
+ // BEGIN: com.azure.storage.queue.queueClient.instantiation.connectionstring
+ String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};"
+ + "AccountKey={key};EndpointSuffix={core.windows.net}";
+ QueueClient queueClient = new QueueClientBuilder()
+ .connectionString(connectionString)
+ .buildClient();
+ // END: com.azure.storage.queue.queueClient.instantiation.connectionstring
+ return queueClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential}
+ * @return An instance of {@link QueueAsyncClient}
+ */
+ public QueueAsyncClient createAsyncClientWithConnectionString() {
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring
+ String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};"
+ + "AccountKey={key};EndpointSuffix={core.windows.net}";
+ QueueAsyncClient queueAsyncClient = new QueueClientBuilder()
+ .connectionString(connectionString)
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueAsyncClient.instantiation.connectionstring
+ return queueAsyncClient;
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#create()}
+ */
+ public void createQueue() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.create
+ VoidResponse response = queueClient.create();
+ System.out.println("Complete creating queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueClient.create
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#create()}
+ */
+ public void createQueueAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.create
+ queueAsyncClient.create().subscribe(
+ response -> { },
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete creating the queue!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.create
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#create(Map)}
+ */
+ public void createQueueMaxOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.create#map
+ VoidResponse response = queueClient.create(Collections.singletonMap("queue", "metadataMap"));
+ System.out.println("Complete creating queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueClient.create#map
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#create(Map)}
+ */
+ public void createQueueAsyncMaxOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.create#map
+ queueAsyncClient.create(Collections.singletonMap("queue", "metadataMap")).subscribe(
+ response -> { },
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete creating the queue!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.create#map
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#enqueueMessage(String)}
+ */
+ public void enqueueMessage() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.enqueueMessage#string
+ Response response = queueClient.enqueueMessage("hello msg");
+ System.out.println("Complete enqueuing the message with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueClient.enqueueMessage#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String)}
+ */
+ public void enqueueMessageAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string
+ queueAsyncClient.enqueueMessage("Hello, Azure").subscribe(
+ response -> { },
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete enqueuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#enqueueMessage(String, Duration, Duration)}
+ */
+ public void enqueueMessageWithTimeoutOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.enqueueMessage#string-duration-duration
+ EnqueuedMessage enqueuedMessage = queueClient.enqueueMessage("Hello, Azure",
+ Duration.ofSeconds(5), null).value();
+ System.out.printf("Message %s expires at %s", enqueuedMessage.messageId(), enqueuedMessage.expirationTime());
+ // END: com.azure.storage.queue.queueClient.enqueueMessage#string-duration-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String, Duration, Duration)}
+ */
+ public void enqueueMessageAsyncWithTimeoutOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string-duration-duration
+ queueAsyncClient.enqueueMessage("Hello, Azure",
+ Duration.ofSeconds(5), null).subscribe(
+ response -> System.out.printf("Message %s expires at %s", response.value().messageId(),
+ response.value().expirationTime()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete enqueuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.enqueueMessage#string-duration-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#enqueueMessage(String, Duration, Duration)}
+ */
+ public void enqueueMessageWithLiveTimeOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration
+ EnqueuedMessage enqueuedMessage = queueClient.enqueueMessage("Goodbye, Azure",
+ null, Duration.ofSeconds(5)).value();
+ System.out.printf("Message %s expires at %s", enqueuedMessage.messageId(), enqueuedMessage.expirationTime());
+ // END: com.azure.storage.queue.queueClient.enqueueMessageLiveTime#string-duration-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#enqueueMessage(String, Duration, Duration)}
+ */
+ public void enqueueMessageAsyncWithLiveTimeOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration
+ queueAsyncClient.enqueueMessage("Goodbye, Azure",
+ null, Duration.ofSeconds(5)).subscribe(
+ response -> System.out.printf("Message %s expires at %s", response.value().messageId(),
+ response.value().expirationTime()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete enqueuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.enqueueMessageLiveTime#string-duration-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#dequeueMessages()}
+ */
+ public void dequeueMessage() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages
+ queueClient.dequeueMessages().forEach(
+ dequeuedMessage -> {
+ System.out.println("Complete dequeuing the message: " + dequeuedMessage.messageText());
+ }
+ );
+ // END: com.azure.storage.queue.queueClient.dequeueMessages
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages()}
+ */
+ public void dequeueMessageAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages
+ queueAsyncClient.dequeueMessages().subscribe(
+ dequeuedMessage -> System.out.println("The message got from dequeue operation: "
+ + dequeuedMessage.messageText()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete dequeuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#dequeueMessages(Integer)}
+ */
+ public void dequeueMessageWithOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages#integer
+ for (DequeuedMessage dequeuedMessage : queueClient.dequeueMessages(5)) {
+ System.out.printf("Dequeued %s and it becomes visible at %s",
+ dequeuedMessage.messageId(), dequeuedMessage.timeNextVisible());
+ }
+ // END: com.azure.storage.queue.queueClient.dequeueMessages#integer
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages(Integer)}
+ */
+ public void dequeueMessageAsyncWithOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer
+ queueAsyncClient.dequeueMessages(5).subscribe(
+ dequeuedMessage -> System.out.println("The message got from dequeue operation: "
+ + dequeuedMessage.messageText()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete dequeuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#dequeueMessages(Integer, Duration)}
+ */
+ public void dequeueMessageMaxOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.dequeueMessages#integer-duration
+ for (DequeuedMessage dequeuedMessage : queueClient.dequeueMessages(5, Duration.ofSeconds(60))) {
+ System.out.printf("Dequeued %s and it becomes visible at %s",
+ dequeuedMessage.messageId(), dequeuedMessage.timeNextVisible());
+ }
+ // END: com.azure.storage.queue.queueClient.dequeueMessages#integer-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#dequeueMessages(Integer, Duration)}
+ */
+ public void dequeueMessageAsyncMaxOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration
+ queueAsyncClient.dequeueMessages(5, Duration.ofSeconds(60)).subscribe(
+ dequeuedMessage -> System.out.println("The message got from dequeue operation: "
+ + dequeuedMessage.messageText()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete dequeuing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.dequeueMessages#integer-duration
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#peekMessages()}
+ */
+ public void peekMessage() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.peekMessages
+ queueClient.peekMessages().forEach(
+ peekedMessage -> {
+ System.out.println("Complete peeking the message: " + peekedMessage.messageText());
+ }
+ );
+ // END: com.azure.storage.queue.queueClient.peekMessages
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#peekMessages()}
+ */
+ public void peekMessageAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.peekMessages
+ queueAsyncClient.peekMessages().subscribe(
+ peekMessages -> System.out.println("The message got from peek operation: " + peekMessages.messageText()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete peeking the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.peekMessages
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#peekMessages(Integer)}
+ */
+ public void peekMessageMaxOverload() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.peekMessages#integer
+ queueClient.peekMessages(5).forEach(
+ peekMessage -> System.out.printf("Peeked message %s has been dequeued %d times",
+ peekMessage.messageId(), peekMessage.dequeueCount())
+ );
+ // END: com.azure.storage.queue.queueClient.peekMessages#integer
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#peekMessages(Integer)}
+ */
+ public void peekMessageAsyncMaxOverload() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.peekMessages#integer
+ queueAsyncClient.peekMessages(5).subscribe(
+ peekMessage -> System.out.printf("Peeked message %s has been dequeued %d times",
+ peekMessage.messageId(), peekMessage.dequeueCount()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete peeking the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.peekMessages#integer
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#updateMessage(String, String, String, Duration)}
+ */
+ public void updateMessage() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.updateMessage
+ queueClient.dequeueMessages().forEach(
+ dequeuedMessage -> {
+ Response response = queueClient.updateMessage("newText",
+ dequeuedMessage.messageId(), dequeuedMessage.popReceipt(), null);
+ System.out.println("Complete updating the message with status code " + response.statusCode());
+ }
+ );
+ // END: com.azure.storage.queue.queueClient.updateMessage
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#updateMessage(String, String, String, Duration)}
+ */
+ public void updateMessageAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.updateMessage
+ queueAsyncClient.dequeueMessages().subscribe(
+ dequeuedMessage -> {
+ queueAsyncClient.updateMessage("newText", dequeuedMessage.messageId(),
+ dequeuedMessage.popReceipt(), null).subscribe(
+ response -> { },
+ updateError -> System.err.print(updateError.toString()),
+ () -> System.out.println("Complete updating the message!")
+ );
+ },
+ dequeueError -> System.err.print(dequeueError.toString()),
+ () -> System.out.println("Complete dequeueing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.updateMessage
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#deleteMessage(String, String)}
+ */
+ public void deleteMessage() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.deleteMessage
+ queueClient.dequeueMessages().forEach(
+ dequeuedMessage -> {
+ VoidResponse response = queueClient.deleteMessage(dequeuedMessage.messageId(),
+ dequeuedMessage.popReceipt());
+ System.out.println("Complete deleting the message with status code " + response.statusCode());
+ }
+ );
+ // END: com.azure.storage.queue.queueClient.deleteMessage
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#deleteMessage(String, String)}
+ */
+ public void deleteMessageAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.deleteMessage
+ queueAsyncClient.dequeueMessages().subscribe(
+ dequeuedMessage -> {
+ queueAsyncClient.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt()).subscribe(
+ response -> { },
+ deleteError -> System.err.print(deleteError.toString()),
+ () -> System.out.println("Complete deleting the message!")
+ );
+ },
+ dequeueError -> System.err.print(dequeueError.toString()),
+ () -> System.out.println("Complete dequeueing the message!")
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.deleteMessage
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#delete()}
+ */
+ public void deleteQueue() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.delete
+ VoidResponse response = queueClient.delete();
+ System.out.println("Complete deleting the queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueClient.delete
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#delete()}
+ */
+ public void deleteQueueAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.delete
+ queueAsyncClient.delete().subscribe(
+ response -> System.out.println("Deleting the queue completed with status code: " + response.statusCode())
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.delete
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#getProperties()}
+ */
+ public void getProperties() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.getProperties
+ QueueProperties properties = queueClient.getProperties().value();
+ System.out.printf("Metadata: %s, Approximate message count: %d", properties.metadata(),
+ properties.approximateMessagesCount());
+ // END: com.azure.storage.queue.queueClient.getProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#getProperties()}
+ */
+ public void getPropertiesAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.getProperties
+ queueAsyncClient.getProperties()
+ .subscribe(response -> {
+ QueueProperties properties = response.value();
+ System.out.printf("Metadata: %s, Approximate message count: %d", properties.metadata(),
+ properties.approximateMessagesCount());
+ });
+ // END: com.azure.storage.queue.queueAsyncClient.getProperties
+ }
+
+ /**
+ * Generate a code sample for using {@link QueueClient#setMetadata(Map)} to set metadata.
+ */
+ public void setMetadata() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.setMetadata#map
+ VoidResponse response = queueClient.setMetadata(Collections.singletonMap("queue", "metadataMap"));
+ System.out.printf("Setting metadata completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueClient.setMetadata#map
+ }
+
+ /**
+ * Generate a code sample for using {@link QueueAsyncClient#setMetadata(Map)} to set metadata.
+ */
+ public void setMetadataAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.setMetadata#map
+ queueAsyncClient.setMetadata(Collections.singletonMap("queue", "metadataMap"))
+ .subscribe(response -> System.out.printf("Setting metadata completed with status code %d",
+ response.statusCode()));
+ // END: com.azure.storage.queue.queueAsyncClient.setMetadata#map
+ }
+
+ /**
+ * Generate a code sample for using {@link QueueClient#setMetadata(Map)} to clear metadata.
+ */
+ public void clearMetadata() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.clearMetadata#map
+ VoidResponse response = queueClient.setMetadata(null);
+ System.out.printf("Clearing metadata completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueClient.clearMetadata#map
+ }
+
+ /**
+ * Generate a code sample for using {@link QueueAsyncClient#setMetadata(Map)} to clear metadata.
+ */
+ public void clearMetadataAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.clearMetadata#map
+ queueAsyncClient.setMetadata(null)
+ .subscribe(response -> System.out.printf("Clearing metadata completed with status code %d",
+ response.statusCode()));
+ // END: com.azure.storage.queue.queueAsyncClient.clearMetadata#map
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#getAccessPolicy()}
+ */
+ public void getAccessPolicy() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.getAccessPolicy
+ for (SignedIdentifier permission : queueClient.getAccessPolicy()) {
+ System.out.printf("Access policy %s allows these permissions: %s", permission.id(),
+ permission.accessPolicy().permission());
+ }
+ // END: com.azure.storage.queue.queueClient.getAccessPolicy
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#getAccessPolicy()}
+ */
+ public void getAccessPolicyAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.getAccessPolicy
+ queueAsyncClient.getAccessPolicy()
+ .subscribe(result -> System.out.printf("Access policy %s allows these permissions: %s",
+ result.id(), result.accessPolicy().permission()));
+ // END: com.azure.storage.queue.queueAsyncClient.getAccessPolicy
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#setAccessPolicy(List)}
+ */
+ public void setAccessPolicy() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.setAccessPolicy
+ AccessPolicy accessPolicy = new AccessPolicy().permission("r")
+ .start(OffsetDateTime.now(ZoneOffset.UTC))
+ .expiry(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10));
+ SignedIdentifier permission = new SignedIdentifier().id("mypolicy").accessPolicy(accessPolicy);
+ VoidResponse response = queueClient.setAccessPolicy(Collections.singletonList(permission));
+ System.out.printf("Setting access policies completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueClient.setAccessPolicy
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#setAccessPolicy(List)}
+ */
+ public void setAccessPolicyAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.setAccessPolicy
+ AccessPolicy accessPolicy = new AccessPolicy().permission("r")
+ .start(OffsetDateTime.now(ZoneOffset.UTC))
+ .expiry(OffsetDateTime.now(ZoneOffset.UTC).plusDays(10));
+
+ SignedIdentifier permission = new SignedIdentifier().id("mypolicy").accessPolicy(accessPolicy);
+ queueAsyncClient.setAccessPolicy(Collections.singletonList(permission))
+ .subscribe(response -> System.out.printf("Setting access policies completed with status code %d",
+ response.statusCode()));
+ // END: com.azure.storage.queue.queueAsyncClient.setAccessPolicy
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueClient#clearMessages()}
+ */
+ public void clearMessages() {
+ QueueClient queueClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueClient.clearMessages
+ VoidResponse response = queueClient.clearMessages();
+ System.out.printf("Clearing messages completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueClient.clearMessages
+ }
+
+
+ /**
+ * Generates a code sample for using {@link QueueAsyncClient#clearMessages()}
+ */
+ public void clearMessagesAsync() {
+ QueueAsyncClient queueAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueAsyncClient.clearMessages
+ queueAsyncClient.clearMessages().subscribe(
+ response -> System.out.println("Clearing messages completed with status code: " + response.statusCode())
+ );
+ // END: com.azure.storage.queue.queueAsyncClient.clearMessages
+ }
+
+}
diff --git a/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java
new file mode 100644
index 0000000000000..3ed03621fbf76
--- /dev/null
+++ b/storage/client/queue/src/samples/java/com/azure/storage/queue/javadoc/QueueServiceJavaDocCodeSamples.java
@@ -0,0 +1,369 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue.javadoc;
+
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.storage.common.credentials.SASTokenCredential;
+import com.azure.storage.common.credentials.SharedKeyCredential;
+import com.azure.storage.queue.QueueClient;
+import com.azure.storage.queue.QueueServiceAsyncClient;
+import com.azure.storage.queue.QueueServiceClient;
+import com.azure.storage.queue.QueueServiceClientBuilder;
+import com.azure.storage.queue.models.QueuesSegmentOptions;
+import com.azure.storage.queue.models.StorageServiceProperties;
+import com.azure.storage.queue.models.StorageServiceStats;
+import java.util.Collections;
+import java.util.Map;
+
+/**
+ * Contains code snippets when generating javadocs through doclets for {@link QueueServiceClient} and {@link QueueServiceAsyncClient}.
+ */
+public class QueueServiceJavaDocCodeSamples {
+ /**
+ * Generates code sample for creating a {@link QueueServiceClient}.
+ */
+ public void buildQueueServiceClient() {
+ // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation
+ QueueServiceClient client = new QueueServiceClientBuilder()
+ .connectionString("connectionstring")
+ .endpoint("endpoint")
+ .buildClient();
+ // END: com.azure.storage.queue.queueServiceClient.instantiation
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceAsyncClient}.
+ */
+ public void buildQueueServiceAsyncClient() {
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation
+ QueueServiceAsyncClient client = new QueueServiceClientBuilder()
+ .connectionString("connectionstring")
+ .endpoint("endpoint")
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueServiceClient}
+ */
+ public QueueServiceClient createClientWithSASToken() {
+ // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.sastoken
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
+ .endpoint("https://${accountName}.queue.core.windows.net?${SASToken}")
+ .buildClient();
+ // END: com.azure.storage.queue.queueServiceClient.instantiation.sastoken
+ return queueServiceClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueServiceAsyncClient}
+ */
+ public QueueServiceAsyncClient createAsyncClientWithSASToken() {
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.sastoken
+ QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder()
+ .endpoint("https://{accountName}.queue.core.windows.net?{SASToken}")
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.sastoken
+ return queueServiceAsyncClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueServiceClient}
+ */
+ public QueueServiceClient createClientWithCredential() {
+ // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.credential
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
+ .endpoint("https://${accountName}.queue.core.windows.net")
+ .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}"))
+ .buildClient();
+ // END: com.azure.storage.queue.queueServiceClient.instantiation.credential
+ return queueServiceClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@link SASTokenCredential}
+ * @return An instance of {@link QueueServiceAsyncClient}
+ */
+ public QueueServiceAsyncClient createAsyncClientWithCredential() {
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential
+ QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder()
+ .endpoint("https://{accountName}.queue.core.windows.net")
+ .credential(SASTokenCredential.fromQuery("{SASTokenQueryParams}"))
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.credential
+ return queueServiceAsyncClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceClient} with {@code connectionString} which turns into {@link SharedKeyCredential}
+ * @return An instance of {@link QueueServiceClient}
+ */
+ public QueueServiceClient createClientWithConnectionString() {
+ // BEGIN: com.azure.storage.queue.queueServiceClient.instantiation.connectionstring
+ String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};"
+ + "AccountKey={key};EndpointSuffix={core.windows.net}";
+ QueueServiceClient queueServiceClient = new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .buildClient();
+ // END: com.azure.storage.queue.queueServiceClient.instantiation.connectionstring
+ return queueServiceClient;
+ }
+
+ /**
+ * Generates code sample for creating a {@link QueueServiceAsyncClient} with {@code connectionString} which turns into {@link SharedKeyCredential}
+ * @return An instance of {@link QueueServiceAsyncClient}
+ */
+ public QueueServiceAsyncClient createAsyncClientWithConnectionString() {
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring
+ String connectionString = "DefaultEndpointsProtocol=https;AccountName={name};"
+ + "AccountKey={key};EndpointSuffix={core.windows.net}";
+ QueueServiceAsyncClient queueServiceAsyncClient = new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .buildAsyncClient();
+ // END: com.azure.storage.queue.queueServiceAsyncClient.instantiation.connectionstring
+ return queueServiceAsyncClient;
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#createQueue(String)}
+ */
+ public void createQueue() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.createQueue#string
+ Response response = queueServiceClient.createQueue("myqueue");
+ System.out.println("Complete creating queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueServiceClient.createQueue#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#createQueue(String)}
+ */
+ public void createQueueAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string
+ queueServiceAsyncClient.createQueue("myqueue").subscribe(
+ response -> { },
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete creating the queue!")
+ );
+ // END: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#createQueue(String, Map)}
+ */
+ public void createQueueMaxOverload() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.createQueue#string-map
+ Response response = queueServiceClient.createQueue("myqueue",
+ Collections.singletonMap("queue", "metadata"));
+ System.out.println("Complete creating queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueServiceClient.createQueue#string-map
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#createQueue(String, Map)}
+ */
+ public void createQueueAsyncMaxOverload() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map
+ queueServiceAsyncClient.createQueue("myqueue", Collections.singletonMap("queue", "metadata"))
+ .subscribe(
+ response -> System.out.printf("Creating the queue with status code %d", response.statusCode()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete creating the queue!")
+ );
+ // END: com.azure.storage.queue.queueServiceAsyncClient.createQueue#string-map
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#listQueues()}
+ */
+ public void listQueues() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.listQueues
+ queueServiceClient.listQueues().forEach(
+ queueItem -> System.out.printf("Queue %s exists in the account", queueItem.name())
+ );
+ // END: com.azure.storage.queue.queueServiceClient.listQueues
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#listQueues()}
+ */
+ public void listQueuesAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.listQueues
+ queueServiceAsyncClient.listQueues().subscribe(
+ queueItem -> System.out.printf("Queue %s exists in the account", queueItem.name()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete listing the queues!")
+ );
+ // END: com.azure.storage.queue.queueServiceAsyncClient.listQueues
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#listQueues(QueuesSegmentOptions)} )}
+ */
+ public void listQueuesWithOverload() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions
+ queueServiceClient.listQueues(new QueuesSegmentOptions().prefix("azure")).forEach(
+ queueItem -> System.out.printf("Queue %s exists in the account and has metadata %s",
+ queueItem.name(), queueItem.metadata())
+ );
+ // END: com.azure.storage.queue.queueServiceClient.listQueues#queueSergmentOptions
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#listQueues(QueuesSegmentOptions)}
+ */
+ public void listQueuesAsyncWithOverload() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.listQueues#queueSergmentOptions
+ queueServiceAsyncClient.listQueues(new QueuesSegmentOptions().prefix("azure")).subscribe(
+ queueItem -> System.out.printf("Queue %s exists in the account and has metadata %s",
+ queueItem.name(), queueItem.metadata()),
+ error -> System.err.print(error.toString()),
+ () -> System.out.println("Complete listing the queues!")
+ );
+ // END: com.azure.storage.queue.queueServiceAsyncClient.listQueues#queueSergmentOptions
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#deleteQueue(String)}
+ */
+ public void deleteQueue() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.deleteQueue#string
+ VoidResponse response = queueServiceClient.deleteQueue("myqueue");
+ System.out.println("Complete deleting the queue with status code: " + response.statusCode());
+ // END: com.azure.storage.queue.queueServiceClient.deleteQueue#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#deleteQueue(String)}
+ */
+ public void deleteQueueAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string
+ queueServiceAsyncClient.deleteQueue("myshare").subscribe(
+ response -> System.out.println("Deleting the queue completed with status code: " + response.statusCode())
+ );
+ // END: com.azure.storage.queue.queueServiceAsyncClient.deleteQueue#string
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#getProperties()}
+ */
+ public void getProperties() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.getProperties
+ StorageServiceProperties properties = queueServiceClient.getProperties().value();
+ System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b",
+ properties.hourMetrics().enabled(), properties.minuteMetrics().enabled());
+ // END: com.azure.storage.queue.queueServiceClient.getProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#getProperties()}
+ */
+ public void getPropertiesAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.getProperties
+ queueServiceAsyncClient.getProperties()
+ .subscribe(response -> {
+ StorageServiceProperties properties = response.value();
+ System.out.printf("Hour metrics enabled: %b, Minute metrics enabled: %b",
+ properties.hourMetrics().enabled(), properties.minuteMetrics().enabled());
+ });
+ // END: com.azure.storage.queue.queueServiceAsyncClient.getProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#setProperties(StorageServiceProperties)}
+ */
+ public void setProperties() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.setProperties#storageServiceProperties
+ StorageServiceProperties properties = queueServiceClient.getProperties().value();
+ properties.cors(Collections.emptyList());
+
+ VoidResponse response = queueServiceClient.setProperties(properties);
+ System.out.printf("Setting Queue service properties completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueServiceClient.setProperties#storageServiceProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#setProperties(StorageServiceProperties)}
+ */
+ public void setPropertiesAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.setProperties#storageServiceProperties
+ StorageServiceProperties properties = queueServiceAsyncClient.getProperties().block().value();
+ queueServiceAsyncClient.setProperties(properties)
+ .subscribe(response -> System.out.printf("Setting Queue service properties completed with status code %d",
+ response.statusCode()));
+ // END: com.azure.storage.queue.queueServiceAsyncClient.setProperties#storageServiceProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#setProperties(StorageServiceProperties)} with metrics enabled.
+ */
+ public void setPropertiesEnableMetrics() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties
+ StorageServiceProperties properties = queueServiceClient.getProperties().value();
+ properties.minuteMetrics().enabled(true);
+ properties.hourMetrics().enabled(true);
+ VoidResponse response = queueServiceClient.setProperties(properties);
+ System.out.printf("Setting Queue service properties completed with status code %d", response.statusCode());
+ // END: com.azure.storage.queue.queueServiceClient.setPropertiesEnableMetrics#storageServiceProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#setProperties(StorageServiceProperties)} with metrics enabled.
+ */
+ public void setPropertiesAsyncEnableMetrics() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties
+ StorageServiceProperties properties = queueServiceAsyncClient.getProperties().block().value();
+ properties.minuteMetrics().enabled(true);
+ properties.hourMetrics().enabled(true);
+ queueServiceAsyncClient.setProperties(properties)
+ .subscribe(response -> System.out.printf("Setting Queue service properties completed with status code %d",
+ response.statusCode()));
+ // END: com.azure.storage.queue.queueServiceAsyncClient.setPropertiesEnableMetrics#storageServiceProperties
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceClient#getStatistics()}
+ */
+ public void getStatistics() {
+ QueueServiceClient queueServiceClient = createClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceClient.getStatistics
+ StorageServiceStats stats = queueServiceClient.getStatistics().value();
+ System.out.printf("Geo replication status: %s, Last synced: %s",
+ stats.geoReplication().status(), stats.geoReplication().lastSyncTime());
+ // END: com.azure.storage.queue.queueServiceClient.getStatistics
+ }
+
+ /**
+ * Generates a code sample for using {@link QueueServiceAsyncClient#getStatistics()}
+ */
+ public void getStatisticsAsync() {
+ QueueServiceAsyncClient queueServiceAsyncClient = createAsyncClientWithSASToken();
+ // BEGIN: com.azure.storage.queue.queueServiceAsyncClient.getStatistics
+ queueServiceAsyncClient.getStatistics()
+ .subscribe(response -> {
+ StorageServiceStats stats = response.value();
+ System.out.printf("Geo replication status: %s, Last synced: %s",
+ stats.geoReplication().status(), stats.geoReplication().lastSyncTime());
+ });
+ // END: com.azure.storage.queue.queueServiceAsyncClient.getStatistics
+ }
+}
diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java
new file mode 100644
index 0000000000000..f658e2aff324b
--- /dev/null
+++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueAsyncClientTests.java
@@ -0,0 +1,695 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.queue.models.AccessPolicy;
+import com.azure.storage.queue.models.DequeuedMessage;
+import com.azure.storage.queue.models.SignedIdentifier;
+import com.azure.storage.queue.models.StorageErrorException;
+import reactor.test.StepVerifier;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+public class QueueAsyncClientTests extends QueueClientTestsBase {
+ private final ClientLogger logger = new ClientLogger(QueueAsyncClientTests.class);
+
+ private QueueAsyncClient client;
+
+ @Override
+ protected void beforeTest() {
+ queueName = getQueueName();
+ helper = new TestHelpers();
+
+ if (interceptorManager.isPlaybackMode()) {
+ client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .queueName(queueName)
+ .httpClient(interceptorManager.getPlaybackClient())
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .buildAsyncClient(), true, logger);
+ } else {
+ client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .queueName(queueName)
+ .httpClient(HttpClient.createDefault().wiretap(true))
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .addPolicy(interceptorManager.getRecordPolicy())
+ .buildAsyncClient(), false, logger);
+ }
+ }
+
+ @Override
+ protected void afterTest() {
+ try {
+ client.clearMessages().block();
+ client.delete().block();
+ } catch (StorageErrorException ex) {
+ // Queue already delete, that's what we wanted anyways.
+ }
+ }
+
+ @Override
+ public void createWithSharedKey() {
+
+ }
+
+ @Override
+ public void createWithSASToken() {
+ // Need to find a way to get SAS tokens from the storage account
+ }
+
+ @Override
+ public void createWithMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void createTwiceSameMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.create(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+ }
+
+ @Override
+ public void createTwiceDifferentMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.create(metadata))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 409));
+ }
+
+ @Override
+ public void deleteExisting() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.enqueueMessage("This queue will be deleted"))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.delete())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ helper.sleepInRecordMode(Duration.ofSeconds(30));
+
+ StepVerifier.create(client.enqueueMessage("This should fail"))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void deleteNonExistent() {
+ StepVerifier.create(client.delete())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void getProperties() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void getPropertiesQueueDoesNotExist() {
+ StepVerifier.create(client.getProperties())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void setMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.setMetadata(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void setMetadataQueueDoesNotExist() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.setMetadata(metadata))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void setInvalidMetadata() {
+ Map badMetadata = Collections.singletonMap("", "bad metadata");
+
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.setMetadata(badMetadata))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void deleteMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(client.create(metadata))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ })
+ .verifyComplete();
+
+ StepVerifier.create(client.setMetadata(null))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(Collections.EMPTY_MAP, response.value().metadata());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void getAccessPolicy() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.getAccessPolicy())
+ .expectNextCount(0)
+ .verifyComplete();
+ }
+
+ @Override
+ public void getAccessPolicyQueueDoesNotExist() {
+ StepVerifier.create(client.getAccessPolicy())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void setAccessPolicy() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("raup")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("testpermission")
+ .accessPolicy(accessPolicy);
+
+ StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission)))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.getAccessPolicy())
+ .assertNext(response -> helper.assertPermissionsAreEqual(permission, response))
+ .verifyComplete();
+ }
+
+ @Override
+ public void setAccessPolicyQueueDoesNotExist() {
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.now())
+ .expiry(OffsetDateTime.now());
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("test-permission")
+ .accessPolicy(accessPolicy);
+
+ StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission)))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void setInvalidAccessPolicy() {
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("theidofthispermissionislongerthanwhatisallowedbytheserviceandshouldfail")
+ .accessPolicy(accessPolicy);
+
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.setAccessPolicy(Collections.singletonList(permission)))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void setTooManyAccessPolicies() {
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ List permissions = new ArrayList<>();
+ for (int i = 0; i < 6; i++) {
+ permissions.add(new SignedIdentifier()
+ .id("policy" + i)
+ .accessPolicy(accessPolicy));
+ }
+
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.setAccessPolicy(permissions))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void enqueueMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages())
+ .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void enqueueEmptyMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages())
+ .assertNext(peekedMessage -> assertNull(peekedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void enqueueShortTimeToLiveMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofSeconds(2)))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages().delaySubscription(Duration.ofSeconds(5)))
+ .expectNextCount(0)
+ .verifyComplete();
+ }
+
+ @Override
+ public void enqueueQueueDoesNotExist() {
+ StepVerifier.create(client.enqueueMessage("this should fail"))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void dequeueMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.dequeueMessages())
+ .assertNext(dequeuedMessage -> assertEquals(messageText, dequeuedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void dequeueMultipleMessages() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ String messageText2 = "test message 2";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.enqueueMessage(messageText2))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.dequeueMessages(2))
+ .assertNext(dequeuedMessage -> assertEquals(messageText, dequeuedMessage.messageText()))
+ .assertNext(dequeuedMessage -> assertEquals(messageText2, dequeuedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void dequeueTooManyMessages() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.dequeueMessages(64))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void dequeueQueueDoesNotExist() {
+ StepVerifier.create(client.dequeueMessages())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void peekMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages())
+ .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void peekMultipleMessages() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ String messageText2 = "test message 2";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.enqueueMessage(messageText2))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages(2))
+ .assertNext(peekedMessage -> assertEquals(messageText, peekedMessage.messageText()))
+ .assertNext(peekedMessage -> assertEquals(messageText2, peekedMessage.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void peekTooManyMessages() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages(64))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void peekQueueDoesNotExist() {
+ StepVerifier.create(client.peekMessages())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void clearMessages() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.enqueueMessage("test message"))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+ StepVerifier.create(client.enqueueMessage("test message"))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+ StepVerifier.create(client.enqueueMessage("test message"))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(3, response.value().approximateMessagesCount());
+ })
+ .verifyComplete();
+
+ StepVerifier.create(client.clearMessages())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void clearMessagesQueueDoesNotExist() {
+ StepVerifier.create(client.clearMessages())
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void deleteMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst();
+ assertEquals(messageText, dequeuedMessage.messageText());
+ StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt()))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void deleteMessageInvalidMessageId() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = new DequeuedMessage();
+ StepVerifier.create(client.dequeueMessages())
+ .assertNext(response -> {
+ assertEquals(messageText, response.messageText());
+ dequeuedMessage.popReceipt(response.popReceipt()).messageId(response.messageId());
+ })
+ .verifyComplete();
+
+ StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId() + "random", dequeuedMessage.popReceipt()))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void deleteMessageInvalidPopReceipt() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = new DequeuedMessage();
+ StepVerifier.create(client.dequeueMessages())
+ .assertNext(response -> {
+ assertEquals(messageText, response.messageText());
+ dequeuedMessage.popReceipt(response.popReceipt()).messageId(response.messageId());
+ })
+ .verifyComplete();
+
+ StepVerifier.create(client.deleteMessage(dequeuedMessage.messageId(), dequeuedMessage.popReceipt() + "random"))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void deleteMessageQueueDoesNotExist() {
+ StepVerifier.create(client.deleteMessage("invalid", "call"))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void updateMessage() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst();
+ assertEquals(messageText, dequeuedMessage.messageText());
+
+ String updatedMessageText = "updated test message";
+ StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId(), dequeuedMessage.popReceipt(), Duration.ofSeconds(1)))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 204))
+ .verifyComplete();
+
+ StepVerifier.create(client.peekMessages().delaySubscription(Duration.ofSeconds(2)))
+ .assertNext(response -> assertEquals(updatedMessageText, response.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void updateMessageInvalidMessageId() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst();
+ assertEquals(messageText, dequeuedMessage.messageText());
+
+ String updatedMessageText = "updated test message";
+ StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId() + "random", dequeuedMessage.popReceipt(), Duration.ofSeconds(1)))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 404));
+ }
+
+ @Override
+ public void updateMessageInvalidPopReceipt() {
+ StepVerifier.create(client.create())
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ String messageText = "test message";
+ StepVerifier.create(client.enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ DequeuedMessage dequeuedMessage = client.dequeueMessages().blockFirst();
+ assertEquals(messageText, dequeuedMessage.messageText());
+
+ String updatedMessageText = "updated test message";
+ StepVerifier.create(client.updateMessage(updatedMessageText, dequeuedMessage.messageId(), dequeuedMessage.popReceipt() + "random", Duration.ofSeconds(1)))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+
+ @Override
+ public void updateMessageQueueDoesNotExist() {
+ StepVerifier.create(client.updateMessage("queue", "doesn't", "exist", Duration.ofSeconds(5)))
+ .verifyErrorSatisfies(throwable -> helper.assertExceptionStatusCode(throwable, 400));
+ }
+}
diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java
new file mode 100644
index 0000000000000..c0da15213d8c7
--- /dev/null
+++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTests.java
@@ -0,0 +1,654 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.http.rest.Response;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.queue.models.AccessPolicy;
+import com.azure.storage.queue.models.DequeuedMessage;
+import com.azure.storage.queue.models.PeekedMessage;
+import com.azure.storage.queue.models.QueueProperties;
+import com.azure.storage.queue.models.SignedIdentifier;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.UpdatedMessage;
+
+import java.time.Duration;
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneOffset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.fail;
+
+public class QueueClientTests extends QueueClientTestsBase {
+ private final ClientLogger logger = new ClientLogger(QueueClientTests.class);
+
+ private QueueClient client;
+
+ @Override
+ protected void beforeTest() {
+ queueName = getQueueName();
+ helper = new TestHelpers();
+
+ if (interceptorManager.isPlaybackMode()) {
+ client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .queueName(queueName)
+ .httpClient(interceptorManager.getPlaybackClient())
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .buildClient(), true, logger);
+ } else {
+ client = helper.setupClient((connectionString, endpoint) -> new QueueClientBuilder()
+ .endpoint(endpoint)
+ .queueName(queueName)
+ .httpClient(HttpClient.createDefault().wiretap(true))
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .addPolicy(interceptorManager.getRecordPolicy())
+ .buildClient(), false, logger);
+ }
+ }
+
+ @Override
+ protected void afterTest() {
+ try {
+ client.clearMessages();
+ client.delete();
+ } catch (StorageErrorException ex) {
+ // Queue already delete, that's what we wanted anyways.
+ }
+ }
+
+ @Override
+ public void createWithSharedKey() {
+
+ }
+
+ @Override
+ public void createWithSASToken() {
+ // Need to find a way to get SAS tokens from the storage account
+ }
+
+ @Override
+ public void createWithMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(metadata), 201);
+
+ QueueProperties properties = client.getProperties().value();
+ assertEquals(metadata, properties.metadata());
+ }
+
+ @Override
+ public void createTwiceSameMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(metadata), 201);
+ helper.assertResponseStatusCode(client.create(metadata), 204);
+ }
+
+ @Override
+ public void createTwiceDifferentMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ try {
+ client.create(metadata);
+ fail("Creating a queue twice with different metadata values should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 409);
+ }
+ }
+
+ @Override
+ public void deleteExisting() {
+ helper.assertResponseStatusCode(client.create(), 201);
+ helper.assertResponseStatusCode(client.enqueueMessage("This queue will be deleted"), 201);
+ helper.assertResponseStatusCode(client.delete(), 204);
+
+ helper.sleepInRecordMode(Duration.ofSeconds(30));
+
+ try {
+ client.enqueueMessage("This should fail");
+ fail("Attempting to work with a queue that has been deleted should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void deleteNonExistent() {
+ try {
+ client.delete();
+ fail("Attempting to delete a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void getProperties() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(metadata), 201);
+
+ Response response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ }
+
+ @Override
+ public void getPropertiesQueueDoesNotExist() {
+ try {
+ client.getProperties();
+ fail("Attempting to get properties of a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void setMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ helper.assertResponseStatusCode(client.setMetadata(metadata), 204);
+
+ Response response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+ }
+
+ @Override
+ public void setMetadataQueueDoesNotExist() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ try {
+ client.setMetadata(metadata);
+ fail("Attempting to set metadata on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void setInvalidMetadata() {
+ Map badMetadata = Collections.singletonMap("", "bad metadata");
+
+ helper.assertResponseStatusCode(client.create(), 201);
+ try {
+ client.setMetadata(badMetadata);
+ fail("Attempting to set invalid metadata on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void deleteMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ helper.assertResponseStatusCode(client.create(metadata), 201);
+
+ Response response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(metadata, response.value().metadata());
+
+ helper.assertResponseStatusCode(client.setMetadata(null), 204);
+
+ response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ assertEquals(Collections.EMPTY_MAP, response.value().metadata());
+ }
+
+ @Override
+ public void getAccessPolicy() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ Iterable accessPolicies = client.getAccessPolicy();
+ assertFalse(accessPolicies.iterator().hasNext());
+ }
+
+ @Override
+ public void getAccessPolicyQueueDoesNotExist() {
+ try {
+ client.getAccessPolicy().iterator().hasNext();
+ fail("Attempting to get access policies on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void setAccessPolicy() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("raup")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("testpermission")
+ .accessPolicy(accessPolicy);
+
+ helper.assertResponseStatusCode(client.setAccessPolicy(Collections.singletonList(permission)), 204);
+
+ Iterator accessPolicies = client.getAccessPolicy().iterator();
+ helper.assertPermissionsAreEqual(permission, accessPolicies.next());
+ assertFalse(accessPolicies.hasNext());
+ }
+
+ @Override
+ public void setAccessPolicyQueueDoesNotExist() {
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.now())
+ .expiry(OffsetDateTime.now());
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("test-permission")
+ .accessPolicy(accessPolicy);
+
+ try {
+ client.setAccessPolicy(Collections.singletonList(permission));
+ fail("Attempting to set access policies on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void setInvalidAccessPolicy() {
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ SignedIdentifier permission = new SignedIdentifier()
+ .id("theidofthispermissionislongerthanwhatisallowedbytheserviceandshouldfail")
+ .accessPolicy(accessPolicy);
+
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ try {
+ client.setAccessPolicy(Collections.singletonList(permission));
+ fail("Attempting to set invalid access policies on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void setTooManyAccessPolicies() {
+ List permissions = new ArrayList<>();
+
+ AccessPolicy accessPolicy = new AccessPolicy()
+ .permission("r")
+ .start(OffsetDateTime.of(LocalDateTime.of(2000, 1, 1, 0, 0), ZoneOffset.UTC))
+ .expiry(OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 0, 0), ZoneOffset.UTC));
+
+ for (int i = 0; i < 6; i++) {
+ permissions.add(new SignedIdentifier()
+ .id("policy" + i)
+ .accessPolicy(accessPolicy));
+ }
+
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ try {
+ client.setAccessPolicy(permissions);
+ fail("Attempting to set more than five access policies on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void enqueueMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.peekMessages().iterator();
+ assertEquals(messageText, response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void enqueueEmptyMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.peekMessages().iterator();
+ assertNull(response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void enqueueShortTimeToLiveMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText, Duration.ofSeconds(0), Duration.ofSeconds(2)), 201);
+
+ helper.sleepInRecordMode(Duration.ofSeconds(5));
+ Iterator response = client.peekMessages().iterator();
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void enqueueQueueDoesNotExist() {
+ try {
+ client.enqueueMessage("This should fail");
+ fail("Attempting to enqueue a message on a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void dequeueMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ assertEquals(messageText, response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void dequeueMultipleMessages() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ String messageText2 = "test message 2";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText2), 201);
+
+ Iterator response = client.dequeueMessages(2).iterator();
+ assertEquals(messageText, response.next().messageText());
+ assertEquals(messageText2, response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void dequeueTooManyMessages() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ try {
+ client.dequeueMessages(64).iterator().hasNext();
+ fail("Attempting to get more than 32 messages from a queue should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void dequeueQueueDoesNotExist() {
+ try {
+ client.dequeueMessages().iterator().hasNext();
+ fail("Attempting to get messages from a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void peekMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.peekMessages().iterator();
+ assertEquals(messageText, response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void peekMultipleMessages() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ String messageText2 = "test message 2";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText2), 201);
+
+ Iterator response = client.peekMessages(2).iterator();
+ assertEquals(messageText, response.next().messageText());
+ assertEquals(messageText2, response.next().messageText());
+ assertFalse(response.hasNext());
+ }
+
+ @Override
+ public void peekTooManyMessages() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ try {
+ client.peekMessages(64).iterator().hasNext();
+ fail("Attempting to peek more than 32 messages from a queue should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void peekQueueDoesNotExist() {
+ try {
+ client.peekMessages().iterator().hasNext();
+ fail("Attempting to peek messages from a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void clearMessages() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ for (int i = 0; i < 3; i++) {
+ helper.assertResponseStatusCode(client.enqueueMessage("test message"), 201);
+ }
+
+ Response response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(3, response.value().approximateMessagesCount());
+
+ helper.assertResponseStatusCode(client.clearMessages(), 204);
+
+ response = client.getProperties();
+ helper.assertResponseStatusCode(response, 200);
+ assertEquals(0, response.value().approximateMessagesCount());
+ }
+
+ @Override
+ public void clearMessagesQueueDoesNotExist() {
+ try {
+ client.clearMessages();
+ fail("Attempting to clear messages of a queue that doesn't exist should throw an exception");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void deleteMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertFalse(response.hasNext());
+ assertEquals(messageText, message.messageText());
+
+ helper.assertResponseStatusCode(client.deleteMessage(message.messageId(), message.popReceipt()), 204);
+
+ Response propertiesResponse = client.getProperties();
+ helper.assertResponseStatusCode(propertiesResponse, 200);
+ assertEquals(0, propertiesResponse.value().approximateMessagesCount());
+ }
+
+ @Override
+ public void deleteMessageInvalidMessageId() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertFalse(response.hasNext());
+ assertEquals(messageText, message.messageText());
+
+ try {
+ client.deleteMessage(message.messageId() + "random", message.popReceipt());
+ fail("Attempting to delete a message with an invalid ID should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void deleteMessageInvalidPopReceipt() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertFalse(response.hasNext());
+ assertEquals(messageText, message.messageText());
+
+ try {
+ client.deleteMessage(message.messageId(), message.popReceipt() + "random");
+ fail("Attempting to delete a message with an invalid popReceipt should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void deleteMessageQueueDoesNotExist() {
+ try {
+ client.deleteMessage("invalid", "call");
+ fail("Attempting to delete a message from a queue that doesn't exist should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void updateMessage() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertEquals(messageText, message.messageText());
+ assertFalse(response.hasNext());
+
+ String updatedMessageText = "updated test message";
+ Response updatedMessageResponse = client.updateMessage(updatedMessageText, message.messageId(), message.popReceipt(), Duration.ofSeconds(1));
+ helper.assertResponseStatusCode(updatedMessageResponse, 204);
+
+ helper.sleepInRecordMode(Duration.ofSeconds(2));
+
+ Iterator peekedMessageIterator = client.peekMessages().iterator();
+ PeekedMessage peekedMessage = peekedMessageIterator.next();
+ assertEquals(updatedMessageText, peekedMessage.messageText());
+ assertFalse(peekedMessageIterator.hasNext());
+ }
+
+ @Override
+ public void updateMessageInvalidMessageId() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertEquals(messageText, message.messageText());
+ assertFalse(response.hasNext());
+
+ String updatedMessageText = "updated test message";
+ try {
+ client.updateMessage(updatedMessageText, message.messageId() + "random", message.popReceipt(), Duration.ofSeconds(1));
+ fail("Attempting to update a message with an invalid ID should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void updateMessageInvalidPopReceipt() {
+ helper.assertResponseStatusCode(client.create(), 201);
+
+ String messageText = "test message";
+ helper.assertResponseStatusCode(client.enqueueMessage(messageText), 201);
+
+ Iterator response = client.dequeueMessages().iterator();
+ DequeuedMessage message = response.next();
+ assertEquals(messageText, message.messageText());
+ assertFalse(response.hasNext());
+
+ String updatedMessageText = "updated test message";
+ try {
+ client.updateMessage(updatedMessageText, message.messageId(), message.popReceipt() + "random", Duration.ofSeconds(1));
+ fail("Attempting to update a message with an invalid popReceipt should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+
+ @Override
+ public void updateMessageQueueDoesNotExist() {
+ try {
+ client.updateMessage("queue", "doesn't", "exist", Duration.ofSeconds(5));
+ fail("Attempting to update a message on a queue that doesn't exist should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 400);
+ }
+ }
+}
diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java
new file mode 100644
index 0000000000000..b83d9a1459bbc
--- /dev/null
+++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueClientTestsBase.java
@@ -0,0 +1,148 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.test.TestBase;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestName;
+
+public abstract class QueueClientTestsBase extends TestBase {
+ String queueName;
+ TestHelpers helper;
+
+ @Rule
+ public TestName testName = new TestName();
+
+ @Override
+ public String testName() {
+ return testName.getMethodName();
+ }
+
+ String getQueueName() {
+ return testResourceNamer.randomName("queue", 16).toLowerCase();
+ }
+
+ @Test
+ public abstract void createWithSharedKey();
+
+ @Test
+ public abstract void createWithSASToken();
+
+ @Test
+ public abstract void createWithMetadata();
+
+ @Test
+ public abstract void createTwiceSameMetadata();
+
+ @Test
+ public abstract void createTwiceDifferentMetadata();
+
+ @Test
+ public abstract void deleteExisting();
+
+ @Test
+ public abstract void deleteNonExistent();
+
+ @Test
+ public abstract void getProperties();
+
+ @Test
+ public abstract void getPropertiesQueueDoesNotExist();
+
+ @Test
+ public abstract void setMetadata();
+
+ @Test
+ public abstract void setMetadataQueueDoesNotExist();
+
+ @Test
+ public abstract void setInvalidMetadata();
+
+ @Test
+ public abstract void deleteMetadata();
+
+ @Test
+ public abstract void getAccessPolicy();
+
+ @Test
+ public abstract void getAccessPolicyQueueDoesNotExist();
+
+ @Test
+ public abstract void setAccessPolicy();
+
+ @Test
+ public abstract void setAccessPolicyQueueDoesNotExist();
+
+ @Test
+ public abstract void setInvalidAccessPolicy();
+
+ @Test
+ public abstract void setTooManyAccessPolicies();
+
+ @Test
+ public abstract void enqueueMessage();
+
+ @Test
+ public abstract void enqueueEmptyMessage();
+
+ @Test
+ public abstract void enqueueShortTimeToLiveMessage();
+
+ @Test
+ public abstract void enqueueQueueDoesNotExist();
+
+ @Test
+ public abstract void dequeueMessage();
+
+ @Test
+ public abstract void dequeueMultipleMessages();
+
+ @Test
+ public abstract void dequeueTooManyMessages();
+
+ @Test
+ public abstract void dequeueQueueDoesNotExist();
+
+ @Test
+ public abstract void peekMessage();
+
+ @Test
+ public abstract void peekMultipleMessages();
+
+ @Test
+ public abstract void peekTooManyMessages();
+
+ @Test
+ public abstract void peekQueueDoesNotExist();
+
+ @Test
+ public abstract void clearMessages();
+
+ @Test
+ public abstract void clearMessagesQueueDoesNotExist();
+
+ @Test
+ public abstract void deleteMessage();
+
+ @Test
+ public abstract void deleteMessageInvalidMessageId();
+
+ @Test
+ public abstract void deleteMessageInvalidPopReceipt();
+
+ @Test
+ public abstract void deleteMessageQueueDoesNotExist();
+
+ @Test
+ public abstract void updateMessage();
+
+ @Test
+ public abstract void updateMessageInvalidMessageId();
+
+ @Test
+ public abstract void updateMessageInvalidPopReceipt();
+
+ @Test
+ public abstract void updateMessageQueueDoesNotExist();
+}
diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java
new file mode 100644
index 0000000000000..8d0b89aa9be07
--- /dev/null
+++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceAsyncClientTests.java
@@ -0,0 +1,250 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.queue.models.Logging;
+import com.azure.storage.queue.models.Metrics;
+import com.azure.storage.queue.models.QueueItem;
+import com.azure.storage.queue.models.QueuesSegmentOptions;
+import com.azure.storage.queue.models.RetentionPolicy;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.StorageServiceProperties;
+import reactor.test.StepVerifier;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+
+public class QueueServiceAsyncClientTests extends QueueServiceClientTestsBase {
+ private final ClientLogger logger = new ClientLogger(QueueServiceAsyncClientTests.class);
+
+ private QueueServiceAsyncClient serviceClient;
+
+ @Override
+ protected void beforeTest() {
+ queueName = getQueueName();
+ helper = new TestHelpers();
+
+ if (interceptorManager.isPlaybackMode()) {
+ serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .httpClient(interceptorManager.getPlaybackClient())
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .buildAsyncClient(), true, logger);
+ } else {
+ serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .httpClient(HttpClient.createDefault().wiretap(true))
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .addPolicy(interceptorManager.getRecordPolicy())
+ .buildAsyncClient(), false, logger);
+ }
+ }
+
+ @Override
+ protected void afterTest() {
+ serviceClient.listQueues(new QueuesSegmentOptions().prefix(queueName))
+ .collectList()
+ .block()
+ .forEach(queue -> {
+ QueueAsyncClient client = serviceClient.getQueueAsyncClient(queue.name());
+ try {
+ client.clearMessages().then(client.delete()).block();
+ } catch (StorageErrorException ex) {
+ // Queue already delete, that's what we wanted anyways.
+ }
+ });
+ }
+
+ @Override
+ public void getQueueDoesNotCreateAQueue() {
+ StepVerifier.create(serviceClient.getQueueAsyncClient(queueName).enqueueMessage("Expecting an exception"));
+ }
+
+ @Override
+ public void createQueue() {
+ StepVerifier.create(serviceClient.createQueue(queueName).block().value().enqueueMessage("Testing service client creating a queue"))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+ }
+
+ @Override
+ public void createQueueWithMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+ QueueAsyncClient client = serviceClient.createQueue(queueName, metadata).block().value();
+
+ StepVerifier.create(client.getProperties())
+ .assertNext(response -> {
+ assertEquals(metadata, response.value().metadata());
+ })
+ .verifyComplete();
+ }
+
+ @Override
+ public void createQueueTwiceSameMetadata() {
+ final String messageText = "Testing service client creating the same queue twice does not modify the queue";
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ StepVerifier.create(serviceClient.createQueue(queueName, metadata).block().value().enqueueMessage(messageText))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 201))
+ .verifyComplete();
+
+ StepVerifier.create(serviceClient.createQueue(queueName, metadata).block().value().peekMessages())
+ .assertNext(response -> assertEquals(messageText, response.messageText()))
+ .verifyComplete();
+ }
+
+ @Override
+ public void createQueueTwiceDifferentMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ try {
+ serviceClient.createQueue(queueName);
+ serviceClient.createQueue(queueName, metadata);
+ } catch (Exception exception) {
+ }
+ }
+
+ @Override
+ public void deleteExistingQueue() {
+ QueueAsyncClient client = serviceClient.createQueue(queueName).block().value();
+ serviceClient.deleteQueue(queueName).block();
+
+ StepVerifier.create(client.enqueueMessage("Expecting an exception"));
+ }
+
+ @Override
+ public void deleteNonExistentQueue() {
+ try {
+ serviceClient.deleteQueue(queueName);
+ } catch (Exception exception) {
+ }
+ }
+
+ @Override
+ public void listQueues() {
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem().name(queueName + i);
+ testQueues.add(queue);
+ serviceClient.createQueue(queue.name(), queue.metadata()).block();
+ }
+
+ StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions()))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .verifyComplete();
+ }
+
+ @Override
+ public void listQueuesIncludeMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem().name(queueName + i);
+ if (i % 2 == 0) {
+ queue.metadata(metadata);
+ }
+
+ testQueues.add(queue);
+ serviceClient.createQueue(queue.name(), queue.metadata()).block();
+ }
+
+ StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().includeMetadata(true)))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .verifyComplete();
+ }
+
+ @Override
+ public void listQueuesWithPrefix() {
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem();
+ if (i % 2 == 0) {
+ queue.name(queueName + "prefix" + i);
+ testQueues.add(queue);
+ } else {
+ queue.name(queueName + i);
+ }
+
+ serviceClient.createQueue(queue.name(), queue.metadata()).block();
+ }
+
+ StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().prefix(queueName + "prefix")))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .assertNext(result -> helper.assertQueuesAreEqual(testQueues.pop(), result))
+ .verifyComplete();
+ }
+
+ @Override
+ public void listQueuesWithLimit() {
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem().name(queueName + i);
+ testQueues.add(queue);
+ serviceClient.createQueue(queue.name(), queue.metadata()).block();
+ }
+
+ StepVerifier.create(serviceClient.listQueues(defaultSegmentOptions().maxResults(2)))
+ .verifyComplete();
+ }
+
+ @Override
+ public void setProperties() {
+ StorageServiceProperties originalProperties = serviceClient.getProperties().block().value();
+
+ RetentionPolicy retentionPolicy = new RetentionPolicy().enabled(true)
+ .days(3);
+
+ Logging logging = new Logging().version("1.0")
+ .delete(true)
+ .write(true)
+ .retentionPolicy(retentionPolicy);
+
+ Metrics metrics = new Metrics().enabled(true)
+ .includeAPIs(false)
+ .retentionPolicy(retentionPolicy)
+ .version("1.0");
+
+ StorageServiceProperties updatedProperties = new StorageServiceProperties().logging(logging)
+ .hourMetrics(metrics)
+ .minuteMetrics(metrics)
+ .cors(new ArrayList<>());
+
+ StepVerifier.create(serviceClient.setProperties(updatedProperties))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 202))
+ .verifyComplete();
+
+ StepVerifier.create(serviceClient.getProperties())
+ .assertNext(response -> helper.assertQueueServicePropertiesAreEqual(updatedProperties, response.value()))
+ .verifyComplete();
+
+ StepVerifier.create(serviceClient.setProperties(originalProperties))
+ .assertNext(response -> helper.assertResponseStatusCode(response, 202))
+ .verifyComplete();
+
+ StepVerifier.create(serviceClient.getProperties())
+ .assertNext(response -> helper.assertQueueServicePropertiesAreEqual(originalProperties, response.value()))
+ .verifyComplete();
+ }
+}
diff --git a/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java
new file mode 100644
index 0000000000000..c6587872c6fb7
--- /dev/null
+++ b/storage/client/queue/src/test/java/com/azure/storage/queue/QueueServiceClientTests.java
@@ -0,0 +1,257 @@
+// Copyright (c) Microsoft Corporation. All rights reserved.
+// Licensed under the MIT License.
+package com.azure.storage.queue;
+
+import com.azure.core.http.HttpClient;
+import com.azure.core.http.policy.HttpLogDetailLevel;
+import com.azure.core.http.rest.Response;
+import com.azure.core.http.rest.VoidResponse;
+import com.azure.core.util.logging.ClientLogger;
+import com.azure.storage.queue.models.EnqueuedMessage;
+import com.azure.storage.queue.models.Logging;
+import com.azure.storage.queue.models.Metrics;
+import com.azure.storage.queue.models.PeekedMessage;
+import com.azure.storage.queue.models.QueueItem;
+import com.azure.storage.queue.models.QueueProperties;
+import com.azure.storage.queue.models.QueuesSegmentOptions;
+import com.azure.storage.queue.models.RetentionPolicy;
+import com.azure.storage.queue.models.StorageErrorException;
+import com.azure.storage.queue.models.StorageServiceProperties;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.LinkedList;
+import java.util.Map;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.fail;
+
+public class QueueServiceClientTests extends QueueServiceClientTestsBase {
+ private final ClientLogger logger = new ClientLogger(QueueServiceClientTests.class);
+
+ private QueueServiceClient serviceClient;
+
+ @Override
+ protected void beforeTest() {
+ queueName = getQueueName();
+ helper = new TestHelpers();
+
+ if (interceptorManager.isPlaybackMode()) {
+ serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .httpClient(interceptorManager.getPlaybackClient())
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .buildClient(), true, logger);
+ } else {
+ serviceClient = helper.setupClient((connectionString, endpoint) -> new QueueServiceClientBuilder()
+ .connectionString(connectionString)
+ .endpoint(endpoint)
+ .httpClient(HttpClient.createDefault().wiretap(true))
+ .httpLogDetailLevel(HttpLogDetailLevel.BODY_AND_HEADERS)
+ .addPolicy(interceptorManager.getRecordPolicy())
+ .buildClient(), false, logger);
+ }
+ }
+
+ @Override
+ protected void afterTest() {
+ serviceClient.listQueues(new QueuesSegmentOptions().prefix(queueName))
+ .forEach(queueToDelete -> {
+ try {
+ QueueClient client = serviceClient.getQueueClient(queueToDelete.name());
+ client.clearMessages();
+ client.delete();
+ } catch (StorageErrorException ex) {
+ // Queue already delete, that's what we wanted anyways.
+ }
+ });
+ }
+
+ @Override
+ public void getQueueDoesNotCreateAQueue() {
+ try {
+ serviceClient.getQueueClient(queueName).enqueueMessage("Expecting an exception");
+ fail("getQueueClient doesn't create a queue in Azure Storage.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void createQueue() {
+ QueueClient client = serviceClient.createQueue(queueName).value();
+ Response response = client.enqueueMessage("Testing service client creating a queue");
+ helper.assertResponseStatusCode(response, 201);
+ }
+
+ @Override
+ public void createQueueWithMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+ QueueClient client = serviceClient.createQueue(queueName, metadata).value();
+
+ Response propertiesResponse = client.getProperties();
+ helper.assertResponseStatusCode(propertiesResponse, 200);
+ assertEquals(metadata, propertiesResponse.value().metadata());
+ }
+
+ @Override
+ public void createQueueTwiceSameMetadata() {
+ final String messageText = "Testing service client creating the same queue twice does not modify the queue";
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ EnqueuedMessage enqueuedMessage = serviceClient.createQueue(queueName, metadata).value().enqueueMessage(messageText).value();
+ assertNotNull(enqueuedMessage);
+
+ PeekedMessage peekedMessage = serviceClient.createQueue(queueName, metadata).value().peekMessages().iterator().next();
+ assertEquals(messageText, peekedMessage.messageText());
+ }
+
+ @Override
+ public void createQueueTwiceDifferentMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ try {
+ serviceClient.createQueue(queueName);
+ serviceClient.createQueue(queueName, metadata);
+ fail("Creating a queue twice with different metadata should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 409);
+ }
+ }
+
+ @Override
+ public void deleteExistingQueue() {
+ QueueClient client = serviceClient.createQueue(queueName).value();
+ serviceClient.deleteQueue(queueName);
+
+ try {
+ client.enqueueMessage("Expecting an exception");
+ fail("Attempting to enqueue a message on a client that has been delete should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void deleteNonExistentQueue() {
+ try {
+ serviceClient.deleteQueue(queueName);
+ fail("Attempting to delete a queue that doesn't exist should throw an exception.");
+ } catch (Exception exception) {
+ helper.assertExceptionStatusCode(exception, 404);
+ }
+ }
+
+ @Override
+ public void listQueues() {
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem().name(queueName + i);
+ testQueues.add(queue);
+ serviceClient.createQueue(queue.name(), queue.metadata());
+ }
+
+ for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions())) {
+ helper.assertQueuesAreEqual(testQueues.pop(), queue);
+ }
+ }
+
+ @Override
+ public void listQueuesIncludeMetadata() {
+ Map metadata = new HashMap<>();
+ metadata.put("metadata1", "value1");
+ metadata.put("metadata2", "value2");
+
+ LinkedList testQueues = new LinkedList<>();
+ for (int i = 0; i < 3; i++) {
+ QueueItem queue = new QueueItem().name(queueName + i);
+ if (i % 2 == 0) {
+ queue.metadata(metadata);
+ }
+
+ testQueues.add(queue);
+ serviceClient.createQueue(queue.name(), queue.metadata());
+ }
+
+ for (QueueItem queue : serviceClient.listQueues(defaultSegmentOptions().includeMetadata(true))) {
+ helper.assertQueuesAreEqual(testQueues.pop(), queue);
+ }
+ }
+
+ @Override
+ public void listQueuesWithPrefix() {
+ LinkedList