# Storage Queue Service SDK Migration Guide from 8.x to 12.x
In this section, we list the main changes you need to be aware of when converting your Storage Queue SDK library from Version 8 to Version 12.
For more info of the motivation behind this major change, please refer to [this guide](https://github.com/Azure/azure-storage-java/blob/master/V12%20Upgrade%20Story.md).
## Prerequisites
Java Development Kit (JDK) with version 8 or above
## Converting Core Classes
Our core synchronous classes have been replaced, as well as new asynchronous counterparts added.
| Core V8 classes | Equivalent V12 Class | NEW Asynchronous clients |
|---:|---:|---:|
| CloudStorageAccount | QueueServiceClientBuilder | QueueServiceClientBuilder |
| CloudQueueClient | QueueServiceClient | QueueServiceAsyncClient |
| CloudQueue & CloudQueueMessage | QueueClient | QueueAsyncClient |
## Updated Maven dependency
Dependency for Queue service:
```xml
com.azure
azure-storage-queue
12.0.0
```
## Build Client
In V8, core classes were built from `CloudStorageAccount` which authenticated with connection string.
```java
CloudStorageAccount storageAccount = CloudStorageAccount.parse("");
CloudQueue cloudQueue = storageAccount.createCloudQueueClient().getQueueReference("");
```
In V12, we have moved to a builder pattern. To replicate the above V8 snippet:
```java
// To get the QueueClient, we can use builder to initialize.
final QueueClient queueClient = new QueueClientBuilder()
.endpoint("https://" + "" + ".queue.core.windows.net")
.queueName("")
.credential(new StorageSharedKeyCredential("", ""))
.buildClient();
```
## Generate SAS token
SAS token generation has moved from helper classes to the core clients themselves.
See section [SAS Token](#sastoken) to learn how to use them as a credential.
Not all fields being set in these samples are necessary.
At minimum, only an expiry time and permission set are necessary to create a SAS.
In V8, to generate the SAS token, you needed to use `SharedAccessSignatureHelper` to fluently build out all it's options.
You also needed to provide `ServiceClient` which includes `SharedKeyCredential` to sign the token with.
```java
// Build the client
CloudStorageAccount storageAccount = CloudStorageAccount.parse("");
CloudQueue cloudQueue = storageAccount.createCloudQueueClient().getQueueReference("");
// Initialize the properties
String identifier = "identifier";
EnumSet permissions = EnumSet.of(
SharedAccessQueuePermissions.READ,
SharedAccessQueuePermissions.UPDATE,
SharedAccessQueuePermissions.ADD,
SharedAccessQueuePermissions.PROCESSMESSAGES);
IPRange ipR = new IPRange("0.0.0.0", "255.255.255.255");
Calendar calendar = Calendar.getInstance();
Date startDate = calendar.getTime();
calendar.add(Calendar.DAY_OF_YEAR, 1);
Date expiryDate = calendar.getTime();
SharedAccessQueuePolicy policy = new SharedAccessQueuePolicy();
policy.setPermissions(permissions);
policy.setSharedAccessStartTime(startDate);
policy.setSharedAccessExpiryTime(expiryDate);
// Build the token
String sasToken = cloudQueue.generateSharedAccessSignature(policy, identifier, ipR, SharedAccessProtocols.HTTPS_ONLY);
```
In V12, SAS tokens are generated off the client to the resource you wish to generate the SAS for.
The resource path handled automatically because of this, and the `SharedKeyCredential` authenticating the client is also used automatically to sign the SAS. See [building a client](#buildclient) for how to get an authenticated client.
```java
// specify token properties
String identifier = "identifier";
QueueSasPermission permissions = new QueueSasPermission()
.setReadPermission(true)
.setAddPermission(true)
.setProcessPermission(true)
.setUpdatePermission(true);
OffsetDateTime startTime = OffsetDateTime.now().minusDays(1);
OffsetDateTime expiryTime = OffsetDateTime.now().plusDays(1);
SasIpRange ipRange = new SasIpRange()
.setIpMax("0.0.0.0")
.setIpMax("255.255.255.255");
SasProtocol sasProtocol = SasProtocol.HTTPS_HTTP;
String version = ShareServiceVersion.V2019_02_02.getVersion();
// build the token
QueueServiceSasSignatureValues sasSignatureValues = new QueueServiceSasSignatureValues();
sasSignatureValues.setVersion(version)
.setProtocol(sasProtocol)
.setStartTime(startTime)
.setExpiryTime(expiryTime)
.setPermissions(permissions)
.setSasIpRange(ipRange)
.setIdentifier(identifier);
QueueServiceSasQueryParameters sasQueryParameters = sasSignatureValues.generateSasQueryParameters(new StorageSharedKeyCredential("", "");
```
In V12, our builders accept connection strings, no calls to `endpoint()` or `credential()` required. However, connection strings generally only point at the account, so you WILL need to specify queue name as necessary.
```java
QueueServiceClient client = new QueueServiceClientBuilder()
.connectionString("${connection-string}")
.buildClient();
```
### Shared key credential
Shared key credentials can be used directly to authenticate your client. You need to fetch the `${accountName}` and `${accountKey}` from Azure Portal.
Learn More from [README](https://github.com/Azure/azure-sdk-for-java/blob/azure-storage-queue_12.0.0/sdk/storage/azure-storage-queue/README.md)
In V8, you used the credential to build the `CloudStorageAccount`.
```java
// Initialize the credentials
StorageCredentialsAccountAndKey credential = new StorageCredentialsAccountAndKey("${accountName}", "${accountKey}");
// CloudStorageAccount take the credential.
CloudStorageAccount storageAccount = new CloudStorageAccount(credential);
```
Since the builder in V12 manages pipeline generation, you can just hand the `StorageSharedKeyCredential` to the builder.
```java
// Initialize the credentials
StorageSharedKeyCredential credential = new StorageSharedKeyCredential("${accountName}", "${accountKey}");
// How service object take in the credentials.
QueueServiceClient client = new QueueServiceClientBuilder()
.endpoint("https://" + "" + ".queue.core.windows.net")
.credential(credential)
.buildClient();
```
### SASToken
A URL with a SAS token looks like the following: `https://${accountName}.queue.core.windows.net/?${sasToken}`.
Refer the [documentation](https://github.com/Azure/azure-sdk-for-java/blob/azure-storage-queue_12.0.0/sdk/storage/azure-storage-queue/README.md) for more info.
See section [Generate SAS token](#generate-sas-token) for how to generate the token programmatically.
In V8, you had to sasToken string, which can paste from portal or generate from session above .
```java
// Here is how the blob object take in the sas token generated in above section [Generate SAS token](#generate-sas-token).
StorageCredentialsSharedAccessSignature credential = new StorageCredentialsSharedAccessSignature("sasToken");
CloudStorageAccount storageAccount = new CloudStorageAccount(credential);
```
In V12, SAS tokens can be managed just like any other credential.
```java
// How service object take in the credentials.
QueueServiceClient client = new QueueServiceClientBuilder()
.endpoint("https://${accountName}.queue.core.windows.net")
.sasToken("${sasToken}")
.buildClient();
```
However, if you already have the full URL with SAS token attached, you can use that too:
```java
QueueServiceClient client = new QueueServiceClientBuilder()
.endpoint("https://${accountName}.queue.core.windows.net/?${sasToken}")
.buildClient();
```
## Minimum Overload APIs and Maxmum Overload APIs:
In V8, we only provide many APIs overloads with the same return type.
```java
public QueueServiceProperties getProperties()
```
In V12, we provide at least one minimum and one maximum for most of the operations.
Minimum overload returns someType of `T` directly. Maximum overload returns response of someType `Response`
which includes the information of the headers, the request, status code, and the type value.
Minimum overload in async:
```java
public QueueServiceProperties getProperties()
```
Maximum overload in async:
```java
public Response getPropertiesWithResponse(Duration timeout, Context context)
```
Listing or Paging API returned `ResultSegment` in V8 which provided the continuation token and result list in `ResultSegment`.
List all queues V8:
```java
private CloudQueueClient queueClient;
private List retrieveQueuesForCurrentPage(ResultContinuation pageToken, List results) throws Exception {
if (pageToken == null) {
return results;
}
ResultSegment resultsNextPage = queueClient.listQueuesSegmented(null, QueueListingDetails.NONE, null, pageToken, null, null);
results.addAll(resultsNextPage.getResults());
retrieveQueuesForCurrentPage(resultsNextPage.getContinuationToken(), resultsNextPage.getResults());
return results;
}
public void run() throws Exception{
// Build CloudQueueClient
CloudStorageAccount storageAccount = CloudStorageAccount.parse("");
queueClient = new CloudQueueClient(storageAccount.getQueueStorageUri(), storageAccount.getCredentials());
// Initialize empty queue list
ResultSegment results = queueClient.listQueuesSegmented();
// Start from first page
retrieveQueuesForCurrentPage(results.getContinuationToken(), results.getResults());
}
```
V12 provides two pagination classes: `PagedIterable` for sync and `PageFlux` for async.
These allow you to consume listing operations by individual item or by response pages. The latter is needed to access general information in each HTTP response.
List all queues using sync API V12, by page:
```java
private QueueServiceClient queueServiceClient;
private List retrieveBlobs(String pageToken, List results) {
if (pageToken == null) {
return results;
}
queueServiceClient.listQueues().streamByPage(pageToken).forEach(
response -> {
results.addAll((Collection) response.getValue());
retrieveBlobs(response.getContinuationToken(), results);
}
);
return results;
}
public void run() {
// Build queueServiceClient
queueServiceClient = new QueueServiceClientBuilder().credential(new StorageSharedKeyCredential("", "")).buildClient();
// Initialize empty queue list
List results = new ArrayList<>();
// Start from first page
queueServiceClient.listQueues()
.streamByPage()
.forEach(response ->
{
results.addAll((Collection) response.getValue());
if (response.getContinuationToken() != null) {
results.addAll((Collection) retrieveBlobs(response.getContinuationToken(), results));
}
});
}
```