//Cloud notes from my desk -Maheshk

"Fortunate are those who take the first steps.” ― Paulo Coelho

Accessing Azure Storage Services REST API

 

First of all, I am not a big fan of implementing Service REST API due to complexity in implementation over easiness with SDK. I would vouch for SDK’s instead going through this lengthy route until unless you have any business compelling reason. The reason is, it would be confusing for the beginners, lot of time spent on testing, lesser samples to refer and why reinvent the wheel. I would focus on the outcome rather going through some complex route of getting the things done.

– ——— C# sample code

static void Main(string[] args)
       {
           GetQueueMessageWithoutSDK(“newportalstorage”);
           Console.Read();
       }

       public static String CreateAuthorizationHeader(String canonicalizedString)
       {
           String signature = String.Empty;
           using (HMACSHA256 hmacSha256 = new HMACSHA256(Convert.FromBase64String(“your_primarykeyorsecondary”)))
           {
               Byte[] dataToHmac = System.Text.Encoding.UTF8.GetBytes(canonicalizedString);
               signature = Convert.ToBase64String(hmacSha256.ComputeHash(dataToHmac));
           }
           String authorizationHeader = String.Format(CultureInfo.InvariantCulture,”{0} {1}:{2}”,”SharedKey”,”newportalstorage”,signature);
           return authorizationHeader;
       }

      // get the queueservice name
       public static void GetQueueMessageWithoutSDK(String queueName)
       {
           string requestMethod = “GET”;
           String urlPath = String.Format(“{0}/messages”, “queuename”);
           String storageServiceVersion = “2012-02-12”;
           String dateInRfc1123Format = DateTime.UtcNow.ToString(“R”, CultureInfo.InvariantCulture);
           String canonicalizedHeaders = String.Format(“x-ms-date:{0}nx-ms-version:{1}”,dateInRfc1123Format,storageServiceVersion);
           String canonicalizedResource = String.Format(“/{0}/{1}”, queueName, urlPath);
           String stringToSign = String.Format(“{0}nnnnnnnnnnnn{1}n{2}”,requestMethod,canonicalizedHeaders,canonicalizedResource);
           String authorizationHeader = CreateAuthorizationHeader(stringToSign);
           Uri uri = new Uri(https://yourstorageaccountname.queue.core.windows.net/ + urlPath);
           HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
           request.Method = requestMethod;
           request.Headers.Add(“x-ms-date”, dateInRfc1123Format);
           request.Headers.Add(“x-ms-version”, storageServiceVersion);
           request.Headers.Add(“Authorization”, authorizationHeader);
           request.Headers.Add(HttpRequestHeader.AcceptCharset, “UTF-8”);
           request.Accept = “application/atom+xml,application/xml”;
           HttpWebResponse response = (HttpWebResponse)request.GetResponse();
           if (response != null
               && response.StatusCode != HttpStatusCode.Unauthorized
               && response.Headers[“Content-Type”] != null
               && response.Headers[“Content-Type”].Contains(“xml”))
           {
               StreamReader ResponseDataStream = new StreamReader(response.GetResponseStream());
               String res = ResponseDataStream.ReadToEnd();
               XmlDocument XMLDoc = new XmlDocument();
               XMLDoc.LoadXml(res);
               XmlNodeList word = XMLDoc.GetElementsByTagName(“MessageText”);
               var xmlNode = word.Item(0);
               if (xmlNode != null)
               {
                   string actualMessage=xmlNode.InnerText;
                   var base64EncodedBytes = Convert.FromBase64String(actualMessage);
                   string str= Encoding.UTF8.GetString(base64EncodedBytes);
                   //Actual queue message
                   Console.WriteLine(str);
               }
           }
       }
————————————————————————————————

Equivalent Java code:-

package testone;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;

import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;

public class storagedemohttp2 {

    static String key=”your_primary_key”;
    static String account=”your_accountname”;
   
    private static Base64 base64 ;
   
    private static String createAuthorizationHeader(String canonicalizedString) throws InvalidKeyException, Base64DecodingException, NoSuchAlgorithmException, IllegalStateException, UnsupportedEncodingException     { 
          Mac mac = Mac.getInstance(“HmacSHA256”); 
          mac.init(new SecretKeySpec(base64.decode(key), “HmacSHA256”)); 
          String authKey = new String(base64.encode(mac.doFinal(canonicalizedString.getBytes(“UTF-8”)))); 
          String authStr = “SharedKey ” + account + “:” + authKey; 
          return authStr; 
     }
   
    @SuppressWarnings(“deprecation”)
    public static void main(String[] args) throws IOException
    {
        String key=”RxKt6ZxB3+7R8dYHo70HCj+lNwQ5SBLryWVnWYbm8woK+dNd9p31bAbWOAXecVxtklHdZTyu7K/szi0geH31Kw==”;
        String account=”your_accountname”;
        String requestMethod = “GET”; 
        String urlPath = “yourqueue/messages”;
        String storageServiceVersion = “2012-02-12”;
        SimpleDateFormat fmt = new SimpleDateFormat(“EEE, dd MMM yyyy HH:mm:ss”); 
        fmt.setTimeZone(TimeZone.getTimeZone(“GMT”)); 
        String date = fmt.format(Calendar.getInstance().getTime()) + ” GMT”;
        String canonicalizedHeaders = “x-ms-date:”+date+”nx-ms-version:”+storageServiceVersion; 
        String canonicalizedResource = “/”+account+”/”+urlPath; 
        String stringToSign = requestMethod+”nnnnnnnnnnnn”+canonicalizedHeaders+”n”+canonicalizedResource;
       
        HttpURLConnection connection = null;
        try {
            String authorizationHeader = createAuthorizationHeader(stringToSign);
           
            URL myUrl = new URL(“https://newportalstorage.queue.core.windows.net/” + urlPath);

            connection=(HttpURLConnection)myUrl.openConnection();
           
            connection.setRequestProperty(“x-ms-date”, date);
            connection.setRequestProperty(“x-ms-version”, storageServiceVersion);
            connection.setRequestProperty(“Authorization”, authorizationHeader);
           
            connection.setDoOutput(true);
            connection.setDoInput(true);
            connection.setRequestMethod(“GET”);
              
            DataInputStream inStream = null;
           
            inStream = new DataInputStream(connection.getInputStream());
                  
            String buffer;
            while((buffer = inStream.readLine()) != null) {
                System.out.println(buffer);
            }
           
            // Close I/O streams
            inStream.close();

        } catch (Exception e) {
               DataInputStream errStream = new DataInputStream(connection.getErrorStream());
            String buffer;
            while((buffer = errStream.readLine()) != null) {
                System.out.println(buffer);
            }
            e.printStackTrace();
        } finally {
            connection.disconnect();
            //fs.close();
        }
        }
}

=============================

Useful links:-

Authentication for the Azure Storage Services

https://msdn.microsoft.com/en-us/library/azure/dd179428.aspx

Github dump >SharedAccessSignatureHelper.java

https://github.com/Azure/azure-storage-java/blob/21ed0379eaadcf849eb7795be3716aa1b9a4a375/microsoft-azure-storage/src/com/microsoft/azure/storage/core/SharedAccessSignatureHelper.java

Examples of the Windows Azure Storage Services REST API

https://dzone.com/articles/examples-windows-azure-storage  & https://convective.wordpress.com/2010/08/18/examples-of-the-windows-azure-storage-services-rest-api/

Let me know why you one have to choose this raw implementation over SDK’s and advantage? I understand, we can avoid bulky SDK references but interesting to hear the use case around this. Feel free to drop your comments on this. 

2016-09-07 Posted by | Azure, C#, Storage | | Leave a comment

How can I set a message to deadlettered – Service Bus

Today one of my colleague had an interesting problem in setting the SB Queue message as dead letter message. There are ton of sample around how to create DeadLetterQueue(DLQ) or move or read a DLQ message. But did not get a clear picture or documentation around “how one can set the message as Deadlettered through code”. As you know, messages would get automatically moved to DLQ after ‘n’ retry attempt or expiry but in this case he wanted to move it intentionally after some condition in code. For an example, when you see a body contains some text or invalid business code then I wanted to mark it as DeadLetter so that my other piece of code would drink it with recovery logic.

As usual, we started looking at our official documentation, Github pages, SB Explorer, internal discussion alias – there is lot of noise and confusion around in calling Receive/Defer/Deadletter but none gave a closest hint about marking a message as Deadletter. Spent almost couple of hours figuring out this 5 line of code Sad smile more importantly function call “order”. Failing to have this in order would give you hair pulling exception. So focus follow the “order”, say should mark it as Defer() before Receive() and then finally DeadLetter().

Microsoft.ServiceBus.Messaging.MessageNotFoundException was unhandled
  HResult=-2146233088 IsTransient=false
  Message=Failed to lock one or more specified messages. The message does not exist. TrackingId:2d6fb843-0bd8-4b73-9fc0-8f9bffe98ca7_G0_B0, SystemTracker:xxxxxx:QueueXXX, Timestamp:9/2/2016 7:34:42 PM
 

 

//Sample code to receive a message with sequence number and then Deadletter

using Microsoft.ServiceBus.Messaging;

static void Main(string[] args)

        {

var queue = QueueClient.CreateFromConnectionString(“Endpoint=sb://xxx.servicebus.windows.net/;SharedAccessKeyName=RootManageSharedAccessKey;SharedAccessKey=xxxx=”, “queuename”, ReceiveMode.PeekLock);

           BrokeredMessage msg = queue.Receive();

            msg.Defer();

            msg = queue.Receive(msg.SequenceNumber);

            msg.DeadLetter();

        }

Let me know if you think there is a better way than this.

good weekend !

2016-09-03 Posted by | .NET, Azure Dev, PaaS, ServiceBus | | Leave a comment