When performing I/O bound operation, the program should use asynchronous approach. This is particularly important when you access the Azure storage services. As of now, Azure managed libraries for .NET and Java do not support asynchronous APIs. Instead, by using underlying run time’s asynchronous programming approaches along with Azure storage services REST API makes you do I/O bound operations on Azure storage services.
In this post, I explain how to access Azure blob storage services asynchronously in Java. I have used following libraries:
The class “AzureStorage” contains the implementation to create HTTP request object for accessing the Azure RESTful resources.
123456789101112131415
publicclassAzureStorage...// fieldsStringstorageMedium;StringaccountName;byte[]secretKey;Stringhost;java.util.regex.PatternurlAbsolutePathPattern;//ctorAzureStorage(StringaccountName,StringstorageMedium,Stringbase64SecretKey)// public methodRequestget(StringresourcePath)// utility methodStringcreateAuthorizationHeader(Requestrequest)
The constructor requires storage account name, storage medium (this is neither Java nor Azure terminology, just identify whether you want to access blob, table or queue) and the primary shared key of the account. In this post, I just provide simple get() method for GET related Azure storage APIs. The input to the method is the resource path. Most the REST API requires authorization which in-turn sign the particular request by shared key. createAuthorizationHeader() method does this job.
The host field contains the part of base Azure storage URL. The primary shared key for the account has been converted to base 64 decoded byte array. Since, there is no AbsolutePath facility from an URL in Java world, I have used regular expression here. For example, the absolute path of the URL “https://myaccount.blob.core.windows.net/acontainer/?restype=container&comp=list” is “acontainer”.
The get() method
A HTTP request should be made to access a Azure storage with following details:
The above request specifies the URL for the resource, the REST API version, the request time stamp, authorization header. The get() method here frames these request headers. To want to know the complete details of request and response of Azure REST API, visit http://msdn.microsoft.com/en-us/library/windowsazure/dd179355.aspx.
The rfc1123Format is used to send request time stamp in RFC 1123 format as shown in the HTTP request. The below code snippet creates the com.ning.http.client.Request object.
The below code creates signed Authorization header.
123456789101112131415161718
StringauthHeader="";try{authHeader=createAuthorizationHeader(request);}catch(InvalidKeyExceptione){// TODO Auto-generated catch blocke.printStackTrace();}catch(UnsupportedEncodingExceptione){// TODO Auto-generated catch blocke.printStackTrace();}catch(NoSuchAlgorithmExceptione){// TODO Auto-generated catch blocke.printStackTrace();}request.getHeaders().add("Authorization","SharedKey "+this.accountName+":"+authHeader);returnrequest;
This part in-turn calls method createAuthorizationHeader().
For more details about this, visit: http://msdn.microsoft.com/en-us/library/windowsazure/dd179428.aspx
The above Java code adds the string starting from GET to Range. For this demonstration, I skipped most of the headers with newline and added only content-length and content-type headers. The below code constructs the CanonicalizedHeaders.
At the calling end, when you invoke the get() method, it returns the com.ning.http.client.Request instance. You can make request asynchronously using Ning’s async library as shown below
AzureStorageblobStorage=newAzureStorage("account-name","blob|table|queue","sharedkey");Requestrequest=blobStorage.get("ablobcontainer/?restype=container&comp=list");AsyncHttpClientclient=newAsyncHttpClient();ListenableFutureresponse=client.executeRequest(request,newAsyncHandler(){privatefinalResponse.ResponseBuilderbuilder=newResponse.ResponseBuilder();publicSTATEonBodyPartReceived(finalHttpResponseBodyPartcontent)throwsException{builder.accumulate(content);returnSTATE.CONTINUE;}publicSTATEonStatusReceived(finalHttpResponseStatusstatus)throwsException{builder.accumulate(status);returnSTATE.CONTINUE;}publicSTATEonHeadersReceived(finalHttpResponseHeadersheaders)throwsException{builder.accumulate(headers);returnSTATE.CONTINUE;}publicResponseonCompleted()throwsException{returnbuilder.build();}publicvoidonThrowable(Throwablearg0){// TODO Auto-generated method stub}});
Visit http://sonatype.github.com/async-http-client/request.html for more details about the above code. After that, you can do other computations. When you reach the place where you want the response for the asynchronous request, you can do the following:
1234567891011121314151617181920
// till here, there are other interesting computation donewhile(!response.isDone()){if(response.isCancelled())break;}ResponseactualResponse;try{actualResponse=response.get();System.out.println(actualResponse.getStatusCode());System.out.println(actualResponse.getResponseBody());}catch(InterruptedExceptione){// TODO Auto-generated catch blocke.printStackTrace();}catch(ExecutionExceptione){// TODO Auto-generated catch blocke.printStackTrace();}
The “while” part just wait for the asynchronous operation to be completed. After that, it processes the com.ning.http.client.Response instance.